Skip to content

Commit 3b0c310

Browse files
authored
Merge pull request #42309 from slavapestov/rqm-sendable-conformance-5.7
RequirementMachine: Allow missing Sendable conformances [5.7]
2 parents d3923da + 9bf8797 commit 3b0c310

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

lib/AST/RequirementMachine/ConcreteContraction.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ Optional<Type> ConcreteContraction::substTypeParameter(
223223

224224
auto conformance = ((*substBaseType)->isTypeParameter()
225225
? ProtocolConformanceRef(proto)
226-
: module->lookupConformance(*substBaseType, proto));
226+
: module->lookupConformance(*substBaseType, proto,
227+
/*allowMissing=*/true));
227228

228229
// The base type doesn't conform, in which case the requirement remains
229230
// unsubstituted.
@@ -362,8 +363,25 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
362363

363364
auto *proto = req.getProtocolDecl();
364365
auto *module = proto->getParentModule();
366+
367+
// For conformance to 'Sendable', allow synthesis of a missing conformance
368+
// if the generic parameter is concrete, that is, if we're looking at a
369+
// signature of the form 'T == Foo, T : Sendable'.
370+
//
371+
// Otherwise, we have a superclass requirement, like 'T : C, T : Sendable';
372+
// don't synthesize the conformance in this case since dropping
373+
// 'T : Sendable' would be incorrect; we want to ensure that we only admit
374+
// subclasses of 'C' which are 'Sendable'.
375+
bool allowMissing = false;
376+
if (auto *rootParam = firstType->getAs<GenericTypeParamType>()) {
377+
auto key = GenericParamKey(rootParam);
378+
if (ConcreteTypes.count(key) > 0)
379+
allowMissing = true;
380+
}
381+
365382
if (!substFirstType->isTypeParameter() &&
366-
!module->lookupConformance(substFirstType, proto)) {
383+
!module->lookupConformance(substFirstType, proto,
384+
allowMissing)) {
367385
// Handle the case of <T where T : P, T : C> where C is a class and
368386
// C does not conform to P by leaving the conformance requirement
369387
// unsubstituted.
@@ -664,4 +682,4 @@ bool swift::rewriting::performConcreteContraction(
664682
ConcreteContraction concreteContraction(debug);
665683
return concreteContraction.performConcreteContraction(
666684
requirements, result, errors);
667-
}
685+
}

lib/AST/RequirementMachine/ConcreteTypeWitness.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,19 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
143143
// or pass the correct one down in here.
144144
auto *module = proto->getParentModule();
145145

146+
// For conformance to 'Sendable', allow synthesis of a missing conformance
147+
// if the requirement is a concrete type requirement, that is, if we're
148+
// looking at a signature of the form 'T == Foo, T : Sendable'.
149+
//
150+
// Otherwise, we have a superclass requirement, like 'T : C, T : Sendable'.
151+
// Don't synthesize the conformance in this case since dropping
152+
// 'T : Sendable' would be incorrect; we want to ensure that we only admit
153+
// subclasses of 'C' which are 'Sendable'.
154+
bool allowMissing = (requirementKind == RequirementKind::SameType);
155+
146156
auto conformance = module->lookupConformance(concreteType,
147-
const_cast<ProtocolDecl *>(proto));
157+
const_cast<ProtocolDecl *>(proto),
158+
allowMissing);
148159
if (conformance.isInvalid()) {
149160
// For superclass rules, it is totally fine to have a signature like:
150161
//

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ static void desugarConformanceRequirement(Type subjectType, Type constraintType,
292292
// Check if the subject type actually conforms.
293293
auto *protoDecl = constraintType->castTo<ProtocolType>()->getDecl();
294294
auto *module = protoDecl->getParentModule();
295-
auto conformance = module->lookupConformance(subjectType, protoDecl);
295+
auto conformance = module->lookupConformance(
296+
subjectType, protoDecl, /*allowMissing=*/true);
296297
if (conformance.isInvalid()) {
297298
errors.push_back(RequirementError::forInvalidRequirementSubject(
298299
{RequirementKind::Conformance, subjectType, constraintType}, loc));
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
3+
4+
// REQUIRES: concurrency
5+
6+
// rdar://91174106 - allow missing Sendable conformances when extending a
7+
// type generically.
8+
// FIXME: Should warn because of missing Sendable, but currently is silent
9+
// because we aren't checking conformance availability here yet.
10+
class C {}
11+
12+
struct G1<T: Sendable> {}
13+
14+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=G1
15+
// CHECK-NEXT: Generic signature: <T where T == C>
16+
extension G1 where T == C {}
17+
18+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=G1
19+
// CHECK-NEXT: Generic signature: <T where T : C, T : Sendable>
20+
extension G1 where T : C {}
21+
22+
protocol P {
23+
associatedtype A
24+
}
25+
26+
struct G2<T : P> where T.A : Sendable {}
27+
28+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=G2
29+
// CHECK-NEXT: Generic signature: <T where T : P, T.[P]A == C>
30+
extension G2 where T.A == C {}
31+
32+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=G2
33+
// CHECK-NEXT: Generic signature: <T where T : P, T.[P]A : C, T.[P]A : Sendable>
34+
extension G2 where T.A : C {}

0 commit comments

Comments
 (0)