masters3d
(Masters3d)
June 19, 2019, 8:59pm
1
Hi Team,
I wanted to bring up the current magical behavior of Optional auto initialization to nil when using ?
Currently in swift you can declare an Optional var
iable in this way
var foo: String?
print(foo) // prints nil
swift will automatically assign .none
to the value. The above is somewhat equivalent to the below code.
var foo: String? = nil // .none
print(foo) // prints nil
but this behavior is only available when using ?
. The below does not work.
var someValue11:Optional<String>
// print(someValue11) // error: variable 'someValue11' used before being initialized
I’d love to see someone pitch and drive a proposal to remove that behavior, by the way. Optionals are the only type in Swift that can be default initialized in this manner, and it feels like an unnecessary bit of magic to me.
I think this behavior is confusing specially when dealing with implicit unwrapped optional.
var someValue33:String!
_ = someValue33 + "?") // Boom Crash. No different from an uninitialized variable error
opened 11:24PM - 14 Jun 19 UTC
bug
compiler
| | |
|------------------|-----------------|…
|Previous ID | SR-10931 |
|Radar | None |
|Original Reporter | @masters3d |
|Type | Bug |
<details>
<summary>Environment</summary>
swift 5.0
</details>
<details>
<summary>Additional Detail from JIRA</summary>
| | |
|------------------|-----------------|
|Votes | 2 |
|Component/s | Compiler |
|Labels | Bug |
|Assignee | None |
|Priority | Medium |
md5: 0e6cd4419cd22cf69c97288a90ec7e94
</details>
**relates to**:
* [SR-354](https://bugs.swift.org/browse/SR-354) Non-optional variable tuple of optional values should not have default value
* [SR-801](https://bugs.swift.org/browse/SR-801) TestPOUnwrapping.py - PO for optional class members set to nil are showing up as if 0 or ""
* [SR-11768](https://bugs.swift.org/browse/SR-11768) Stored property declaration + initialization expressions cannot be inlinable
* [SR-11777](https://bugs.swift.org/browse/SR-11777) 'var something: 'Type?' always get double initialised
**Issue Description:**
I am having a hard time understanding why T? variables auto initialize to nil when Optional\<T\> variables do not. This seems like a bug to me. If its not a bug, where else is this feature being used?
``` java
do{
let someValue1:Optional<String>
//print(someValue1) // error: constant 'someValue1' used before being initialized
var someValue11:Optional<String>
// print(someValue11) // error: variable 'someValue11' used before being initialized
let someValue2:String?
// print(someValue2) //error: constant 'someValue2' used before being initialized
var someValue22:String?
print(someValue22) // Compiler happy. Why? What is the technical reason why this should work.
// Now consider the following type of optional.
var someValue33:String!
print(someValue33 + "") // Boom Crash. Implicit initialization here is actually dangerous.
}
```
I propose that we deprecate this to make swift more consistent.
var foo: String?
// print(foo) // error: variable 'foo' used before being initialized. <Insert fixit here to add = nil>
What does the community think?
15 Likes
Jon_Shier
(Jon Shier)
June 19, 2019, 9:01pm
2
I don't see how the calculus has changed. It's a trivial rule to learn and saves more than it hurts.
5 Likes
It's also confusing because it applies to local variables but not to properties.
jrose
(Jordan Rose)
June 19, 2019, 9:23pm
4
It applies to var
but not let
, both for local variables and properties.
5 Likes
Well the fact that I got that wrong just shows how confusing it is!
7 Likes
blangmuir
(Ben Langmuir)
June 19, 2019, 11:45pm
6
I'd be very happy to see the implicit initialization removed. In addition to the issues mentioned in your pre-pitch, I want
var x: Int?
if b {
x = 1
} else {
}
use(x)
to tell me that I haven't initialized x
on all paths like it does for any other type.
13 Likes
Undocumented extension of this feature: tuples of optional types are default initialized as well.
var x: (Int?, ((Bool?, Int?), Int?))
print(x) // prints (nil, ((nil, nil), nil))
If we remove this behavior, we should document that the tuple behavior is removed as well.
12 Likes
Alejandro
(Alejandro Alonso)
June 19, 2019, 11:52pm
8
This would clean up a lot of implicit rules and edge cases in the compiler!
1 Like
i know what the rule is but at this point i’ve taken to just always writing out the nil
s to avoid confusion with let
deferred initialization. will attest that i too find this pretty confusing.
3 Likes
jarod
(Jarod Long)
June 19, 2019, 11:55pm
10
I've run into problems a handful of times where I forgot to set an optional property during initialization because it defaulted to nil. I'd be happy to see this rule removed mainly for that reason, but also because it's a special case rule that doesn't pull its weight in terms of convenience imo.
11 Likes
bobergj
(Jonas)
June 20, 2019, 12:13am
11
Then make that property non-optional? Perhaps you are tracking some state where, instead of an optional, it would be better to use your own enum with cases named after the states + associated values for the data.
Since most people above seem positive to this pitch, just want to add a -1.
jarod
(Jarod Long)
June 20, 2019, 12:25am
12
I agree that a custom enum is sometimes more appropriate than an optional, but not always. In cases where an optional is more appropriate, I wouldn't want to create an enum just to protect against this issue.
2 Likes
I'm +1 on this. I don't feel it pulls it's weight, and I agree with @taylorswift about the let
deferred initialization issue.
1 Like
ladislas
(Ladislas de Toldi)
June 20, 2019, 8:50am
14
+1 as well for the reasons above.
I don't normally post here, but I also wanted to balance things out a bit with a -1.
Personally, I find it convenient to declare and initialise optionals with nil
in one go (sort of like the opposite to type inference for non-optional variables, i.e. writing out the type instead of the value). Despite the anecdotes above, the rule also seems straightforward.
(Equally, I'm one of the weirdos that liked doing var x = Int?()
in the Swift 2 days, so make of that what you will!)
2 Likes
kyzmitch
(Andrey Ermoshin)
June 20, 2019, 10:56am
16
to protect yourself from missed initialisation in that case when you have if else
I use let
kyzmitch
(Andrey Ermoshin)
June 20, 2019, 10:58am
17
it is like init
with default parameters but for Optional, isn't it?
anandabits
(Matthew Johnson)
June 20, 2019, 1:23pm
18
+1. There is no reason for a special case implicit initialization.
2 Likes
ashin
(Adam Shin)
June 20, 2019, 3:29pm
20
With this change, would all @IBOutlet
s have to be explicitly initialized to nil then?
@IBOutlet var label: UILabel! = nil
8 Likes