Skip to content

Commit 4d6c6e8

Browse files
committed
Sema: Simplify logic for building extension generic signature
1 parent 01a254f commit 4d6c6e8

7 files changed

+95
-107
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 31 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -515,23 +515,19 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) {
515515
/// Generic types
516516
///
517517

518-
/// Form the interface type of an extension from the raw type and the
519-
/// extension's list of generic parameters.
520-
static Type formExtensionInterfaceType(
521-
ExtensionDecl *ext, Type type,
522-
const GenericParamList *genericParams,
523-
SmallVectorImpl<Requirement> &sameTypeReqs,
524-
bool &mustInferRequirements) {
518+
/// Collect additional requirements into \p sameTypeReqs.
519+
static void collectAdditionalExtensionRequirements(
520+
Type type, SmallVectorImpl<Requirement> &sameTypeReqs) {
525521
if (type->is<ErrorType>())
526-
return type;
522+
return;
527523

528524
// Find the nominal type declaration and its parent type.
529525
if (type->is<ProtocolCompositionType>())
530526
type = type->getCanonicalType();
531527

532528
// A parameterized protocol type is not a nominal. Unwrap it to get
533529
// the underlying nominal, and record a same-type requirement for
534-
// the primary associated type.
530+
// the primary associated types.
535531
if (auto *paramProtoTy = type->getAs<ParameterizedProtocolType>()) {
536532
auto *protoTy = paramProtoTy->getBaseType();
537533
type = protoTy;
@@ -544,15 +540,9 @@ static Type formExtensionInterfaceType(
544540
Type parentType = type->getNominalParent();
545541
GenericTypeDecl *genericDecl = type->getAnyGeneric();
546542

547-
// Reconstruct the parent, if there is one.
543+
// Visit the parent type, if there is one.
548544
if (parentType) {
549-
// Build the nested extension type.
550-
auto parentGenericParams = genericDecl->getGenericParams()
551-
? genericParams->getOuterParameters()
552-
: genericParams;
553-
parentType =
554-
formExtensionInterfaceType(ext, parentType, parentGenericParams,
555-
sameTypeReqs, mustInferRequirements);
545+
collectAdditionalExtensionRequirements(parentType, sameTypeReqs);
556546
}
557547

558548
// Find the nominal type.
@@ -563,59 +553,26 @@ static Type formExtensionInterfaceType(
563553
nominal = type->getNominalOrBoundGenericNominal();
564554
}
565555

566-
// Form the result.
567-
Type resultType;
568-
SmallVector<Type, 2> genericArgs;
569-
if (!nominal->isGeneric() || isa<ProtocolDecl>(nominal)) {
570-
resultType = NominalType::get(nominal, parentType,
571-
nominal->getASTContext());
572-
} else if (genericParams) {
573-
auto currentBoundType = type->getAs<BoundGenericType>();
574-
575-
// Form the bound generic type with the type parameters provided.
576-
unsigned gpIndex = 0;
577-
for (auto gp : *genericParams) {
578-
SWIFT_DEFER { ++gpIndex; };
579-
556+
// If we have a bound generic type, add same-type requirements for each of
557+
// its generic arguments.
558+
if (auto currentBoundType = type->getAs<BoundGenericType>()) {
559+
auto *genericParams = currentBoundType->getDecl()->getGenericParams();
560+
for (unsigned gpIndex : indices(genericParams->getParams())) {
561+
auto *gp = genericParams->getParams()[gpIndex];
580562
auto gpType = gp->getDeclaredInterfaceType();
581-
genericArgs.push_back(gpType);
582563

583-
if (currentBoundType) {
584-
sameTypeReqs.emplace_back(RequirementKind::SameType, gpType,
585-
currentBoundType->getGenericArgs()[gpIndex]);
586-
}
564+
sameTypeReqs.emplace_back(RequirementKind::SameType, gpType,
565+
currentBoundType->getGenericArgs()[gpIndex]);
587566
}
588-
589-
resultType = BoundGenericType::get(nominal, parentType, genericArgs);
590567
}
591568

592-
// If we have a typealias, try to form type sugar.
569+
// If we have a passthrough typealias, add the requirements from its
570+
// generic signature.
593571
if (typealias && TypeChecker::isPassThroughTypealias(
594572
typealias, typealias->getUnderlyingType(), nominal)) {
595-
auto typealiasSig = typealias->getGenericSignature();
596-
SubstitutionMap subMap;
597-
if (typealiasSig) {
598-
subMap = typealiasSig->getIdentitySubstitutionMap();
599-
600-
mustInferRequirements = true;
601-
}
602-
603-
resultType = TypeAliasType::get(typealias, parentType, subMap, resultType);
573+
for (auto req : typealias->getGenericSignature().getRequirements())
574+
sameTypeReqs.push_back(req);
604575
}
605-
606-
607-
return resultType;
608-
}
609-
610-
/// Retrieve the generic parameter depth of the extended type.
611-
static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
612-
auto nominal = ext->getSelfNominalTypeDecl();
613-
if (!nominal) return static_cast<unsigned>(-1);
614-
615-
auto sig = nominal->getGenericSignatureOfContext();
616-
if (!sig) return static_cast<unsigned>(-1);
617-
618-
return sig.getGenericParams().back()->getDepth();
619576
}
620577

621578
GenericSignature
@@ -650,7 +607,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
650607
}
651608

652609
bool allowConcreteGenericParams = false;
653-
const auto *genericParams = GC->getGenericParams();
610+
auto *genericParams = GC->getGenericParams();
654611
const auto *where = GC->getTrailingWhereClause();
655612

656613
if (genericParams) {
@@ -695,10 +652,12 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
695652
return GC->getParentForLookup()->getGenericSignatureOfContext();
696653
}
697654

698-
auto parentSig = GC->getParentForLookup()->getGenericSignatureOfContext();
655+
GenericSignature parentSig;
699656
SmallVector<TypeLoc, 2> inferenceSources;
700657
SmallVector<Requirement, 2> sameTypeReqs;
701658
if (auto VD = dyn_cast_or_null<ValueDecl>(GC->getAsDecl())) {
659+
parentSig = GC->getParentForLookup()->getGenericSignatureOfContext();
660+
702661
auto func = dyn_cast<AbstractFunctionDecl>(VD);
703662
auto subscr = dyn_cast<SubscriptDecl>(VD);
704663

@@ -753,38 +712,23 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
753712
}
754713
}
755714
} else if (auto *ext = dyn_cast<ExtensionDecl>(GC)) {
756-
// Form the interface type of the extension so we can use it as an inference
757-
// source.
758-
//
759-
// FIXME: Push this into the "get interface type" request.
760-
bool mustInferRequirements = false;
761-
Type extInterfaceType =
762-
formExtensionInterfaceType(ext, ext->getExtendedType(),
763-
genericParams, sameTypeReqs,
764-
mustInferRequirements);
765-
766-
auto cannotReuseNominalSignature = [&]() -> bool {
767-
const auto finalDepth = genericParams->getParams().back()->getDepth();
768-
return mustInferRequirements
769-
|| !sameTypeReqs.empty()
770-
|| ext->getTrailingWhereClause()
771-
|| (getExtendedTypeGenericDepth(ext) != finalDepth);
772-
};
715+
parentSig = ext->getExtendedNominal()->getGenericSignatureOfContext();
716+
genericParams = nullptr;
717+
718+
collectAdditionalExtensionRequirements(ext->getExtendedType(), sameTypeReqs);
773719

774-
// Re-use the signature of the type being extended by default.
775-
if (!cannotReuseNominalSignature()) {
776-
return ext->getSelfNominalTypeDecl()->getGenericSignatureOfContext();
720+
// Re-use the signature of the type being extended by default.
721+
if (sameTypeReqs.empty() && !ext->getTrailingWhereClause()) {
722+
return parentSig;
777723
}
778724

779725
// Allow parameters to be equated with concrete types.
780726
allowConcreteGenericParams = true;
781-
782-
inferenceSources.emplace_back(nullptr, extInterfaceType);
783727
}
784728

785729
auto request = InferredGenericSignatureRequest{
786730
GC->getParentModule(), parentSig.getPointer(),
787-
GC->getGenericParams(), WhereClauseOwner(GC),
731+
genericParams, WhereClauseOwner(GC),
788732
sameTypeReqs, inferenceSources,
789733
allowConcreteGenericParams};
790734
auto sig = evaluateOrDefault(ctx.evaluator, request,

test/Generics/conditional_conformances.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct RedundantSuper<T: P4> {}
5555
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper
5656
// CHECK-NEXT: (normal_conformance type=RedundantSuper<T> protocol=P2)
5757
extension RedundantSuper: P2 where T: P1 {}
58+
// expected-warning@-1 {{redundant conformance constraint 'T' : 'P1'}}
5859

5960
struct OverlappingSub<T: P1> {}
6061
// CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub
@@ -187,6 +188,7 @@ struct ClassLessSpecific<T: C3> {}
187188
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific
188189
// CHECK-NEXT: (normal_conformance type=ClassLessSpecific<T> protocol=P2)
189190
extension ClassLessSpecific: P2 where T: C1 {}
191+
// expected-warning@-1 {{redundant superclass constraint 'T' : 'C1'}}
190192

191193

192194
// Inherited conformances:
@@ -330,6 +332,8 @@ struct RedundancyOrderDependenceGood<T: P1, U> {}
330332
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceGood<T, U> protocol=P2
331333
// CHECK-NEXT: same_type: T U)
332334
extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {}
335+
// expected-warning@-1 {{redundant conformance constraint 'U' : 'P1'}}
336+
333337
struct RedundancyOrderDependenceBad<T, U: P1> {}
334338
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad
335339
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad

test/SourceKit/DocSupport/doc_swift_module.swift.response

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
13011301
{
13021302
key.kind: source.lang.swift.ref.generic_type_param,
13031303
key.name: "Self",
1304-
key.usr: "s:4cake4ProtPAASi7ElementRtzrlE4Selfxmfp",
1304+
key.usr: "s:4cake4ProtP4Selfxmfp",
13051305
key.offset: 1595,
13061306
key.length: 4
13071307
},
@@ -1649,7 +1649,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
16491649
{
16501650
key.kind: source.lang.swift.ref.generic_type_param,
16511651
key.name: "Wrapped",
1652-
key.usr: "s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp",
1652+
key.usr: "s:4cake2S3V7Wrappedxmfp",
16531653
key.offset: 2041,
16541654
key.length: 7
16551655
},
@@ -2557,7 +2557,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
25572557
],
25582558
key.offset: 1574,
25592559
key.length: 63,
2560-
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:4cake4ProtP\">Prot</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:4cake4ProtPAASi7ElementRtzrlE4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:4cake4ProtP7ElementQa\">Element</ref.associatedtype> == <ref.struct usr=\"s:Si\">Int</ref.struct></decl.generic_type_requirement></decl.extension.protocol>",
2560+
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:4cake4ProtP\">Prot</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:4cake4ProtP4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:4cake4ProtP7ElementQa\">Element</ref.associatedtype> == <ref.struct usr=\"s:Si\">Int</ref.struct></decl.generic_type_requirement></decl.extension.protocol>",
25612561
key.extends: {
25622562
key.kind: source.lang.swift.ref.protocol,
25632563
key.name: "Prot",
@@ -2758,14 +2758,19 @@ func shouldPrintAnyAsKeyword(x x: Any)
27582758
},
27592759
{
27602760
key.kind: source.lang.swift.decl.extension.struct,
2761+
key.generic_params: [
2762+
{
2763+
key.name: "Wrapped"
2764+
}
2765+
],
27612766
key.generic_requirements: [
27622767
{
27632768
key.description: "Wrapped : P6"
27642769
}
27652770
],
27662771
key.offset: 2022,
27672772
key.length: 80,
2768-
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:4cake2S3V\">S3</ref.struct> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp\">Wrapped</ref.generic_type_param> : <ref.protocol usr=\"s:4cake2P6P\">P6</ref.protocol></decl.generic_type_requirement>",
2773+
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:4cake2S3V\">S3</ref.struct> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:4cake2S3V7Wrappedxmfp\">Wrapped</ref.generic_type_param> : <ref.protocol usr=\"s:4cake2P6P\">P6</ref.protocol></decl.generic_type_requirement>",
27692774
key.extends: {
27702775
key.kind: source.lang.swift.ref.struct,
27712776
key.name: "S3",

test/SourceKit/DocSupport/doc_swift_module1.swift.response

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ extension Dictionary.Keys where Key : cake1.P1 {
569569
{
570570
key.kind: source.lang.swift.ref.generic_type_param,
571571
key.name: "Self",
572-
key.usr: "s:5cake12P2PA2A2P3RzrlE4Selfxmfp",
572+
key.usr: "s:5cake12P2P4Selfxmfp",
573573
key.offset: 670,
574574
key.length: 4
575575
},
@@ -671,7 +671,7 @@ extension Dictionary.Keys where Key : cake1.P1 {
671671
{
672672
key.kind: source.lang.swift.ref.generic_type_param,
673673
key.name: "Key",
674-
key.usr: "s:SD4KeysV5cake1AC2P1RzrlE3Keyxmfp",
674+
key.usr: "s:SD3Keyxmfp",
675675
key.offset: 836,
676676
key.length: 3
677677
},
@@ -1038,7 +1038,7 @@ extension Dictionary.Keys where Key : cake1.P1 {
10381038
],
10391039
key.offset: 651,
10401040
key.length: 64,
1041-
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:5cake12P2P\">P2</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:5cake12P2PA2A2P3RzrlE4Selfxmfp\">Self</ref.generic_type_param> : <ref.protocol usr=\"s:5cake12P3P\">P3</ref.protocol></decl.generic_type_requirement></decl.extension.protocol>",
1041+
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:5cake12P2P\">P2</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:5cake12P2P4Selfxmfp\">Self</ref.generic_type_param> : <ref.protocol usr=\"s:5cake12P3P\">P3</ref.protocol></decl.generic_type_requirement></decl.extension.protocol>",
10421042
key.extends: {
10431043
key.kind: source.lang.swift.ref.protocol,
10441044
key.name: "P2",
@@ -1110,6 +1110,14 @@ extension Dictionary.Keys where Key : cake1.P1 {
11101110
},
11111111
{
11121112
key.kind: source.lang.swift.decl.extension.struct,
1113+
key.generic_params: [
1114+
{
1115+
key.name: "Key"
1116+
},
1117+
{
1118+
key.name: "Value"
1119+
}
1120+
],
11131121
key.generic_requirements: [
11141122
{
11151123
key.description: "Key : Hashable"
@@ -1120,7 +1128,7 @@ extension Dictionary.Keys where Key : cake1.P1 {
11201128
],
11211129
key.offset: 804,
11221130
key.length: 66,
1123-
key.fully_annotated_decl: "<decl.extension.struct><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.struct usr=\"s:SD\">Dictionary</ref.struct>.<ref.struct usr=\"s:SD4KeysV\">Keys</ref.struct></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:SD4KeysV5cake1AC2P1RzrlE3Keyxmfp\">Key</ref.generic_type_param> : <ref.protocol usr=\"s:5cake12P1P\">P1</ref.protocol></decl.generic_type_requirement></decl.extension.struct>",
1131+
key.fully_annotated_decl: "<decl.extension.struct><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.struct usr=\"s:SD\">Dictionary</ref.struct>.<ref.struct usr=\"s:SD4KeysV\">Keys</ref.struct></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:SD3Keyxmfp\">Key</ref.generic_type_param> : <ref.protocol usr=\"s:5cake12P1P\">P1</ref.protocol></decl.generic_type_requirement></decl.extension.struct>",
11241132
key.extends: {
11251133
key.kind: source.lang.swift.ref.struct,
11261134
key.name: "Keys",

0 commit comments

Comments
 (0)