Swift null safety questions


(Elijah Johnson) #1

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah


(Elijah Johnson) #2

Additionally, not discarding previous comments, one way the language could
be improved is by replacing (or rather augmenting) optional binding with a
faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a
re-definition of variables and an additional “if” operator. Besides the
extra characters involved in typing and reading it, usually variables have
specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly
and requires refractoring) is one thing that still makes forced unwrapping
still very much a necessary or common part of Swift coding, even where it
could be replaced with optional binding.

···

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah


(Joe Groff) #3

The long-term vision here is to have some form of finer-grained fault isolation ("actors" being the buzzword for that we tend to throw around). As others noted, using `!` is intended to indicate that it is *impossible* for a value to be nil at a certain point, and that the programmers screwed up if the value is nil at that point. The only safe thing to do in a situation the programmers didn't plan for is stop execution; anything else is just going to lead to harder-to-debug, potentially-exploitable inconsistencies further removed from the original problem. With actors, it could become possible for that crash to only take down an isolated subprogram, and give a supervisor subprogram an opportunity to gracefully wind down the process—on clients, this might mean saving application state so that the app can be cleanly restarted, and on the server, this might mean closing the process's accept socket but still letting existing requests complete before restarting the potentially-compromised process. There's still a tradeoff here from a defense-in-depth standpoint, since any requests running in the same process have the potential to corrupt each other's state. Swift's crash-early design hopes to minimize the opportunity for corruption to leak.

-Joe

···

On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.


(Austin Zheng) #4

Swift already is an unmanaged language, and is far closer to C++ than Java.
There is no equivalent to the CLR or JVM and it is trivially easy to call
into C code or the unsafe APIs and do nearly anything that C can do with
regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime
exception. Instead, it is an assertion which indicates a programmer logic
error. The preferred way to handle an optional at runtime has always been
to use the conditional-unwrapping functionality the language offers. The
correct way to report errors at runtime that aren't due to programmer error
is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is
a project management and/or developer competence issue, and not something
the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly
rejected proposals list:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

···

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Additionally, not discarding previous comments, one way the language could
be improved is by replacing (or rather augmenting) optional binding with a
faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a
re-definition of variables and an additional “if” operator. Besides the
extra characters involved in typing and reading it, usually variables have
specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly
and requires refractoring) is one thing that still makes forced unwrapping
still very much a necessary or common part of Swift coding, even where it
could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matthew Johnson) #5

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.

The long-term vision here is to have some form of finer-grained fault isolation ("actors" being the buzzword for that we tend to throw around). As others noted, using `!` is intended to indicate that it is *impossible* for a value to be nil at a certain point, and that the programmers screwed up if the value is nil at that point. The only safe thing to do in a situation the programmers didn't plan for is stop execution; anything else is just going to lead to harder-to-debug, potentially-exploitable inconsistencies further removed from the original problem. With actors, it could become possible for that crash to only take down an isolated subprogram, and give a supervisor subprogram an opportunity to gracefully wind down the process—on clients, this might mean saving application state so that the app can be cleanly restarted, and on the server, this might mean closing the process's accept socket but still letting existing requests complete before restarting the potentially-compromised process. There's still a tradeoff here from a defense-in-depth standpoint, since any requests running in the same process have the potential to corrupt each other's state. Swift's crash-early design hopes to minimize the opportunity for corruption to leak.

Wouldn’t it also be possible to support isolated execution contexts which can be statically verified to only mutate state that no other part of the process can see? This would allow the process itself (and other execution contexts in the process) to continue running without risk of corrupted state. This seems like an approach that would work well for server processes that can handle requests in isolation.

···

On Mar 22, 2017, at 12:03 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

-Joe

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Elijah Johnson) #6

Hi,

Note that this thread has branched off a bit, so my latest proposal and the
“head” of this thread can be found at
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html

Can you give an example of this corruption which would be exploitable in a
web server context? An example where, having caught the force-unwrap or
other precondition fatalError, that the web server would face more danger
from continued execution that it would loose by crashing?

The optional has been triggered, the request has been stopped, and incoming
requests are going to a new process, but there are a few threads open still
finishing what they were doing - I’d like to see a good example of the
danger caused by a real “inconsistency”. Lets assume also that all objects
shared between threads are Swift objects and not “UnsafePointers”, which is
a very fair assumtion for a web server. Java even allows native access and
they don’t even crash there. I’m sorry, but I completely fail to grasp the
danger as being > crashing.

As for “hard to debug” errors, providing a stack trace and logging it,
stopping the one request that caused it, is sufficient for debugging a
production environment.

I’d be interested to know who these web server developers (ex. Kitura,
Vapor) are targeting without any form of crash handling and if they read
these threads. It really limits the pool of developers more so than on apps
because a single crash on the app ie equivelant to a failed request, not a
crashed web server. I realize you are not competing with Java, but I do not
see yet the compelling reason for no crash handling.

The “actors” with thread pool and proccesses is one idea, but I think these
servers are aiming also for speed and scaleability - don’t know if they
would accept this model. I know that it does get used, and do work for a
company that uses it on their backend (just plain Java, not sep.
processes). Their front-end probably runs like a pre-fork server, but Java
is so stable that there is simply no need for that.

···

On March 22, 2017 at 1:03:42 PM, Joe Groff (jgroff@apple.com) wrote:

On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

