Skip to content

Commit 156f5d3

Browse files
committed
Merge pull request #2 from apple/master
Update
2 parents d96970d + a5a4f70 commit 156f5d3

7 files changed

+502
-5
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,15 @@ sooner.
135135
### Implemented proposals for Swift 2.2
136136

137137
* [SE-0001: Allow (most) keywords as argument labels](proposals/0001-keywords-as-argument-labels.md)
138-
* [SE-0015: Tuple comparison operators](proposals/0015-tuple-comparison-operators.md)
139-
* [SE-0014: Constraining `AnySequence.init`](proposals/0014-constrained-AnySequence.md)
140138
* [SE-0011: Replace `typealias` keyword with `associatedtype` for associated type declarations](proposals/0011-replace-typealias-associated.md)
139+
* [SE-0014: Constraining `AnySequence.init`](proposals/0014-constrained-AnySequence.md)
140+
* [SE-0015: Tuple comparison operators](proposals/0015-tuple-comparison-operators.md)
141+
* [SE-0020: Swift Language Version Build Configuration](proposals/0020-if-swift-version.md)
141142
* [SE-0021: Naming Functions with Argument Labels](proposals/0021-generalized-naming.md)
142143
* [SE-0022: Referencing the Objective-C selector of a method](proposals/0022-objc-selectors.md)
143144

144145
### Accepted proposals for Swift 2.2
145146
* [SE-0008: Add a Lazy flatMap for Sequences of Optionals](proposals/0008-lazy-flatmap-for-optionals.md)
146-
* [SE-0020: Swift Language Version Build Configuration](proposals/0020-if-swift-version.md)
147147

148148
# Other Proposals
149149

