Skip to content

Commit 672f2d1

Browse files
authored
Merge pull request #63493 from hborla/5.8-preconcurrency-requirement-inference
[5.8][RequirementMachine] Skip `Sendable` conformance requirements from `@preconcurrency` declarations in requirement inference.
2 parents b0980d9 + ddfd73e commit 672f2d1

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,12 @@ namespace {
467467
/// AST walker that infers requirements from type representations.
468468
struct InferRequirementsWalker : public TypeWalker {
469469
ModuleDecl *module;
470+
DeclContext *dc;
470471
SmallVector<Requirement, 2> reqs;
471472
SmallVector<RequirementError, 2> errors;
472473

473-
explicit InferRequirementsWalker(ModuleDecl *module) : module(module) {}
474+
explicit InferRequirementsWalker(ModuleDecl *module, DeclContext *dc)
475+
: module(module), dc(dc) {}
474476

475477
Action walkToTypePre(Type ty) override {
476478
// Unbound generic types are the result of recovered-but-invalid code, and
@@ -482,11 +484,32 @@ struct InferRequirementsWalker : public TypeWalker {
482484
}
483485

484486
Action walkToTypePost(Type ty) override {
487+
// Skip `Sendable` conformance requirements that are inferred from
488+
// `@preconcurrency` declarations.
489+
auto skipRequirement = [&](Requirement req, Decl *fromDecl) {
490+
if (!fromDecl->preconcurrency())
491+
return false;
492+
493+
// If this decl is `@preconcurrency`, include concurrency
494+
// requirements. The explicit annotation directly on the decl
495+
// will still exclude `Sendable` requirements from ABI.
496+
auto *decl = dc->getAsDecl();
497+
if (!decl || decl->preconcurrency())
498+
return false;
499+
500+
return (req.getKind() == RequirementKind::Conformance &&
501+
req.getSecondType()->castTo<ProtocolType>()->getDecl()
502+
->isSpecificProtocol(KnownProtocolKind::Sendable));
503+
};
504+
485505
// Infer from generic typealiases.
486506
if (auto typeAlias = dyn_cast<TypeAliasType>(ty.getPointer())) {
487507
auto decl = typeAlias->getDecl();
488508
auto subMap = typeAlias->getSubstitutionMap();
489509
for (const auto &rawReq : decl->getGenericSignature().getRequirements()) {
510+
if (skipRequirement(rawReq, decl))
511+
continue;
512+
490513
desugarRequirement(rawReq.subst(subMap), SourceLoc(), reqs, errors);
491514
}
492515

@@ -567,6 +590,9 @@ struct InferRequirementsWalker : public TypeWalker {
567590
// Handle the requirements.
568591
// FIXME: Inaccurate TypeReprs.
569592
for (const auto &rawReq : genericSig.getRequirements()) {
593+
if (skipRequirement(rawReq, decl))
594+
continue;
595+
570596
auto req = rawReq.subst(subMap);
571597
desugarRequirement(req, SourceLoc(), reqs, errors);
572598
}
@@ -585,12 +611,13 @@ struct InferRequirementsWalker : public TypeWalker {
585611
/// We automatically infer 'T : Hashable' from the fact that 'struct Set'
586612
/// declares a Hashable requirement on its generic parameter.
587613
void swift::rewriting::inferRequirements(
588-
Type type, SourceLoc loc, ModuleDecl *module,
614+
Type type, SourceLoc loc,
615+
ModuleDecl *module, DeclContext *dc,
589616
SmallVectorImpl<StructuralRequirement> &result) {
590617
if (!type)
591618
return;
592619

593-
InferRequirementsWalker walker(module);
620+
InferRequirementsWalker walker(module, dc);
594621
type.walk(walker);
595622

596623
for (const auto &req : walker.reqs)
@@ -619,11 +646,11 @@ void swift::rewriting::realizeRequirement(
619646
if (shouldInferRequirements) {
620647
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
621648
: SourceLoc());
622-
inferRequirements(firstType, firstLoc, moduleForInference, result);
649+
inferRequirements(firstType, firstLoc, moduleForInference, dc, result);
623650

624651
auto secondLoc = (reqRepr ? reqRepr->getConstraintRepr()->getStartLoc()
625652
: SourceLoc());
626-
inferRequirements(secondType, secondLoc, moduleForInference, result);
653+
inferRequirements(secondType, secondLoc, moduleForInference, dc, result);
627654
}
628655

629656
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors);
@@ -634,7 +661,7 @@ void swift::rewriting::realizeRequirement(
634661
if (shouldInferRequirements) {
635662
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
636663
: SourceLoc());
637-
inferRequirements(firstType, firstLoc, moduleForInference, result);
664+
inferRequirements(firstType, firstLoc, moduleForInference, dc, result);
638665
}
639666

640667
SmallVector<Requirement, 2> reqs;
@@ -652,11 +679,11 @@ void swift::rewriting::realizeRequirement(
652679
if (shouldInferRequirements) {
653680
auto firstLoc = (reqRepr ? reqRepr->getFirstTypeRepr()->getStartLoc()
654681
: SourceLoc());
655-
inferRequirements(firstType, firstLoc, moduleForInference, result);
682+
inferRequirements(firstType, firstLoc, moduleForInference, dc, result);
656683

657684
auto secondLoc = (reqRepr ? reqRepr->getSecondTypeRepr()->getStartLoc()
658685
: SourceLoc());
659-
inferRequirements(secondType, secondLoc, moduleForInference, result);
686+
inferRequirements(secondType, secondLoc, moduleForInference, dc, result);
660687
}
661688

662689
SmallVector<Requirement, 2> reqs;
@@ -700,7 +727,8 @@ void swift::rewriting::realizeInheritedRequirements(
700727
auto *typeRepr = inheritedTypes[index].getTypeRepr();
701728
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
702729
if (shouldInferRequirements) {
703-
inferRequirements(inheritedType, loc, moduleForInference, result);
730+
inferRequirements(inheritedType, loc, moduleForInference,
731+
decl->getInnermostDeclContext(), result);
704732
}
705733

706734
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);

lib/AST/RequirementMachine/RequirementLowering.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void desugarRequirement(Requirement req, SourceLoc loc,
4242
SmallVectorImpl<Requirement> &result,
4343
SmallVectorImpl<RequirementError> &errors);
4444

45-
void inferRequirements(Type type, SourceLoc loc, ModuleDecl *module,
45+
void inferRequirements(Type type, SourceLoc loc,
46+
ModuleDecl *module, DeclContext *dc,
4647
SmallVectorImpl<StructuralRequirement> &result);
4748

4849
void realizeRequirement(DeclContext *dc,

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ InferredGenericSignatureRequest::evaluate(
829829
loc = typeLoc;
830830

831831
inferRequirements(sourcePair.getType(), typeLoc, moduleForInference,
832-
requirements);
832+
lookupDC, requirements);
833833
}
834834

835835
// Finish by adding any remaining requirements. This is used to introduce
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
2+
3+
// CHECK-LABEL: ExistingType
4+
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Sendable>
5+
@preconcurrency
6+
public struct ExistingType<T: Sendable> : Sendable {}
7+
8+
// CHECK-LABEL: existingClient(arg:)
9+
// CHECK: Canonical generic signature: <τ_0_0>
10+
public func existingClient<T>(arg: T.Type) -> ExistingType<T>? { nil }
11+
12+
public typealias Alias = ExistingType
13+
14+
// CHECK-LABEL: existingClient2(arg:)
15+
// CHECK: Canonical generic signature: <τ_0_0>
16+
public func existingClient2<T>(arg: T.Type) -> Alias<T>? { nil }
17+
18+
// CHECK-LABEL: preconcurrencyClient(arg:)
19+
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Sendable>
20+
@preconcurrency
21+
public func preconcurrencyClient<T>(arg: T.Type) -> ExistingType<T>? { nil }

0 commit comments

Comments
 (0)