The long-term vision here is to have some form of finer-grained fault
isolation ("actors" being the buzzword for that we tend to throw around).
As others noted, using `!` is intended to indicate that it is *impossible*
for a value to be nil at a certain point, and that the programmers screwed
up if the value is nil at that point. The only safe thing to do in a
situation the programmers didn't plan for is stop execution; anything else
is just going to lead to harder-to-debug, potentially-exploitable
inconsistencies further removed from the original problem. With actors, it
could become possible for that crash to only take down an isolated
subprogram, and give a supervisor subprogram an opportunity to gracefully
wind down the process—on clients, this might mean saving application state
so that the app can be cleanly restarted, and on the server, this might
mean closing the process's accept socket but still letting existing
requests complete before restarting the potentially-compromised process.
There's still a tradeoff here from a defense-in-depth standpoint, since any
requests running in the same process have the potential to corrupt each
other's state. Swift's crash-early design hopes to minimize the opportunity
for corruption to leak.

-Joe


(Elijah Thomas Johnson) #7

Well, I think that it is far more ingrained into the language and its daily
use than you might realize.

At the very least, someone should correct the XCode warning that says (to
paraphrase) “code does not comple, double click to insert optional here”
and create some code-analysis warnings against the practice of forced
unwrap where it can be replaced.

I’ve been a full year with Swift now, and just a week or two ago I learned
about this optional binding feature. You could say I’m not devoted enough,
but I’ve not had any crashing issues, XCode just told me to insert
force-unwrap and thats what I did.

If this whole “force-unwrap” thing isn’t the intended way of doing things,
that could be made a bit more explicit I think.

Here’s a screenshot of what I am referring to: https://snag.gy/dH6twR.jpg

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

Xcode might not be in the Swift evolution domain, but I think the idea of
warnings for "unnecessary use of !” are.

Swift already is an unmanaged language, and is far closer to C++ than Java.
There is no equivalent to the CLR or JVM and it is trivially easy to call
into C code or the unsafe APIs and do nearly anything that C can do with
regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime
exception. Instead, it is an assertion which indicates a programmer logic
error. The preferred way to handle an optional at runtime has always been
to use the conditional-unwrapping functionality the language offers. The
correct way to report errors at runtime that aren't due to programmer error
is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is
a project management and/or developer competence issue, and not something
the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly
rejected proposals list:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

···

On March 6, 2017 at 9:47:04 PM, Austin Zheng (austinzheng@gmail.com) wrote:

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Additionally, not discarding previous comments, one way the language could
be improved is by replacing (or rather augmenting) optional binding with a
faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a
re-definition of variables and an additional “if” operator. Besides the
extra characters involved in typing and reading it, usually variables have
specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly
and requires refractoring) is one thing that still makes forced unwrapping
still very much a necessary or common part of Swift coding, even where it
could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Elijah Johnson) #8

The problem for using Swift on the server is one of these optionals (or
array index out of bounds error, or cast from Int to UInt error) would
crash the entire server directing many requests. Granted, thats not Apple’s
busininess, but it is pretty much standad in a modern webserver never to
crash, and whoever is developing servers will find they don’t have the
necessary power to do that. Some languages like PHP have a unique process
per-request style, but that phrohibits shared data. One could do the same
with Swift, but it would be a major loss.

Just because Swift is not garbage collected doesn’t mean that you can’t
safely unwind the stack and continue execution somewhere. If “bad”
developers would start using this as unwanted exceptions, then it can be
made inconvient somehow.

Think about a server that handles 1,000 requests per minute - its going to
happen evenutally, even despite testing, and chances are that once it
happens it will re-occur - and now the server goes down every minute or
even every few seconds and needs an auto-restart loop.

If we’re going to be talking about “bad developers” as in ones who might
once code a bug with an optional or index out of bounds exception, then
that is going to be a very high standard and result in a very mild adoption
of server side Swift. Maybe it would take off for a while, and then when
people realize these things, they will say “thats why everyone writes their
server-side code in Java/C#/PHP, etc” and Swift will be a thing for people
who need ultra-fast performance on a server.

Its not really Apple’s business, and clearly you are trying to replace only
C++ and not Java/C#, but if you can add a compiler mode with exceptions
instead of fatalError(mesage:) calls, that would contribute a lot to making
web servers with Swift. Even if you leak the entire call stack, it would
still be better than crashing an entire web serer.

Swift already is an unmanaged language, and is far closer to C++ than Java.
There is no equivalent to the CLR or JVM and it is trivially easy to call
into C code or the unsafe APIs and do nearly anything that C can do with
regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime
exception. Instead, it is an assertion which indicates a programmer logic
error. The preferred way to handle an optional at runtime has always been
to use the conditional-unwrapping functionality the language offers. The
correct way to report errors at runtime that aren't due to programmer error
is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is
a project management and/or developer competence issue, and not something
the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly
rejected proposals list:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

···

On March 6, 2017 at 9:47:03 PM, Austin Zheng (austinzheng@gmail.com) wrote:

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Additionally, not discarding previous comments, one way the language could
be improved is by replacing (or rather augmenting) optional binding with a
faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a
re-definition of variables and an additional “if” operator. Besides the
extra characters involved in typing and reading it, usually variables have
specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly
and requires refractoring) is one thing that still makes forced unwrapping
still very much a necessary or common part of Swift coding, even where it
could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Joe Groff) #9

