Skip to content

Commit 70209e4

Browse files
authored
Fix drafting errors (#1405)
1 parent 971d1f4 commit 70209e4

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

proposals/0315-placeholder-types.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@ Fortunately, Swift provides several ways for the user to provide type informatio
3434
* Variable type annotations:
3535

3636
```swift
37-
let losslessStringConverter: (String) -> Double = Double.init
37+
let losslessStringConverter: (String) -> Double? = Double.init
3838
```
3939

4040
* Type coercion via `as` (seen above):
4141

4242
```swift
43-
let losslessStringConverter = Double.init as (String) -> Double
43+
let losslessStringConverter = Double.init as (String) -> Double?
4444
```
4545

4646
* Passing type parameters explicitly (e.g., `JSONDecoder` ):
4747

4848
```swift
49-
let dict = JSONDecoder().decode([String: Int].self, from: data)
49+
let dict = try JSONDecoder().decode([String: Int].self, from: data)
5050
```
5151

5252
The downside of all of these approaches is that they require the user to write out the *entire* type, even when the compiler only needs guidance on some sub-component of that type. This can become particularly problematic in cases where a complex type that would normally be inferred has to be written out explicitly because some *unrelated* portion of the type signature is required. E.g.,
@@ -137,7 +137,7 @@ let publisher: AnyPublisher<Int, _> = Just(makeValue()).setFailureType(to: Error
137137

138138
Now, the type checker has all the information it needs to resolve the reference to `makeValue` : the ultimately resulting `AnyPublisher` must have `Output == Int` , so the result of `setFailureType(to:)` must have `Output == Int` , so the instance of `Just` must have `Output == Int` , so the argument to `Just.init` must have type `Int` , so `makeValue` must refer to the `Int` -returning overload!
139139

140-
Note: it is not permitted to specify a type that is _just_ a placeholder—see the relevant subsection in **Future directions** for a dicussion of the considerations. This means that, for example, the following would fail to compile:
140+
Note: it is not permitted to specify a type that is _just_ a placeholder—see the relevant subsection in **Future directions** for a discussion of the considerations. This means that, for example, the following would fail to compile:
141141

142142
```swift
143143
let percent: _ = 100.0 // error: placeholders are not allowed as top-level types
@@ -151,7 +151,7 @@ In some cases, placeholders may be expected to conform to certain protocols. E.g
151151
let dict: [_: String] = [0: "zero", 1: "one", 2: "two"]
152152
```
153153

154-
When examining the storage type for `dict` , the compiler will expect the placeholder key type to conform to `Hashable` . Conservatively, placeholder types are assumed to satisfy all necessary constraints, deferring the verification of these constraints until the checking of the intialization expression.
154+
When examining the storage type for `dict` , the compiler will expect the placeholder key type to conform to `Hashable` . Conservatively, placeholder types are assumed to satisfy all necessary constraints, deferring the verification of these constraints until the checking of the initialization expression.
155155

156156
### Generic parameter inference
157157

@@ -206,31 +206,31 @@ extension Bar {
206206
func frobnicate() -> Bar {
207207
return Bar(t: 42, u: 42)
208208
}
209-
func frobnicate2() -> Bar<_, _> {
209+
func frobnicate2() -> Bar<_, _> { // error
210210
return Bar(t: 42, u: 42)
211211
}
212212
func frobnicate3() -> Bar {
213213
return Bar<_, _>(t: 42, u: 42)
214214
}
215-
func frobnicate4() -> Bar<_, _> {
215+
func frobnicate4() -> Bar<_, _> { // error
216216
return Bar<_, _>(t: 42, u: 42)
217217
}
218-
func frobnicate5() -> Bar<_, U> {
218+
func frobnicate5() -> Bar<_, U> { // error
219219
return Bar(t: 42, u: 42)
220220
}
221221
func frobnicate6() -> Bar {
222222
return Bar<_, U>(t: 42, u: 42)
223223
}
224-
func frobnicate7() -> Bar<_, _> {
224+
func frobnicate7() -> Bar<_, _> { // error
225225
return Bar<_, U>(t: 42, u: 42)
226226
}
227-
func frobnicate8() -> Bar<_, U> {
227+
func frobnicate8() -> Bar<_, U> { // error
228228
return Bar<_, _>(t: 42, u: 42)
229229
}
230230
}
231231
```
232232

233-
Under this proposal, only `frobnicate`, `frobnicate3` and `frobnicate6` would compile without error (`frobnicate1`, of course, compiles without this proposal as well), since all others have placeholders appearing in at least one position in the function signature.
233+
Under this proposal, only `frobnicate`, `frobnicate3` and `frobnicate6` would compile without error (`frobnicate`, of course, compiles without this proposal as well), since all others have placeholders appearing in at least one position in the function signature.
234234

235235
### Dynamic casts
236236

@@ -326,7 +326,7 @@ An earlier draft of this proposal allowed for the use of placeholders as top-lev
326326
let x: _ = 0.0 // type of x is inferred as Double
327327
```
328328

329-
Compared to other uses of this feature, top-level placeholders are clearly of more limited utility. In type annotations (as above), they merely serve as a slightly more explicit way to indicate "this type is inferred," and they are similarly unhelpful in `as` casts. There is *some* use for top-level placeholders in type expression position, particularly when passing a metatype value as a parameter. For instance, Combine's `setFailureType(to:)` operator could be used with a top-level placeholder to make conversions between failure types more lightweight wen necessary:
329+
Compared to other uses of this feature, top-level placeholders are clearly of more limited utility. In type annotations (as above), they merely serve as a slightly more explicit way to indicate "this type is inferred," and they are similarly unhelpful in `as` casts. There is *some* use for top-level placeholders in type expression position, particularly when passing a metatype value as a parameter. For instance, Combine's `setFailureType(to:)` operator could be used with a top-level placeholder to make conversions between failure types more lightweight when necessary:
330330

331331
```swift
332332
let p: AnyPublisher<Int, Error> = Just<Int>().setFailureType(to: _.self).eraseToAnyPublisher()
@@ -335,7 +335,7 @@ let p: AnyPublisher<Int, Error> = Just<Int>().setFailureType(to: _.self).eraseTo
335335
However, as Xiaodi Wu points out, allowing placeholders in these positions would have the effect of permitting clients to leave out type names in circumstances where library authors intended the type information to be provided explicitly, such as when using `KeyedDecodingContainer.decode(_:forKey:)`. It is not obviously desirable for users to be able to write, e.g.:
336336

337337
```swift
338-
self.someProp = container.decode(_.self, forKey: .someProp)
338+
self.someProp = try container.decode(_.self, forKey: .someProp)
339339
```
340340

341341
Due to the additional considerations here, the author has opted to leave top-level placeholders as a future direction, which could potentially be considered once there is more real-world usage of placeholder types that could inform the benefits and drawbacks.

0 commit comments

Comments
 (0)