Skip to content

Commit 784d760

Browse files
committed
Correct @sendable variance for witnesses
It previously treated parameters and return types as the same, instead of properly handling variance.
1 parent 07d0cfa commit 784d760

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,25 @@ getTypesToCompare(ValueDecl *reqt, Type reqtType, bool reqtTypeIsIUO,
155155
// function types that aren't in a parameter can be Sendable or not.
156156
// FIXME: Should we check for a Sendable bound on the requirement type?
157157
bool inRequirement = (adjustment != TypeAdjustment::NoescapeToEscaping);
158-
(void)adjustInferredAssociatedType(adjustment, reqtType, inRequirement);
158+
Type adjustedReqtType =
159+
adjustInferredAssociatedType(adjustment, reqtType, inRequirement);
159160

160161
bool inWitness = false;
161162
Type adjustedWitnessType =
162163
adjustInferredAssociatedType(adjustment, witnessType, inWitness);
163-
if (inWitness && !inRequirement)
164-
witnessType = adjustedWitnessType;
164+
165+
switch (variance) {
166+
case VarianceKind::None:
167+
break;
168+
case VarianceKind::Covariant:
169+
if (inRequirement && !inWitness)
170+
reqtType = adjustedReqtType;
171+
break;
172+
case VarianceKind::Contravariant:
173+
if (inWitness && !inRequirement)
174+
witnessType = adjustedWitnessType;
175+
break;
176+
}
165177
};
166178

167179
applyAdjustment(TypeAdjustment::NoescapeToEscaping);

test/attr/attr_concurrent.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,17 @@ class SubSendable: SuperSendable {
139139
override func runnableInBackground() -> () -> Void { fatalError() } // expected-error {{method does not override any method from its superclass}}
140140
override func runnableInForeground() -> @Sendable () -> Void { fatalError() }
141141
}
142+
143+
protocol AbstractSendable {
144+
func runsInBackground(_: @Sendable () -> Void)
145+
func runsInForeground(_: () -> Void) // expected-note {{protocol requires function 'runsInForeground' with type '(() -> Void) -> ()'; do you want to add a stub?}}
146+
func runnableInBackground() -> @Sendable () -> Void // expected-note {{protocol requires function 'runnableInBackground()' with type '() -> @Sendable () -> Void'; do you want to add a stub?}}
147+
func runnableInForeground() -> () -> Void
148+
}
149+
150+
struct ConcreteSendable: AbstractSendable { // expected-error {{type 'ConcreteSendable' does not conform to protocol 'AbstractSendable'}}
151+
func runsInBackground(_: () -> Void) {}
152+
func runsInForeground(_: @Sendable () -> Void) {} // expected-note {{candidate has non-matching type '(@Sendable () -> Void) -> ()'}}
153+
func runnableInBackground() -> () -> Void { fatalError() } // expected-note {{candidate has non-matching type '() -> () -> Void'}}
154+
func runnableInForeground() -> @Sendable () -> Void { fatalError() }
155+
}

0 commit comments

Comments
 (0)