That would be the ideal. Any channel of communication, including a crash signal, is still a potential vector for attack against a weak supervisor, depending on how flexible that channel is. It's certainly much less likely for this form of corruption to occur in a well-isolated runtime model with regulated communication channels among components, and in practice there will hopefully be off-the-shelf runtimes you can plug in to.

-Joe

···

On Mar 22, 2017, at 10:09 AM, Matthew Johnson <matthew@anandabits.com> wrote:

On Mar 22, 2017, at 12:03 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.

The long-term vision here is to have some form of finer-grained fault isolation ("actors" being the buzzword for that we tend to throw around). As others noted, using `!` is intended to indicate that it is *impossible* for a value to be nil at a certain point, and that the programmers screwed up if the value is nil at that point. The only safe thing to do in a situation the programmers didn't plan for is stop execution; anything else is just going to lead to harder-to-debug, potentially-exploitable inconsistencies further removed from the original problem. With actors, it could become possible for that crash to only take down an isolated subprogram, and give a supervisor subprogram an opportunity to gracefully wind down the process—on clients, this might mean saving application state so that the app can be cleanly restarted, and on the server, this might mean closing the process's accept socket but still letting existing requests complete before restarting the potentially-compromised process. There's still a tradeoff here from a defense-in-depth standpoint, since any requests running in the same process have the potential to corrupt each other's state. Swift's crash-early design hopes to minimize the opportunity for corruption to leak.

Wouldn’t it also be possible to support isolated execution contexts which can be statically verified to only mutate state that no other part of the process can see? This would allow the process itself (and other execution contexts in the process) to continue running without risk of corrupted state. This seems like an approach that would work well for server processes that can handle requests in isolation.


(Elijah Johnson) #10

TLDR version, I would check with the developers of Swift web servers
(Vapor, Kitura, etc) if this is their actual plan also to re-work their
webserver using actors and processes instead of threads. I’m not writing a
webserver myself, so that is what it should come down to. Right now, if you
unwrap an optional, it crashes their entire server. It just seems
thoughtless to me.

···

On March 22, 2017 at 7:07:04 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

Note that this thread has branched off a bit, so my latest proposal and the
“head” of this thread can be found at
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html

Can you give an example of this corruption which would be exploitable in a
web server context? An example where, having caught the force-unwrap or
other precondition fatalError, that the web server would face more danger
from continued execution that it would loose by crashing?

The optional has been triggered, the request has been stopped, and incoming
requests are going to a new process, but there are a few threads open still
finishing what they were doing - I’d like to see a good example of the
danger caused by a real “inconsistency”. Lets assume also that all objects
shared between threads are Swift objects and not “UnsafePointers”, which is
a very fair assumtion for a web server. Java even allows native access and
they don’t even crash there. I’m sorry, but I completely fail to grasp the
danger as being > crashing.

As for “hard to debug” errors, providing a stack trace and logging it,
stopping the one request that caused it, is sufficient for debugging a
production environment.

I’d be interested to know who these web server developers (ex. Kitura,
Vapor) are targeting without any form of crash handling and if they read
these threads. It really limits the pool of developers more so than on apps
because a single crash on the app ie equivelant to a failed request, not a
crashed web server. I realize you are not competing with Java, but I do not
see yet the compelling reason for no crash handling.

The “actors” with thread pool and proccesses is one idea, but I think these
servers are aiming also for speed and scaleability - don’t know if they
would accept this model. I know that it does get used, and do work for a
company that uses it on their backend (just plain Java, not sep.
processes). Their front-end probably runs like a pre-fork server, but Java
is so stable that there is simply no need for that.

On March 22, 2017 at 1:03:42 PM, Joe Groff (jgroff@apple.com) wrote:

On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

The long-term vision here is to have some form of finer-grained fault
isolation ("actors" being the buzzword for that we tend to throw around).
As others noted, using `!` is intended to indicate that it is *impossible*
for a value to be nil at a certain point, and that the programmers screwed
up if the value is nil at that point. The only safe thing to do in a
situation the programmers didn't plan for is stop execution; anything else
is just going to lead to harder-to-debug, potentially-exploitable
inconsistencies further removed from the original problem. With actors, it
could become possible for that crash to only take down an isolated
subprogram, and give a supervisor subprogram an opportunity to gracefully
wind down the process—on clients, this might mean saving application state
so that the app can be cleanly restarted, and on the server, this might
mean closing the process's accept socket but still letting existing
requests complete before restarting the potentially-compromised process.
There's still a tradeoff here from a defense-in-depth standpoint, since any
requests running in the same process have the potential to corrupt each
other's state. Swift's crash-early design hopes to minimize the opportunity
for corruption to leak.

-Joe


(Joe Groff) #11

Hi,

Note that this thread has branched off a bit, so my latest proposal and the “head” of this thread can be found at https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html

Can you give an example of this corruption which would be exploitable in a web server context? An example where, having caught the force-unwrap or other precondition fatalError, that the web server would face more danger from continued execution that it would loose by crashing?

The optional has been triggered, the request has been stopped, and incoming requests are going to a new process, but there are a few threads open still finishing what they were doing - I’d like to see a good example of the danger caused by a real “inconsistency”. Lets assume also that all objects shared between threads are Swift objects and not “UnsafePointers”, which is a very fair assumtion for a web server. Java even allows native access and they don’t even crash there.

