[Design Question] Unexpected forced optional unwrapping behavior


(Michael Henson) #1

I've spent some time exploring different aspects of the language's type
system and came across a case where I wanted to know the type of the thing
an optional might hold, if it exists. The direct type of an optional
variable is, unsurprisingly, an optional:

var example: String? = "example"

example: String? = "example"

example.dynamicType

$R1: String?.Type = String?

Ok, that didn't work. What if I dereference?

example!.dynamicType

$R2: String.Type = String

Ok. What if the optional doesn't currently have a value? Does this still
work?

example = nil

$R3: String.Type = String

That's odd. I expected it not work, given how forced unwrapping of nil
optionals usually turns out.

Is this explicitly intended behavior, something that really shouldn't work
and shouldn't be relied on, or... other?

Mike


(Charles Srstka) #2

Well, there’s at least one case where it doesn’t work, since this only seems to work with ‘var’ variables, and not with ‘let’ constants.

1> var variable: String? = nil
variable: String? = nil
  2> let constant: String? = nil
constant: String? = nil
  3> variable!.dynamicType
$R0: String.Type = String
  4> constant!.dynamicType
fatal error: unexpectedly found nil while unwrapping an Optional value
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)

I, too, am confused as to why this ever works at all.

Charles

···

On Jan 8, 2016, at 7:56 PM, Michael Henson via swift-evolution <swift-evolution@swift.org> wrote:

I've spent some time exploring different aspects of the language's type system and came across a case where I wanted to know the type of the thing an optional might hold, if it exists. The direct type of an optional variable is, unsurprisingly, an optional:

> var example: String? = "example"
example: String? = "example"
> example.dynamicType
$R1: String?.Type = String?

Ok, that didn't work. What if I dereference?

> example!.dynamicType
$R2: String.Type = String

Ok. What if the optional doesn't currently have a value? Does this still work?

> example = nil
$R3: String.Type = String

That's odd. I expected it not work, given how forced unwrapping of nil optionals usually turns out.

Is this explicitly intended behavior, something that really shouldn't work and shouldn't be relied on, or... other?


(John McCall) #3

Please file a bug; we might be failing to evaluate the base when we can statically fold the .dynamicType expression.

John.

···

On Jan 8, 2016, at 6:14 PM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 8, 2016, at 7:56 PM, Michael Henson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I've spent some time exploring different aspects of the language's type system and came across a case where I wanted to know the type of the thing an optional might hold, if it exists. The direct type of an optional variable is, unsurprisingly, an optional:

> var example: String? = "example"
example: String? = "example"
> example.dynamicType
$R1: String?.Type = String?

Ok, that didn't work. What if I dereference?

> example!.dynamicType
$R2: String.Type = String

Ok. What if the optional doesn't currently have a value? Does this still work?

> example = nil
$R3: String.Type = String

That's odd. I expected it not work, given how forced unwrapping of nil optionals usually turns out.

Is this explicitly intended behavior, something that really shouldn't work and shouldn't be relied on, or... other?

Well, there’s at least one case where it doesn’t work, since this only seems to work with ‘var’ variables, and not with ‘let’ constants.

1> var variable: String? = nil
variable: String? = nil
  2> let constant: String? = nil
constant: String? = nil
  3> variable!.dynamicType
$R0: String.Type = String
  4> constant!.dynamicType
fatal error: unexpectedly found nil while unwrapping an Optional value
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)

I, too, am confused as to why this ever works at all.