You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a requirement calls for a parameter's function type to be @sendable, Swift will now permit a witness that does *not* make that parameter @sendable. This is fine because @sendable does not affect the calling convention and the witness may not need to exploit the opportunity to send the closure anywhere.
In other words, this code is now valid:
```
protocol P {
func fn(_: @sendable () -> Void)
}
struct S: P {
func fn(_: () -> Void)
}
```
There's an edge case where this still isn't allowed when an associated type is @sendable.
Copy file name to clipboardExpand all lines: test/decl/protocol/conforms/associated_type.swift
+44-2Lines changed: 44 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -33,22 +33,40 @@ class Foo: FooType {
33
33
}
34
34
35
35
// rdar://problem/35297911: noescape function types
36
+
// (and @Sendable equivalents of some cases)
36
37
protocolP1{
37
38
associatedtypeA
38
39
39
-
func f(_:A)
40
+
func f(_:A) // expected-note {{protocol requires function 'f' with type '(@escaping SendableX1b.A) -> ()' (aka '(@escaping @Sendable (Int) -> Int) -> ()'); do you want to add a stub?}}
40
41
}
41
42
42
43
structX1a:P1{
43
44
func f(_:@escaping(Int)->Int){}
44
45
}
45
46
47
+
structSendableX1a:P1{
48
+
func f(_:@Sendable(Int)->Int){}
49
+
}
50
+
46
51
structX1b:P1{
47
52
typealiasA=(Int)->Int
48
53
49
54
func f(_:@escaping(Int)->Int){}
50
55
}
51
56
57
+
// FIXME: We would like this case to work. It doesn't because, by the time we
58
+
// actually look through the DependentMemberType and see that `A` is a
59
+
// @Sendable function type, we are simplifying a Bind constraint and
60
+
// don't have the flexibility to adjust the witness's type. Perhaps
61
+
// instead of adjusting types before adding them to the constraint
62
+
// graph, we should introduce a new constraint kind that allows only a
63
+
// witness's adjustments.
64
+
structSendableX1b:P1{ // expected-error {{type 'SendableX1b' does not conform to protocol 'P1'}}
65
+
typealiasA=@Sendable(Int)->Int
66
+
67
+
func f(_:(Int)->Int){} // expected-note {{candidate has non-matching type '((Int) -> Int) -> ()'}}
68
+
}
69
+
52
70
structX1c:P1{
53
71
typealiasA=(Int)->Int
54
72
@@ -60,17 +78,41 @@ struct X1d : P1 {
60
78
}
61
79
62
80
protocolP2{
63
-
func f(_:(Int)->Int) // expected-note{{protocol requires function 'f' with type '((Int) -> Int) -> ()'; do you want to add a stub?}}
81
+
func f(_:(Int)->Int) // expected-note 3 {{protocol requires function 'f' with type '((Int) -> Int) -> ()'; do you want to add a stub?}}
82
+
func g(_:@escaping(Int)->Int) // expected-note 2 {{protocol requires function 'g' with type '(@escaping (Int) -> Int) -> ()'; do you want to add a stub?}}
83
+
func h(_:@Sendable(Int)->Int) // expected-note 2 {{protocol requires function 'h' with type '(@Sendable (Int) -> Int) -> ()'; do you want to add a stub?}}
84
+
func i(_:@escaping@Sendable(Int)->Int)
64
85
}
65
86
66
87
structX2a:P2{
67
88
func f(_:(Int)->Int){}
89
+
func g(_:(Int)->Int){}
90
+
func h(_:(Int)->Int){}
91
+
func i(_:(Int)->Int){}
68
92
}
69
93
70
94
structX2b:P2{ // expected-error{{type 'X2b' does not conform to protocol 'P2'}}
71
95
func f(_:@escaping(Int)->Int){} // expected-note{{candidate has non-matching type '(@escaping (Int) -> Int) -> ()'}}
96
+
func g(_:@escaping(Int)->Int){}
97
+
func h(_:@escaping(Int)->Int){} // expected-note{{candidate has non-matching type '(@escaping (Int) -> Int) -> ()'}}
98
+
func i(_:@escaping(Int)->Int){}
72
99
}
73
100
101
+
structX2c:P2{ // expected-error{{type 'X2c' does not conform to protocol 'P2'}}
102
+
func f(_:@Sendable(Int)->Int){} // expected-note{{candidate has non-matching type '(@Sendable (Int) -> Int) -> ()'}}
103
+
func g(_:@Sendable(Int)->Int){} // expected-note{{candidate has non-matching type '(@Sendable (Int) -> Int) -> ()'}}
104
+
func h(_:@Sendable(Int)->Int){}
105
+
func i(_:@Sendable(Int)->Int){}
106
+
}
107
+
108
+
structX2d:P2{ // expected-error{{type 'X2d' does not conform to protocol 'P2'}}
109
+
func f(_:@escaping@Sendable(Int)->Int){} // expected-note{{candidate has non-matching type '(@escaping @Sendable (Int) -> Int) -> ()'}}
110
+
func g(_:@escaping@Sendable(Int)->Int){} // expected-note{{candidate has non-matching type '(@escaping @Sendable (Int) -> Int) -> ()'}}
111
+
func h(_:@escaping@Sendable(Int)->Int){} // expected-note{{candidate has non-matching type '(@escaping @Sendable (Int) -> Int) -> ()'}}
0 commit comments