When considering security threats, we have to take the presence of an exploit as given until we prove otherwise. A precondition failure indicates a logic error somewhere in the program, and while safe Swift abstractions are intended not to lead to memory unsafety in the face of precondition failures, there's plenty of relatively young, unsafe code below the hood in the implementations of those abstractions, written by humans who make mistakes. Whatever lurking security bugs there may be, they're more likely to be exploitable if you're already in a situation where assumptions have been violated.

I’m sorry, but I completely fail to grasp the danger as being > crashing.

Crashing is inconvenient. The user may have to retry their request or relaunch their app. Security breaches or data corruption are disasters that can have unbounded impact and cost—you can't undisclose sensitive data.

I’d be interested to know who these web server developers (ex. Kitura, Vapor) are targeting without any form of crash handling and if they read these threads. It really limits the pool of developers more so than on apps because a single crash on the app ie equivelant to a failed request, not a crashed web server. I realize you are not competing with Java, but I do not see yet the compelling reason for no crash handling.

The “actors” with thread pool and proccesses is one idea, but I think these servers are aiming also for speed and scaleability - don’t know if they would accept this model. I know that it does get used, and do work for a company that uses it on their backend (just plain Java, not sep. processes). Their front-end probably runs like a pre-fork server, but Java is so stable that there is simply no need for that.

You can use processes for fault isolation today, and that will have some cost. At Swift's current maturity level, that's really probably the only responsible isolation strategy. The goal of "actors" would be to get most of the benefits of processes through language-level isolation without paying the full cost of processes.

-Joe

···

On Mar 22, 2017, at 4:07 PM, Elijah Johnson <ejrx7753@gmail.com> wrote:


(Austin Zheng) #12

I've worked on several large Swift codebases for large, prominent companies and use of '!' was extremely rare and highly discouraged. It showed up most frequently as the type for @IBOutlet properties, which would not be relevant when programming a server application.

I completely agree with you that the Xcode fix-it is terrible and should be removed or replaced, but unfortunately it's been made clear that changes to Xcode are outside the purview of swift-evolution. You should definitely file a Radar, though.

Best,
Austin

···

On Mar 6, 2017, at 7:52 PM, Elijah Thomas Johnson <tomac120@gmail.com> wrote:

Well, I think that it is far more ingrained into the language and its daily use than you might realize.

At the very least, someone should correct the XCode warning that says (to paraphrase) “code does not comple, double click to insert optional here” and create some code-analysis warnings against the practice of forced unwrap where it can be replaced.

I’ve been a full year with Swift now, and just a week or two ago I learned about this optional binding feature. You could say I’m not devoted enough, but I’ve not had any crashing issues, XCode just told me to insert force-unwrap and thats what I did.

If this whole “force-unwrap” thing isn’t the intended way of doing things, that could be made a bit more explicit I think.

Here’s a screenshot of what I am referring to: https://snag.gy/dH6twR.jpg

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

Xcode might not be in the Swift evolution domain, but I think the idea of warnings for "unnecessary use of !” are.

On March 6, 2017 at 9:47:04 PM, Austin Zheng (austinzheng@gmail.com <mailto:austinzheng@gmail.com>) wrote:

Swift already is an unmanaged language, and is far closer to C++ than Java. There is no equivalent to the CLR or JVM and it is trivially easy to call into C code or the unsafe APIs and do nearly anything that C can do with regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime exception. Instead, it is an assertion which indicates a programmer logic error. The preferred way to handle an optional at runtime has always been to use the conditional-unwrapping functionality the language offers. The correct way to report errors at runtime that aren't due to programmer error is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is a project management and/or developer competence issue, and not something the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly rejected proposals list: https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Additionally, not discarding previous comments, one way the language could be improved is by replacing (or rather augmenting) optional binding with a faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a re-definition of variables and an additional “if” operator. Besides the extra characters involved in typing and reading it, usually variables have specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly and requires refractoring) is one thing that still makes forced unwrapping still very much a necessary or common part of Swift coding, even where it could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com <mailto:ejrx7753@gmail.com>) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Josh Parmenter) #13

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

I agree with this in general. I tell people that I’m teaching that unwrapping uses ‘!' for a reason. It should scream at you that something is happening that probably needs more careful attention.

Best,
Josh

Joshua Parmenter | Engineering Lead, Apple Technologies

T 248 777 7777
C 206 437 1551
F 248 616 1980
www.vectorform.com<http://www.vectorform.com/>

Vectorform
2107 Elliott Ave Suite 303
Seattle, WA 98121 USA

Think Tank. Lab. Studio.
We invent digital products and experiences.

SEATTLE | DETROIT | NEW YORK | MUNICH | HYDERABAD

···

On Mar 6, 2017, at 7:52 PM, Elijah Thomas Johnson via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:


(Austin Zheng) #14

If you want improved error handling, feel free to put together a proposal once Swift 4 phase 2 is over. A good proposal should take into account the reasons Swift's error handling was designed as it currently is (https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst)

Otherwise, if you really need to build a web server framework that can swallow any sort of application logic without choking, perhaps Swift as it currently stands isn't the best tool for the job.

Best,
Austin

···

On Mar 12, 2017, at 12:06 PM, Elijah Johnson <ejrx7753@gmail.com> wrote:

