Skip to content

Commit bc43cdd

Browse files
committed
RequirementMachine: Generalize hack that allows associated type inheritance clauses to reference protocol typealiases
We want to allow this for all conformance requirements written in protocols or the `where` clause of protocol extensions. Fixes rdar://problem/91304291.
1 parent 25232e8 commit bc43cdd

File tree

6 files changed

+80
-67
lines changed

6 files changed

+80
-67
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,6 @@ struct WhereClauseOwner {
604604
return !(lhs == rhs);
605605
}
606606

607-
public:
608607
/// Retrieve the array of requirements.
609608
MutableArrayRef<RequirementRepr> getRequirements() const;
610609

@@ -1903,8 +1902,7 @@ class InferredGenericSignatureRequest :
19031902
/// InferredGenericSignatureRequest.
19041903
class InferredGenericSignatureRequestRQM :
19051904
public SimpleRequest<InferredGenericSignatureRequestRQM,
1906-
GenericSignatureWithError (ModuleDecl *,
1907-
const GenericSignatureImpl *,
1905+
GenericSignatureWithError (const GenericSignatureImpl *,
19081906
GenericParamList *,
19091907
WhereClauseOwner,
19101908
SmallVector<Requirement, 2>,
@@ -1920,7 +1918,6 @@ class InferredGenericSignatureRequestRQM :
19201918
// Evaluation.
19211919
GenericSignatureWithError
19221920
evaluate(Evaluator &evaluator,
1923-
ModuleDecl *parentModule,
19241921
const GenericSignatureImpl *baseSignature,
19251922
GenericParamList *genericParams,
19261923
WhereClauseOwner whereClause,

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8464,7 +8464,6 @@ InferredGenericSignatureRequest::evaluate(
84648464
return evaluateOrDefault(
84658465
ctx.evaluator,
84668466
InferredGenericSignatureRequestRQM{
8467-
parentModule,
84688467
parentSig,
84698468
genericParams,
84708469
whereClause,

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
#include "llvm/ADT/SmallVector.h"
161161
#include "llvm/ADT/SetVector.h"
162162
#include "RewriteContext.h"
163+
#include "NameLookup.h"
163164

164165
using namespace swift;
165166
using namespace rewriting;
@@ -384,12 +385,40 @@ swift::rewriting::desugarRequirement(Requirement req, SourceLoc loc,
384385
// Requirement realization and inference.
385386
//
386387

387-
static void realizeTypeRequirement(Type subjectType, Type constraintType,
388+
static void realizeTypeRequirement(DeclContext *dc,
389+
Type subjectType, Type constraintType,
388390
SourceLoc loc,
389391
SmallVectorImpl<StructuralRequirement> &result,
390392
SmallVectorImpl<RequirementError> &errors) {
391393
SmallVector<Requirement, 2> reqs;
392394

395+
// The GenericSignatureBuilder allowed the right hand side of a
396+
// conformance or superclass requirement to reference a protocol
397+
// typealias whose underlying type was a protocol or class.
398+
//
399+
// Since protocol typealiases resolve to DependentMemberTypes in
400+
// ::Structural mode, this relied on the GSB's "delayed requirements"
401+
// mechanism.
402+
//
403+
// The RequirementMachine does not have an equivalent, and cannot really
404+
// support that because we need to collect the protocols mentioned on
405+
// the right hand sides of conformance requirements ahead of time.
406+
//
407+
// However, we can support it in simple cases where the typealias is
408+
// defined in the protocol itself and is accessed as a member of 'Self'.
409+
if (auto *proto = dc->getSelfProtocolDecl()) {
410+
if (auto memberType = constraintType->getAs<DependentMemberType>()) {
411+
if (memberType->getBase()->isEqual(proto->getSelfInterfaceType())) {
412+
SmallVector<TypeDecl *, 1> result;
413+
lookupConcreteNestedType(proto, memberType->getName(), result);
414+
auto *typeDecl = findBestConcreteNestedType(result);
415+
if (auto *aliasDecl = dyn_cast_or_null<TypeAliasDecl>(typeDecl)) {
416+
constraintType = aliasDecl->getUnderlyingType();
417+
}
418+
}
419+
}
420+
}
421+
393422
if (constraintType->isConstraintType()) {
394423
// Handle conformance requirements.
395424
desugarConformanceRequirement(subjectType, constraintType, loc, reqs, errors);
@@ -534,18 +563,20 @@ void swift::rewriting::inferRequirements(
534563
/// Desugar a requirement and perform requirement inference if requested
535564
/// to obtain zero or more structural requirements.
536565
void swift::rewriting::realizeRequirement(
566+
DeclContext *dc,
537567
Requirement req, RequirementRepr *reqRepr,
538-
ModuleDecl *moduleForInference,
568+
bool shouldInferRequirements,
539569
SmallVectorImpl<StructuralRequirement> &result,
540570
SmallVectorImpl<RequirementError> &errors) {
541571
auto firstType = req.getFirstType();
542572
auto loc = (reqRepr ? reqRepr->getSeparatorLoc() : SourceLoc());
573+
auto *moduleForInference = dc->getParentModule();
543574

544575
switch (req.getKind()) {
545576
case RequirementKind::Superclass:
546577
case RequirementKind::Conformance: {
547578
auto secondType = req.getSecondType();
548-
if (moduleForInference) {
579+
if (shouldInferRequirements) {
549580
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
550581
: SourceLoc());
551582
inferRequirements(firstType, firstLoc, moduleForInference, result);
@@ -555,12 +586,12 @@ void swift::rewriting::realizeRequirement(
555586
inferRequirements(secondType, secondLoc, moduleForInference, result);
556587
}
557588

558-
realizeTypeRequirement(firstType, secondType, loc, result, errors);
589+
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors);
559590
break;
560591
}
561592

562593
case RequirementKind::Layout: {
563-
if (moduleForInference) {
594+
if (shouldInferRequirements) {
564595
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
565596
: SourceLoc());
566597
inferRequirements(firstType, firstLoc, moduleForInference, result);
@@ -578,7 +609,7 @@ void swift::rewriting::realizeRequirement(
578609

579610
case RequirementKind::SameType: {
580611
auto secondType = req.getSecondType();
581-
if (moduleForInference) {
612+
if (shouldInferRequirements) {
582613
auto firstLoc = (reqRepr ? reqRepr->getFirstTypeRepr()->getStartLoc()
583614
: SourceLoc());
584615
inferRequirements(firstType, firstLoc, moduleForInference, result);
@@ -602,11 +633,13 @@ void swift::rewriting::realizeRequirement(
602633
/// Collect structural requirements written in the inheritance clause of an
603634
/// AssociatedTypeDecl or GenericTypeParamDecl.
604635
void swift::rewriting::realizeInheritedRequirements(
605-
TypeDecl *decl, Type type, ModuleDecl *moduleForInference,
636+
TypeDecl *decl, Type type, bool shouldInferRequirements,
606637
SmallVectorImpl<StructuralRequirement> &result,
607638
SmallVectorImpl<RequirementError> &errors) {
608639
auto &ctx = decl->getASTContext();
609640
auto inheritedTypes = decl->getInherited();
641+
auto *dc = decl->getInnermostDeclContext();
642+
auto *moduleForInference = dc->getParentModule();
610643

611644
for (unsigned index : indices(inheritedTypes)) {
612645
Type inheritedType
@@ -616,41 +649,13 @@ void swift::rewriting::realizeInheritedRequirements(
616649
Type());
617650
if (!inheritedType) continue;
618651

619-
// The GenericSignatureBuilder allowed an associated type's inheritance
620-
// clause to reference a protocol typealias whose underlying type was a
621-
// protocol or class.
622-
//
623-
// Since protocol typealiases resolve to DependentMemberTypes in
624-
// ::Structural mode, this relied on the GSB's "delayed requirements"
625-
// mechanism.
626-
//
627-
// The RequirementMachine does not have an equivalent, and cannot really
628-
// support that because we need to collect the protocols mentioned on
629-
// the right hand sides of conformance requirements ahead of time.
630-
//
631-
// However, we can support it in simple cases where the typealias is
632-
// defined in the protocol itself and is accessed as a member of 'Self'.
633-
if (auto *assocTypeDecl = dyn_cast<AssociatedTypeDecl>(decl)) {
634-
if (auto memberType = inheritedType->getAs<DependentMemberType>()) {
635-
if (memberType->getBase()->isEqual(
636-
assocTypeDecl->getProtocol()->getSelfInterfaceType())) {
637-
inheritedType
638-
= evaluateOrDefault(ctx.evaluator,
639-
InheritedTypeRequest{decl, index,
640-
TypeResolutionStage::Interface},
641-
Type());
642-
if (!inheritedType) continue;
643-
}
644-
}
645-
}
646-
647652
auto *typeRepr = inheritedTypes[index].getTypeRepr();
648653
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
649-
if (moduleForInference) {
654+
if (shouldInferRequirements) {
650655
inferRequirements(inheritedType, loc, moduleForInference, result);
651656
}
652657

653-
realizeTypeRequirement(type, inheritedType, loc, result, errors);
658+
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
654659
}
655660
}
656661

@@ -823,14 +828,14 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
823828
auto selfTy = proto->getSelfInterfaceType();
824829

825830
realizeInheritedRequirements(proto, selfTy,
826-
/*moduleForInference=*/nullptr,
831+
/*inferRequirements=*/false,
827832
result, errors);
828833

829834
// Add requirements from the protocol's own 'where' clause.
830835
WhereClauseOwner(proto).visitRequirements(TypeResolutionStage::Structural,
831836
[&](const Requirement &req, RequirementRepr *reqRepr) {
832-
realizeRequirement(req, reqRepr,
833-
/*moduleForInference=*/nullptr,
837+
realizeRequirement(proto, req, reqRepr,
838+
/*inferRequirements=*/false,
834839
result, errors);
835840
return false;
836841
});
@@ -855,15 +860,15 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
855860
// Add requirements placed directly on this associated type.
856861
auto assocType = assocTypeDecl->getDeclaredInterfaceType();
857862
realizeInheritedRequirements(assocTypeDecl, assocType,
858-
/*moduleForInference=*/nullptr,
863+
/*inferRequirements=*/false,
859864
result, errors);
860865

861866
// Add requirements from this associated type's where clause.
862867
WhereClauseOwner(assocTypeDecl).visitRequirements(
863868
TypeResolutionStage::Structural,
864869
[&](const Requirement &req, RequirementRepr *reqRepr) {
865-
realizeRequirement(req, reqRepr,
866-
/*moduleForInference=*/nullptr,
870+
realizeRequirement(proto, req, reqRepr,
871+
/*inferRequirements=*/false,
867872
result, errors);
868873
return false;
869874
});

lib/AST/RequirementMachine/RequirementLowering.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ void desugarRequirement(Requirement req, SourceLoc loc,
4545
void inferRequirements(Type type, SourceLoc loc, ModuleDecl *module,
4646
SmallVectorImpl<StructuralRequirement> &result);
4747

48-
void realizeRequirement(Requirement req, RequirementRepr *reqRepr,
49-
ModuleDecl *moduleForInference,
48+
void realizeRequirement(DeclContext *dc,
49+
Requirement req, RequirementRepr *reqRepr,
50+
bool shouldInferRequirements,
5051
SmallVectorImpl<StructuralRequirement> &result,
5152
SmallVectorImpl<RequirementError> &errors);
5253

5354
void realizeInheritedRequirements(TypeDecl *decl, Type type,
54-
ModuleDecl *moduleForInference,
55+
bool shouldInferRequirements,
5556
SmallVectorImpl<StructuralRequirement> &result,
5657
SmallVectorImpl<RequirementError> &errors);
5758

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,6 @@ AbstractGenericSignatureRequestRQM::evaluate(
685685
GenericSignatureWithError
686686
InferredGenericSignatureRequestRQM::evaluate(
687687
Evaluator &evaluator,
688-
ModuleDecl *parentModule,
689688
const GenericSignatureImpl *parentSigImpl,
690689
GenericParamList *genericParamList,
691690
WhereClauseOwner whereClause,
@@ -694,8 +693,6 @@ InferredGenericSignatureRequestRQM::evaluate(
694693
bool allowConcreteGenericParams) const {
695694
GenericSignature parentSig(parentSigImpl);
696695

697-
auto &ctx = parentModule->getASTContext();
698-
699696
SmallVector<GenericTypeParamType *, 4> genericParams(
700697
parentSig.getGenericParams().begin(),
701698
parentSig.getGenericParams().end());
@@ -705,9 +702,12 @@ InferredGenericSignatureRequestRQM::evaluate(
705702
for (const auto &req : parentSig.getRequirements())
706703
requirements.push_back({req, SourceLoc(), /*wasInferred=*/false});
707704

705+
DeclContext *lookupDC = nullptr;
706+
708707
const auto visitRequirement = [&](const Requirement &req,
709708
RequirementRepr *reqRepr) {
710-
realizeRequirement(req, reqRepr, parentModule, requirements, errors);
709+
realizeRequirement(lookupDC, req, reqRepr, /*inferRequirements=*/true,
710+
requirements, errors);
711711
return false;
712712
};
713713

@@ -738,11 +738,12 @@ InferredGenericSignatureRequestRQM::evaluate(
738738
->castTo<GenericTypeParamType>();
739739
genericParams.push_back(gpType);
740740

741-
realizeInheritedRequirements(gpDecl, gpType, parentModule,
741+
realizeInheritedRequirements(gpDecl, gpType,
742+
/*inferRequirements=*/true,
742743
requirements, errors);
743744
}
744745

745-
auto *lookupDC = (*gpList->begin())->getDeclContext();
746+
lookupDC = (*gpList->begin())->getDeclContext();
746747

747748
// Add the generic parameter list's 'where' clause to the builder.
748749
//
@@ -758,6 +759,8 @@ InferredGenericSignatureRequestRQM::evaluate(
758759
// Realize all requirements in the free-standing 'where' clause, if there
759760
// is one.
760761
if (whereClause) {
762+
lookupDC = whereClause.dc;
763+
761764
if (loc.isInvalid())
762765
loc = whereClause.getLoc();
763766

@@ -766,13 +769,16 @@ InferredGenericSignatureRequestRQM::evaluate(
766769
visitRequirement);
767770
}
768771

772+
auto *moduleForInference = lookupDC->getParentModule();
773+
769774
// Perform requirement inference from function parameter and result
770775
// types and such.
771776
for (auto sourcePair : inferenceSources) {
772777
auto *typeRepr = sourcePair.getTypeRepr();
773778
auto loc = typeRepr ? typeRepr->getStartLoc() : SourceLoc();
774779

775-
inferRequirements(sourcePair.getType(), loc, parentModule, requirements);
780+
inferRequirements(sourcePair.getType(), loc, moduleForInference,
781+
requirements);
776782
}
777783

778784
// Finish by adding any remaining requirements. This is used to introduce
@@ -781,6 +787,7 @@ InferredGenericSignatureRequestRQM::evaluate(
781787
for (const auto &req : addedRequirements)
782788
requirements.push_back({req, SourceLoc(), /*wasInferred=*/true});
783789

790+
auto &ctx = moduleForInference->getASTContext();
784791
auto &rewriteCtx = ctx.getRewriteContext();
785792

786793
if (rewriteCtx.getDebugOptions().contains(DebugFlags::Timers)) {

test/Generics/rdar90219229.swift renamed to test/Generics/conformance_requirement_with_protocol_typealias.swift

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
33

44
// CHECK-LABEL: .P@
55
// CHECK-NEXT: Requirement signature: <Self where Self.[P]T : C>
@@ -20,17 +20,21 @@ protocol PBad {
2020
// expected-error@-1 {{type 'Self.T1' constrained to non-protocol, non-class type 'Self.B.A'}}
2121

2222
associatedtype T2 where T2 : A
23-
// expected-error@-1 {{type 'Self.T2' constrained to non-protocol, non-class type 'Self.A'}}
2423
}
2524

26-
// FIXME: Terrible diagnostics.
27-
2825
protocol PWorse {
29-
// expected-error@-1 5{{circular reference}}
30-
// expected-note@-2 9{{through reference here}}
3126
typealias A = C
3227

3328
associatedtype T : Self.A
34-
// expected-note@-1 5{{while resolving type 'Self.A'}}
35-
// expected-note@-2 5{{through reference here}}
3629
}
30+
31+
protocol Q1 {}
32+
protocol Q2 {}
33+
34+
extension P {
35+
typealias B = (Q1 & Q2)
36+
}
37+
38+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=P
39+
// CHECK-NEXT: Generic signature: <Self where Self : P, Self : Q1, Self : Q2>
40+
extension P where Self: B {}

0 commit comments

Comments
 (0)