proposals/0020-if-swift-version.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
* Proposal: [SE-0020](https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md)
44
* Author(s): [David Farler](https://github.com/bitjammer)
5-
* Status: **Accepted** for Swift 2.2
5+
* Status: **Implemented** in Swift 2.2
66
* Review manager: Doug Gregor
77

88
## Introduction
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Change IteratorType post-nil guarantee
2+
3+
* Proposal: [SE-0052](https://github.com/apple/swift-evolution/blob/master/proposals/0052-iterator-post-nil-guarantee.md)
4+
* Author(s): [Patrick Pijnappel](https://github.com/PatrickPijnappel)
5+
* Status: **Awaiting review**
6+
* Review manager: TBD
7+
8+
## Introduction
9+
10+
Currently, the documentation for `IteratorType.next()` has the precondition
11+
that when calling `next()`, no preceding call to `next()` should have returned
12+
`nil`, and in fact encourages implementations to raise a `preconditionFailure()`
13+
for violations of this requirement. However, all current 27 `IteratorType`
14+
implementations in the standard library return `nil` indefinitely. Many users
15+
are likely unaware of the precondition, expecting all iterators to return
16+
`nil` indefinitely and writing code that might rely on this assumption. Such
17+
code will usually run fine, until someone does in fact pass in an iterator not
18+
repeating `nil` (it's a silent corner case).
19+
20+
Swift-evolution thread: [\[Proposal\] Change guarantee for GeneratorType.next() to always return nil past end](http://thread.gmane.org/gmane.comp.lang.swift.evolution/8519)
21+
22+
Pull-request: [#1702](https://github.com/apple/swift/pull/1702)
23+
24+
## Motivation
25+
26+
While not overwhelmingly common, it is relatively easy to write code based on the
27+
assumption `nil` will be returned indefinitely:
28+
29+
``` swift
30+
// Example based on standard library code (Sequence.swift)
31+
while let element = iterator.next() {
32+
if condition(element) {
33+
foo(element) // call foo on first element satisfying condition
34+
break
35+
}
36+
}
37+
while let element = iterator.next() {
38+
bar(element) // call bar on remaining elements
39+
}
40+
41+
// Another example
42+
switch (iterator.next(), iterator.next()) {
43+
// ...
44+
}
45+
```
46+
47+
Even though this can be trivially rewritten to not rely on post-`nil` behavior,
48+
the user won't perform this rewrite if they are unaware of the precondition. In
49+
their testing the code will work fine, and likely will in almost every case,
50+
except when passing the rare iterator that doesn't repeat `nil`.
51+
52+
## Proposed solution
53+
54+
Bring the guarantee in line with the common expectation, and require iterators
55+
to return `nil` indefinitely.
56+
57+
Requiring `nil` to be returned indefinitely does require the implementors of
58+
custom `IteratorType` conformances to respect this, but this is likely already
59+
the expectation for most users. Most iterators already get this as a natural
60+
consequence of their implementation (as is the case with all current standard
61+
library iterators), but otherwise they can simply track a `done` flag to do so.
62+
It should be noted that this requirement would also affect closures passed to
63+
`AnyIterator`.
64+
65+
### Performance considerations
66+
The original rationale for introducing the precondition was because of concerns
67+
it might add storage and performance burden to some implementations of
68+
`IteratorType` (see [here](http://article.gmane.org/gmane.comp.lang.swift.evolution/8532)).
69+
70+
However, in light of implementation experience, there are a few observations we
71+
can make:
72+
- These cases are rare. The standard library currently has no iterators that
73+
require extra state or branches to return `nil` indefinitely. The iterator for
74+
the proposed `takeWhile()` ([SE-0045](https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md))
75+
would be the first occurance in the standard library.
76+
- Even in such cases, in the common case the calling code doesn't rely on
77+
post-`nil` behavior (e.g. `for in`, `map`, etc.) this extra storage and
78+
branching can usually optimized away.
79+
- Not having the post-`nil` guarantee can sometimes add storage and performance
80+
burden for the caller instead, e.g. when an iterator somehow buffers it's
81+
underlying iterator. This in contrast can usually not be optimized away. For
82+
example, the standard library's UTF-8/UTF-16 decoding has 4 instead of 3 branches
83+
per character for ASCII because of this.
84+
85+
## Detailed design
86+
87+
Original guarantee:
88+
89+
``` swift
90+
/// Advance to the next element and return it, or `nil` if no next
91+
/// element exists.
92+
///
93+
/// - Precondition: `next()` has not been applied to a copy of `self`
94+
/// since the copy was made, and no preceding call to `self.next()`
95+
/// has returned `nil`. Specific implementations of this protocol
96+
/// are encouraged to respond to violations of this requirement by
97+
/// calling `preconditionFailure("...")`.
98+
```
99+
100+
Proposed guarantee:
101+
102+
``` swift
103+
/// Advance to the next element and return it, or `nil` if no next element
104+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
105+
///
106+
/// - Precondition: `next()` has not been applied to a copy of `self`
107+
/// since the copy was made.
108+
```
109+
110+
## Impact on existing code
111+
112+
All `IteratorType` implementations in the standard library already comply with
113+
the new guarantee. It is likely most existing custom iterators will as well,
114+
however some might be rendered in violation of their guarantee by the change.
115+
116+
## Alternatives considered
117+
118+
- Require `IteratorType` to not crash but keep the return value up to specific
119+
implementations. This allows them to use it for other behavior e.g. repeating
120+
the sequence after `nil` is returned. This however retains most of the problems
121+
of the original guaranteee described in this proposal.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Remove explicit use of `let` from Function Parameters
2+
3+
* Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md)
4+
* Author(s): [Nicholas Maccharoli](https://github.com/nirma)
5+
* Status: **Awaiting review**
6+
* Review manager: TBD
7+
8+
## Introduction
9+
10+
Since function parameters are immutable by default, allowing function parameters to be explicitly labeled
11+
as `let` is a bit of a syntactic redundancy that would best be removed.
12+
Not allowing function parameters to be explicitly declared as `let` would permit a more simple and uniform function declaration syntax for swift.
13+
Furthermore proposal [SE-0003​: "Removing `var` from Function Parameters"](https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters.md) removes `var` from function parameters removing any possible ambiguity as to whether a function parameter is immutable or not.
14+
15+
16+
Swift-evolution thread: [[swift-evolution] Removing explicit use of `let` from Function Parameters](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160314/012851.html)
17+
18+
## Motivation
19+
Now that proposal [SE-0003​: "Removing `var` from Function Parameters"](https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters.md) has been accepted, it would make sense that the syntax for function parameters being explicitly declared as `let` would be removed as well.
20+
Since prepending `let` to an argument label does not modify behavior, leaving it as part of the language would only add redundancy and complexity to Swift's syntax at no added benefit.
21+
Furthermore [SE-0001](https://github.com/apple/swift-evolution/blob/master/proposals/0001-keywords-as-argument-labels.md) allowed the use of all keywords as argument labels except for `inout`, `var` and `let`.
22+
Proposal [SE-0031](https://github.com/apple/swift-evolution/blob/master/proposals/0031-adjusting-inout-declarations.md) made `inout` a type modifier freeing `inout` to be used as an argument label and proposal [SE-0003](https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters.md) prohibits declaring function parameters as `var` freeing `var` to be used as an argument label.
23+
The only keyword still in use that is preventing any keyword from being used as an argument label is `let` which if removed from function parameter syntax would permit [SE-0001](https://github.com/apple/swift-evolution/blob/master/proposals/0001-keywords-as-argument-labels.md) to allow all keywords as argument labels with no exceptions.
24+
25+
## Proposed solution
26+
27+
Make functions with parameters declared with an explicit `let` prohibited and a compile time error.
28+
29+
Basically make functions declared like this a compile time error:
30+
```swift
31+
func foo(let x: Int) { ... }
32+
```
33+
34+
In favor of omitting `let` like this:
35+
```swift
36+
func foo(x: Int) { ... }
37+
```
38+
39+
## Impact on existing code
40+
41+
In code that is migrating to this newer proposed syntax the `let` keyword should be deleted if placed before a function parameter or else it will be treated as an external label.
42+
This should not be too disruptive since the common convention is already to not label function parameters as `let`.
43+
44+
45+
## Alternatives considered
46+
47+
Leave the redundant syntax in place, but I personally don't see any merit in that.
48+
49+

proposals/0054-abolish-iuo.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Abolish `ImplicitlyUnwrappedOptional` type
2+
3+
* Proposal: [SE-0054](0054-abolish-iuo.md)
4+
* Author: [Chris Willmore](http://github.com/cwillmor)
5+
* Status: **Awaiting review**
6+
* Review Manager: [Chris Lattner](https://github.com/lattner)
7+
8+
## Introduction
9+
10+
This proposal seeks to remove the `ImplicitlyUnwrappedOptional` type from the
11+
Swift type system and replace it with an IUO attribute on declarations.
12+
Appending `!` to the type of a Swift declaration will give it optional type and
13+
annotate the declaration with an attribute stating that it may be implicitly
14+
unwrapped when used.
15+
16+
Swift-evolution thread: ["Abolish IUO Type"](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160314/012752.html)
17+
18+
## Motivation
19+
20+
The `ImplicitlyUnwrappedOptional` ("IUO") type is a valuable tool for importing
21+
Objective-C APIs where the nullability of a parameter or return type is
22+
unspecified. It also represents a convenient mechanism for working through
23+
definite initialization problems in initializers. However, IUOs are a
24+
transitional technology; they represent an easy way to work around un-annotated
25+
APIs, or the lack of language features that could more elegantly handle certain
26+
patterns of code. As such, we would like to limit their usage moving forward,
27+
and introduce more specific language features to take their place. Except for a
28+
few specific scenarios, optionals are always the safer bet, and we’d like to
29+
encourage people to use them instead of IUOs.
30+
31+
This proposal seeks to limit the adoption of IUOs to places where they are
32+
actually required, and put the Swift language on the path to removing
33+
implicitly unwrapped optionals from the system entirely when other technologies
34+
render them unnecessary. It also completely abolishes any notion of IUOs below
35+
the type-checker level of the compiler, which will substantially simplify the
36+
compiler implementation.
37+
38+
## Proposed solution
39+
40+
In this proposal, we continue to use the syntax `T!` for declaring implicitly
41+
unwrapped optional values in the following locations:
42+
43+
* property and variable declarations
44+
* initializer declarations
45+
* function and method declarations
46+
* subscript declarations
47+
* parameter declarations (with the exception of vararg parameters)
48+
49+
However, the appearance of `!` at the end of a property or variable
50+
declaration's type no longer indicates that the declaration has IUO type;
51+
rather, it indicates that (1) the declaration has optional type, and (2) the
52+
declaration has an attribute indicating that its value may be implicitly
53+
forced. (No human would ever write or observe this attribute, but we will
54+
refer to it as `@_autounwrapped`.) Such a declaration is referred to henceforth
55+
as an IUO declaration.
56+
57+
Likewise, the appearance of `!` at the end of the return type of a function
58+
indicates that the function has optional return type and its return value may
59+
be implicitly unwrapped. The use of `init!` in an initializer declaration
60+
indicates that the initializer is failable and the result of the initializer
61+
may be implicitly unwrapped. In both of these cases, the `@_autounwrapped`
62+
attribute is attached to the declaration.
63+
64+
A reference to an IUO variable or property prefers to bind to an optional, but
65+
may be implicitly forced (i.e. converted to the underlying type) when being
66+
type-checked; this replicates the current behavior of a declaration with IUO
67+
type. Likewise, the result of a function application or initialization where
68+
the callee is a reference to an IUO function declaration prefers to retain its
69+
optional type, but may be implicitly forced if necessary.
70+
71+
If the expression can be explicitly type checked with a strong optional type,
72+
it will be. However, the type checker will fall back to forcing the optional if
73+
necessary. The effect of this behavior is that the result of any expression
74+
that refers to a value declared as `T!` will either have type `T` or type `T?`.
75+
For example, in the following code:
76+
77+
```Swift
78+
let x: Int! = 5
79+
let y = x
80+
let z = x + 0
81+
```
82+
83+
… `x` is declared as an IUO, but because the initializer for `y` type checks
84+
correctly as an optional, `y` will be bound as type `Int?`. However, the
85+
initializer for `z` does not type check with `x` declared as an optional
86+
(there's no overload of `+` that takes an optional), so the compiler forces the
87+
optional and type checks the initializer as `Int`.
88+
89+
This model is more predictable because it prevents IUOs from propagating
90+
implicitly through the codebase, and converts them to strong optionals, the
91+
safer option, by default.
92+
93+
An IUO variable may still be converted to a value with non-optional type,
94+
through either evaluating it in a context which requires the non-optional type,
95+
explicitly converting it to a non-optional type using the `as` operator,
96+
binding it to a variable with explicit optional type, or using the force
97+
operator (`!`).
98+
99+
Because IUOs are an attribute on declarations rather than on types, the
100+
`ImplicitlyUnwrappedOptional` type, as well as the long form
101+
`ImplicitlyUnwrappedOptional<T>` syntax, is removed. Types with nested IUOs are
102+
no longer allowed. This includes types such as `[Int!]` and `(Int!, Int!)`.
103+
104+
Type aliases may not have IUO information associated with them. Thus the
105+
statement `typealias X = Int!` is illegal. This includes type aliases resulting
106+
from imported `typedef` statements. For example, the Objective-C type
107+
declaration
108+
109+
```Objective-C
110+
typedef void (^ViewHandler)(NSView *);
111+
```
112+
113+
... is imported as the Swift type declaration
114+
115+
```Swift
116+
typealias ViewHandler = (NSView?) -> ()
117+
```
118+
119+
Note that the parameter type is `NSView?`, not `NSView!`.
120+
121+
## Examples
122+
123+
```Swift
124+
func f() -> Int! { return 3 } // f: () -> Int?, has IUO attribute
125+
let x1 = f() // succeeds; x1: Int? == 3
126+
let x2: Int? = f() // succeeds; x2: Int? = .some(3)
127+
let x3: Int! = f() // succeeds; x3: Int? = .some(3), has IUO attribute
128+
let x4: Int = f() // succeeds; x4: Int = 3
129+
let a1 = [f()] // succeeds; a: [Int?] = [.some(3)]
130+
let a2: [Int!] = [f()] // illegal, nested IUO type
131+
let a3: [Int] = [f()] // succeeds; a: [Int] = [3]
132+
133+
func g() -> Int! { return nil } // f: () -> Int?, has IUO attribute
134+
let y1 = g() // succeeds; y1: Int? = .none
135+
let y2: Int? = g() // succeeds; y2: Int? = .none
136+
let y3: Int! = g() // succeeds; y3: Int? = .none, has IUO attribute
137+
let y4: Int = g() // traps
138+
let b1 = [g()] // succeeds; b: [Int?] = [.none]
139+
let b2: [Int!] = [g()] // illegal, nested IUO type
140+
let b3: [Int] = [g()] // traps
141+
142+
func p<T>(x: T) { print(x) }
143+
p(f()) // prints "Optional(3)"; p is instantiated with T = Int?
144+
145+
if let x5 = f() {
146+
// executes, with x5: Int = 3
147+
}
148+
if let y5 = g() {
149+
// does not execute
150+
}
151+
```
152+
153+
## Impact on existing code
154+
155+
These changes will break existing code; as a result, I would like for them to
156+
be considered for inclusion in Swift 3. This breakage will come in two forms:
157+
158+
* Variable bindings which previously had inferred type `T!` from their binding
159+
on the right-hand side will now have type `T?`. The compiler will emit an
160+
error at sites where those bound variables are used in a context that demands
161+
a non-optional type and suggest that the value be forced with the `!`
162+
operator.
163+
164+
* Explicitly written nested IUO types (like `[Int!]`) will have to be rewritten
165+
to use the corresponding optional type (`[Int?]`) or non-optional type
166+
(`[Int]`) depending on what's more appropriate for the context. However, most
167+
declarations with non-nested IUO type will continue to work as they did
168+
before.
169+
170+
* Unsugared use of the `ImplicitlyUnwrappedOptional` type will have to be
171+
replaced with the postfix `!` notation.
172+
173+
It will still be possible to declare IUO properties, so the following deferred
174+
initialization pattern will still be possible:
175+
176+
```Swift
177+
struct S {
178+
var x: Int!
179+
init() {}
180+
func initLater(x someX: Int) { x = someX }
181+
}
182+
```
183+
184+
I consider the level of breakage resulting from this change acceptable. Types
185+
imported from Objective-C APIs change frequently as those APIs gain nullability
186+
annotations, and that occasionally breaks existing code too; this change will
187+
have similar effect.
188+
189+
## Alternatives considered
190+
191+
* Continue to allow IUO type, but don't propagate it to variables and
192+
intermediate values without explicit type annotation. This resolves the issue
193+
of IUO propagation but still allows nested IUO types, and doesn't address the
194+
complexity of handling IUOs below the Sema level of the compiler.
195+
196+
* Remove IUOs completely. Untenable due to the prevalence of deferred
197+
initialization and unannotated Objective-C API in today's Swift ecosystem.

0 commit comments

Comments
 (0)