The problem for using Swift on the server is one of these optionals (or array index out of bounds error, or cast from Int to UInt error) would crash the entire server directing many requests. Granted, thats not Apple’s busininess, but it is pretty much standad in a modern webserver never to crash, and whoever is developing servers will find they don’t have the necessary power to do that. Some languages like PHP have a unique process per-request style, but that phrohibits shared data. One could do the same with Swift, but it would be a major loss.

Just because Swift is not garbage collected doesn’t mean that you can’t safely unwind the stack and continue execution somewhere. If “bad” developers would start using this as unwanted exceptions, then it can be made inconvient somehow.

Think about a server that handles 1,000 requests per minute - its going to happen evenutally, even despite testing, and chances are that once it happens it will re-occur - and now the server goes down every minute or even every few seconds and needs an auto-restart loop.

If we’re going to be talking about “bad developers” as in ones who might once code a bug with an optional or index out of bounds exception, then that is going to be a very high standard and result in a very mild adoption of server side Swift. Maybe it would take off for a while, and then when people realize these things, they will say “thats why everyone writes their server-side code in Java/C#/PHP, etc” and Swift will be a thing for people who need ultra-fast performance on a server.

Its not really Apple’s business, and clearly you are trying to replace only C++ and not Java/C#, but if you can add a compiler mode with exceptions instead of fatalError(mesage:) calls, that would contribute a lot to making web servers with Swift. Even if you leak the entire call stack, it would still be better than crashing an entire web serer.

On March 6, 2017 at 9:47:03 PM, Austin Zheng (austinzheng@gmail.com <mailto:austinzheng@gmail.com>) wrote:

Swift already is an unmanaged language, and is far closer to C++ than Java. There is no equivalent to the CLR or JVM and it is trivially easy to call into C code or the unsafe APIs and do nearly anything that C can do with regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime exception. Instead, it is an assertion which indicates a programmer logic error. The preferred way to handle an optional at runtime has always been to use the conditional-unwrapping functionality the language offers. The correct way to report errors at runtime that aren't due to programmer error is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is a project management and/or developer competence issue, and not something the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly rejected proposals list: https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Additionally, not discarding previous comments, one way the language could be improved is by replacing (or rather augmenting) optional binding with a faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a re-definition of variables and an additional “if” operator. Besides the extra characters involved in typing and reading it, usually variables have specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly and requires refractoring) is one thing that still makes forced unwrapping still very much a necessary or common part of Swift coding, even where it could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com <mailto:ejrx7753@gmail.com>) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Elijah Johnson) #15

Hi,

Note that this thread has branched off a bit, so my latest proposal and

the “head” of this thread can be found at
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html

Can you give an example of this corruption which would be exploitable in

a web server context? An example where, having caught the force-unwrap or
other precondition fatalError, that the web server would face more danger
from continued execution that it would loose by crashing?

The optional has been triggered, the request has been stopped, and

incoming requests are going to a new process, but there are a few threads
open still finishing what they were doing - I’d like to see a good example
of the danger caused by a real “inconsistency”. Lets assume also that all
objects shared between threads are Swift objects and not “UnsafePointers”,
which is a very fair assumtion for a web server. Java even allows native
access and they don’t even crash there.

When considering security threats, we have to take the presence of an
exploit as given until we prove otherwise. A precondition failure indicates
a logic error somewhere in the program, and while safe Swift abstractions
are intended not to lead to memory unsafety in the face of precondition
failures, there's plenty of relatively young, unsafe code below the hood in
the implementations of those abstractions, written by humans who make
mistakes. Whatever lurking security bugs there may be, they're more likely
to be exploitable if you're already in a situation where assumptions have
been violated.

I’m sorry, but I completely fail to grasp the danger as being > crashing.

Crashing is inconvenient. The user may have to retry their request or
relaunch their app. Security breaches or data corruption are disasters that
can have unbounded impact and cost—you can't undisclose sensitive data.

I’d be interested to know who these web server developers (ex. Kitura,

Vapor) are targeting without any form of crash handling and if they read
these threads. It really limits the pool of developers more so than on apps
because a single crash on the app ie equivelant to a failed request, not a
crashed web server. I realize you are not competing with Java, but I do not
see yet the compelling reason for no crash handling.

The “actors” with thread pool and proccesses is one idea, but I think

these servers are aiming also for speed and scaleability - don’t know if
they would accept this model. I know that it does get used, and do work for
a company that uses it on their backend (just plain Java, not sep.
processes). Their front-end probably runs like a pre-fork server, but Java
is so stable that there is simply no need for that.

You can use processes for fault isolation today, and that will have some
cost. At Swift's current maturity level, that's really probably the only
responsible isolation strategy. The goal of "actors" would be to get most
of the benefits of processes through language-level isolation without
paying the full cost of processes.

-Joe

I have no personal objection to actors or processes or anything else. I
would just emphasize that the webservers in existence for Swift (and quite
well funded) are right now on a “crash the whole thing” model AFAIK. I
don’t know if they will be able to get by with catching all the
precondition failures in testing - maybe they will - maybe not, but I see
people either wisely turning down Swift for web development or getting
their first crash as a “zero-day” system down event where some guy has to
ssh in and actually start the server back up.

But whatever the fix is, or nothing, they (developers of Perfect, Kitura,
Vapor, etc) will have to like it and implement it. If they’re not
interested, I’m not starting a development company to compete. And also the
development time is so short on my idea that you basically just have to
approve it and the development time for it is hours not months or years.
Just add a fatalError function override and any c developer could have it
done in minutes like this guy https://github.com/ankurp/unsafe-swift (not
endorsing the post, just showing evidence that setjmp and longjmp work fine
with swift).

···

On March 22, 2017 at 8:41:25 PM, Joe Groff (jgroff@apple.com) wrote:

On Mar 22, 2017, at 4:07 PM, Elijah Johnson <ejrx7753@gmail.com> wrote:


(Chris Lattner) #16

FYI, this fixit is entirely generated by the swift compiler, not Xcode. The swift compiler is fully open source and generally welcomes well formed patches.

-Chris

···

On Mar 6, 2017, at 7:57 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

I've worked on several large Swift codebases for large, prominent companies and use of '!' was extremely rare and highly discouraged. It showed up most frequently as the type for @IBOutlet properties, which would not be relevant when programming a server application.

I completely agree with you that the Xcode fix-it is terrible and should be removed or replaced, but unfortunately it's been made clear that changes to Xcode are outside the purview of swift-evolution. You should definitely file a Radar, though.


(Elijah Johnson) #17

Well, I do believe the warnings that show up in Xcode come from the Swift compiler itself. In the case where you have a line

test(a: n!);

then it should be trivial at least in that case to emit a warning.

Apple’s radar is a no-go for me, still wating months on a segmentation fault issue with Swift 3. They just lumped them all together and closed all the issues. I opened up a new ticket the same day with reproducible scenario and haven’t heard from them. No problem though, as I’m nearly finished re-writing our code base function by function :slight_smile: . That kind of thing (fixing the Fix-its) needs to come internally.

···

On March 6, 2017 at 10:57:04 PM, Austin Zheng (austinzheng@gmail.com) wrote:

I've worked on several large Swift codebases for large, prominent companies and use of '!' was extremely rare and highly discouraged. It showed up most frequently as the type for @IBOutlet properties, which would not be relevant when programming a server application.

I completely agree with you that the Xcode fix-it is terrible and should be removed or replaced, but unfortunately it's been made clear that changes to Xcode are outside the purview of swift-evolution. You should definitely file a Radar, though.

Best,
Austin

On Mar 6, 2017, at 7:52 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org> wrote::

Well, I think that it is far more ingrained into the language and its daily use than you might realize.

At the very least, someone should correct the XCode warning that says (to paraphrase) “code does not comple, double click to insert optional here” and create some code-analysis warnings against the practice of forced unwrap where it can be replaced.

I’ve been a full year with Swift now, and just a week or two ago I learned about this optional binding feature. You could say I’m not devoted enough, but I’ve not had any crashing issues, XCode just told me to insert force-unwrap and thats what I did.

If this whole “force-unwrap” thing isn’t the intended way of doing things, that could be made a bit more explicit I think.

Here’s a screenshot of what I am referring to: https://snag.gy/dH6twR.jpg

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

Xcode might not be in the Swift evolution domain, but I think the idea of warnings for "unnecessary use of !” are.

On March 6, 2017 at 9:47:04 PM, Austin Zheng (austinzheng@gmail.com) wrote:
Swift already is an unmanaged language, and is far closer to C++ than Java. There is no equivalent to the CLR or JVM and it is trivially easy to call into C code or the unsafe APIs and do nearly anything that C can do with regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime exception. Instead, it is an assertion which indicates a programmer logic error. The preferred way to handle an optional at runtime has always been to use the conditional-unwrapping functionality the language offers. The correct way to report errors at runtime that aren't due to programmer error is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is a project management and/or developer competence issue, and not something the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly rejected proposals list: https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution <swift-evolution@swift.org> wrote:
Additionally, not discarding previous comments, one way the language could be improved is by replacing (or rather augmenting) optional binding with a faster syntax.

ex.

func test( name : String?, name2 :String? ){
name! , name2! {
// inside this block, “name” and “name2” are non-optional
} else {
// no forced unwrapping, just optional else case
}
}

Whereas the alternative (current optional binding), requires a re-definition of variables and an additional “if” operator. Besides the extra characters involved in typing and reading it, usually variables have specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
if let nameUnwrapped = name , let name2Unwrapped = name2 {

\} else \{

}
}

func test( name : String?, name2 :String? ){
guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

\}

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly and requires refractoring) is one thing that still makes forced unwrapping still very much a necessary or common part of Swift coding, even where it could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up the question, “what happens when a null optional is forcibly unwrapped?” and the answer was clearly that not only would the request crash, but the entire server would also crash, since the server itself is/would be also written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety” attempts. The first is that there needs to be a way to isolate blocks of code so that a “null pointer exception” does not crash the system. I think it is fair to say, in the language of Java, that these are really “runtime exceptions” and for some reason are being treated as segmentation faults would be in C/C++. In my opinion, the existence of these things has the ability to bring Swift down below Java and closer to an unamanged language. Not really sure why it would ever be desireable, but in terms of server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these “force-unwrap” errors. I agree with the usage of new language features like guard, optional binding, etc to remove a null value, but I see this force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a mistake are a rational for making better coders. In fact, I personally see the “force-unwrap” operator having very great potential usage as a deliberate assertion exception - the programmer demands that a certain value be non-null for execution to continue, only there should be a proper scope and context where these exceptions can propogate to. On debug modes, one might want it to pause on the line, but for other uses, it should be caught IMO - on regular code by the user, and inside dispatch blocks by the queue itself. For a multithreaded app or server to exit, the user should have to explicitly write exit(0), isn’t this the goal of a managed language? Maybe in some cases, Apple will want the program to crash, but if Swift is given an audience not just with Apple hardware, then it should have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Elijah Johnson) #18

How about the proposal of warnings and/or fix-it for unnecessary use of
optionals?

It seems to me though, that there aren't too many "necessary" uses for
forced-unwrapping. Judging from (
https://github.com/apple/swift-evolution/blob/master/proposals/0054-abolish-iuo.md),
it was probably added as a way of helping work with Obj-C also.

func test(a:String?) -> String {
    return a!
}

is equivelent to

func test(a:String?) -> String {
    if let a = a {
         print(a);
    } else {
         fatalError();
    }
}

I wouldn't remove it at this stage, but to quote (
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md),
it is "favoring terseness over clarity by introducing new magic syntactic
sugar," ironically adding this very terse and easy syntax for the coding
style that we do not want to incentivize.

Adding warnings and a fix-it to make the crash explicit would more or less
be as good as removing forced-unwrap from the language. Just maybe needs
some clarification of what exactly is a valid use of the force-unwrap.
Maybe for interop with Obj-C it should be considered "necessary", for
example.

···

2017-03-07 11:54 GMT-05:00 Josh Parmenter <jparmenter@vectorform.com>:

On Mar 6, 2017, at 7:52 PM, Elijah Johnson via swift-evolution < > swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

I agree with this in general. I tell people that I’m teaching that
unwrapping uses ‘!' for a reason. It should scream at you that something is
happening that probably needs more careful attention.

Best,
Josh

Joshua Parmenter | Engineering Lead, Apple Technologies

T 248 777 7777
C 206 437 1551
F 248 616 1980
www.vectorform.com<http://www.vectorform.com/>

Vectorform
2107 Elliott Ave Suite 303
Seattle, WA 98121 USA

Think Tank. Lab. Studio.
We invent digital products and experiences.

SEATTLE | DETROIT | NEW YORK | MUNICH | HYDERABAD


(Elijah Johnson) #19

Correct me if I am wrong, but it seems like the main intended use of
optionals would be to work with legacy Obj-C code that is missing
nullability specifiers. In the rest of the cases, a forced-unwrap is just
"syntactic sugar" for a fatal error block or a way to indicate that you
have already checked the type using "as" or "!= nil" (ie. that they wrote
the code in a non-Swift style and haven't updated it yet - just the perfect
situation for a warning).

Another use is interoperability with "C" code, where the user knows that
the code does not return a "null" pointer but has no way of annotating that
in C. Or with arrays where the result is optional, but never is when the
index is right. Maybe an @allowsForceUnwrap annotation on the function
could silence this warning. Definitely a much more serious a condition that
where the result of the function call goes unused.

A simple condition that a warning is emitted, except when unwrapping
NSObject and its subclasses, or other unsafe operations like UnsafePointer,
should cover all of its non-syntax uses. I think it is fair to say that
developers would want to see the fatalError() written out.

···

2017-03-07 13:36 GMT-05:00 Elijah Johnson <ejrx7753@gmail.com>:

How about the proposal of warnings and/or fix-it for unnecessary use of
optionals?

It seems to me though, that there aren't too many "necessary" uses for
forced-unwrapping. Judging from (https://github.com/apple/
swift-evolution/blob/master/proposals/0054-abolish-iuo.md), it was
probably added as a way of helping work with Obj-C also.

func test(a:String?) -> String {
    return a!
}

is equivelent to

func test(a:String?) -> String {
    if let a = a {
         print(a);
    } else {
         fatalError();
    }
}

I wouldn't remove it at this stage, but to quote (
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md),
it is "favoring terseness over clarity by introducing new magic syntactic
sugar," ironically adding this very terse and easy syntax for the coding
style that we do not want to incentivize.

Adding warnings and a fix-it to make the crash explicit would more or less
be as good as removing forced-unwrap from the language. Just maybe needs
some clarification of what exactly is a valid use of the force-unwrap.
Maybe for interop with Obj-C it should be considered "necessary", for
example.

2017-03-07 11:54 GMT-05:00 Josh Parmenter <jparmenter@vectorform.com>:

On Mar 6, 2017, at 7:52 PM, Elijah Johnson via swift-evolution < >> swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Says: Fix it: Insert !
Should say: Fix it: Use optional binding.

I agree with this in general. I tell people that I’m teaching that
unwrapping uses ‘!' for a reason. It should scream at you that something is
happening that probably needs more careful attention.

Best,
Josh

Joshua Parmenter | Engineering Lead, Apple Technologies

T 248 777 7777
C 206 437 1551
F 248 616 1980
www.vectorform.com<http://www.vectorform.com/>

Vectorform
2107 Elliott Ave Suite 303
Seattle, WA 98121 USA

Think Tank. Lab. Studio.
We invent digital products and experiences.

SEATTLE | DETROIT | NEW YORK | MUNICH | HYDERABAD


(Elijah Johnson) #20

I’ve skimmed through it just now. What we are talking about is “Logic
Failures” and that is handled in three small paragraphs of the
ErrorHandling document the rest (universal, recoverable, simple domain
errors) are separate. Basically, to summarize the Logic Failures section,
there is no rule yet set down “yet".

Quote:

The correct handling of these error conditions is an open question and is
not a focus of this proposal. Should we decide to make them recoverable,
they will likely follow the same implementation mechanism as universal
errors, if not necessarily the same language rules."

The “universal errors” section referred to is equally open-ended. To sum up
the two sections, there seems to be an implicit proposal to add universal
exceptions in the future (“logic failures” and Obj-C/C++ exception support)
in the future, with a few concerns about discouraging its use. My concern
about webservers is mentioned directly in the “Logic Failures” section,
"High-reliability systems may need some way to limp on even after an
assertion failure.”.

So, granted that the proposal is more or less already there, I would
propose typed exceptions for "Logic Failures", Obj-C, and C++ exceptions.

If someone needs more discouragement than that, then all that needs to be
done is to make the syntax cumbersome. Like having to pass a closure to a
function instead of the clean do{} catch{} syntax, which btw is the way
that it is done now for those who need to catch Obj-C exceptions from
Swift. See
http://stackoverflow.com/questions/35119531/catch-objective-c-exception-in-swift
for
that. I can say that I’ve used it myself and that I am extremely
discouraged from using it to throw an NSException from Swift, or even to
catch the Obj-C exceptions for that matter.

If you want improved error handling, feel free to put together a proposal
once Swift 4 phase 2 is over. A good proposal should take into account the
reasons Swift's error handling was designed as it currently is (
https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst)

Otherwise, if you really need to build a web server framework that can
swallow any sort of application logic without choking, perhaps Swift as it
currently stands isn't the best tool for the job.

Best,
Austin

The problem for using Swift on the server is one of these optionals (or
array index out of bounds error, or cast from Int to UInt error) would
crash the entire server directing many requests. Granted, thats not Apple’s
busininess, but it is pretty much standad in a modern webserver never to
crash, and whoever is developing servers will find they don’t have the
necessary power to do that. Some languages like PHP have a unique process
per-request style, but that phrohibits shared data. One could do the same
with Swift, but it would be a major loss.

Just because Swift is not garbage collected doesn’t mean that you can’t
safely unwind the stack and continue execution somewhere. If “bad”
developers would start using this as unwanted exceptions, then it can be
made inconvient somehow.

Think about a server that handles 1,000 requests per minute - its going to
happen evenutally, even despite testing, and chances are that once it
happens it will re-occur - and now the server goes down every minute or
even every few seconds and needs an auto-restart loop.

If we’re going to be talking about “bad developers” as in ones who might
once code a bug with an optional or index out of bounds exception, then
that is going to be a very high standard and result in a very mild adoption
of server side Swift. Maybe it would take off for a while, and then when
people realize these things, they will say “thats why everyone writes their
server-side code in Java/C#/PHP, etc” and Swift will be a thing for people
who need ultra-fast performance on a server.

Its not really Apple’s business, and clearly you are trying to replace only
C++ and not Java/C#, but if you can add a compiler mode with exceptions
instead of fatalError(mesage:) calls, that would contribute a lot to making
web servers with Swift. Even if you leak the entire call stack, it would
still be better than crashing an entire web serer.

Swift already is an unmanaged language, and is far closer to C++ than Java.
There is no equivalent to the CLR or JVM and it is trivially easy to call
into C code or the unsafe APIs and do nearly anything that C can do with
regard to direct access to memory.

The force-unwrap operator was never intended to model a Java-style runtime
exception. Instead, it is an assertion which indicates a programmer logic
error. The preferred way to handle an optional at runtime has always been
to use the conditional-unwrapping functionality the language offers. The
correct way to report errors at runtime that aren't due to programmer error
is through the do-try-catch mechanism. Pervasive, unnecessary use of '!' is
a project management and/or developer competence issue, and not something
the language should go out of its way to fix.

Sugaring 'if let' for programmer convenience is something on the commonly
rejected proposals list:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

Regards,
Austin

···

On March 12, 2017 at 3:20:41 PM, Austin Zheng (austinzheng@gmail.com) wrote:
On Mar 12, 2017, at 12:06 PM, Elijah Johnson <ejrx7753@gmail.com> wrote:
On March 6, 2017 at 9:47:03 PM, Austin Zheng (austinzheng@gmail.com) wrote:

On Mon, Mar 6, 2017 at 6:27 PM, Elijah Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Additionally, not discarding previous comments, one way the language could
be improved is by replacing (or rather augmenting) optional binding with a
faster syntax.

ex.

func test( name : String?, name2 :String? ){
     name! , name2! {
// inside this block, “name” and “name2” are non-optional
    } else {
      // no forced unwrapping, just optional else case
   }
}

Whereas the alternative (current optional binding), requires a
re-definition of variables and an additional “if” operator. Besides the
extra characters involved in typing and reading it, usually variables have
specific names that the user does not want to augument.

func test( name : String?, name2 :String? ){
    if let nameUnwrapped = name , let name2Unwrapped = name2 {

    } else {
   }
}

func test( name : String?, name2 :String? ){
    guard let nameUnwrapped = name , let name2Unwrapped = name2 else {

    }

}

The fact that we don’t need a “nameUnwrapped” variable (which is unsightly
and requires refractoring) is one thing that still makes forced unwrapping
still very much a necessary or common part of Swift coding, even where it
could be replaced with optional binding.

On March 6, 2017 at 7:20:40 PM, Elijah Johnson (ejrx7753@gmail.com) wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.

Elijah

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution