Skip to content

Commit a07636b

Browse files
authored
Merge pull request #41820 from slavapestov/simpler-extension-generic-signature
Sema: Simplify logic for building extension generic signature
2 parents c9ddfbc + 9aaea55 commit a07636b

6 files changed

+93
-107
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 31 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -468,23 +468,19 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) {
468468
/// Generic types
469469
///
470470

471-
/// Form the interface type of an extension from the raw type and the
472-
/// extension's list of generic parameters.
473-
static Type formExtensionInterfaceType(
474-
ExtensionDecl *ext, Type type,
475-
const GenericParamList *genericParams,
476-
SmallVectorImpl<Requirement> &sameTypeReqs,
477-
bool &mustInferRequirements) {
471+
/// Collect additional requirements into \p sameTypeReqs.
472+
static void collectAdditionalExtensionRequirements(
473+
Type type, SmallVectorImpl<Requirement> &sameTypeReqs) {
478474
if (type->is<ErrorType>())
479-
return type;
475+
return;
480476

481477
// Find the nominal type declaration and its parent type.
482478
if (type->is<ProtocolCompositionType>())
483479
type = type->getCanonicalType();
484480

485481
// A parameterized protocol type is not a nominal. Unwrap it to get
486482
// the underlying nominal, and record a same-type requirement for
487-
// the primary associated type.
483+
// the primary associated types.
488484
if (auto *paramProtoTy = type->getAs<ParameterizedProtocolType>()) {
489485
auto *protoTy = paramProtoTy->getBaseType();
490486
type = protoTy;
@@ -497,15 +493,9 @@ static Type formExtensionInterfaceType(
497493
Type parentType = type->getNominalParent();
498494
GenericTypeDecl *genericDecl = type->getAnyGeneric();
499495

500-
// Reconstruct the parent, if there is one.
496+
// Visit the parent type, if there is one.
501497
if (parentType) {
502-
// Build the nested extension type.
503-
auto parentGenericParams = genericDecl->getGenericParams()
504-
? genericParams->getOuterParameters()
505-
: genericParams;
506-
parentType =
507-
formExtensionInterfaceType(ext, parentType, parentGenericParams,
508-
sameTypeReqs, mustInferRequirements);
498+
collectAdditionalExtensionRequirements(parentType, sameTypeReqs);
509499
}
510500

511501
// Find the nominal type.
@@ -516,59 +506,26 @@ static Type formExtensionInterfaceType(
516506
nominal = type->getNominalOrBoundGenericNominal();
517507
}
518508

519-
// Form the result.
520-
Type resultType;
521-
SmallVector<Type, 2> genericArgs;
522-
if (!nominal->isGeneric() || isa<ProtocolDecl>(nominal)) {
523-
resultType = NominalType::get(nominal, parentType,
524-
nominal->getASTContext());
525-
} else if (genericParams) {
526-
auto currentBoundType = type->getAs<BoundGenericType>();
527-
528-
// Form the bound generic type with the type parameters provided.
529-
unsigned gpIndex = 0;
530-
for (auto gp : *genericParams) {
531-
SWIFT_DEFER { ++gpIndex; };
532-
509+
// If we have a bound generic type, add same-type requirements for each of
510+
// its generic arguments.
511+
if (auto currentBoundType = type->getAs<BoundGenericType>()) {
512+
auto *genericParams = currentBoundType->getDecl()->getGenericParams();
513+
for (unsigned gpIndex : indices(genericParams->getParams())) {
514+
auto *gp = genericParams->getParams()[gpIndex];
533515
auto gpType = gp->getDeclaredInterfaceType();
534-
genericArgs.push_back(gpType);
535516

536-
if (currentBoundType) {
537-
sameTypeReqs.emplace_back(RequirementKind::SameType, gpType,
538-
currentBoundType->getGenericArgs()[gpIndex]);
539-
}
517+
sameTypeReqs.emplace_back(RequirementKind::SameType, gpType,
518+
currentBoundType->getGenericArgs()[gpIndex]);
540519
}
541-
542-
resultType = BoundGenericType::get(nominal, parentType, genericArgs);
543520
}
544521

545-
// If we have a typealias, try to form type sugar.
522+
// If we have a passthrough typealias, add the requirements from its
523+
// generic signature.
546524
if (typealias && TypeChecker::isPassThroughTypealias(
547525
typealias, typealias->getUnderlyingType(), nominal)) {
548-
auto typealiasSig = typealias->getGenericSignature();
549-
SubstitutionMap subMap;
550-
if (typealiasSig) {
551-
subMap = typealiasSig->getIdentitySubstitutionMap();
552-
553-
mustInferRequirements = true;
554-
}
555-
556-
resultType = TypeAliasType::get(typealias, parentType, subMap, resultType);
526+
for (auto req : typealias->getGenericSignature().getRequirements())
527+
sameTypeReqs.push_back(req);
557528
}
558-
559-
560-
return resultType;
561-
}
562-
563-
/// Retrieve the generic parameter depth of the extended type.
564-
static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
565-
auto nominal = ext->getSelfNominalTypeDecl();
566-
if (!nominal) return static_cast<unsigned>(-1);
567-
568-
auto sig = nominal->getGenericSignatureOfContext();
569-
if (!sig) return static_cast<unsigned>(-1);
570-
571-
return sig.getGenericParams().back()->getDepth();
572529
}
573530

574531
GenericSignature
@@ -605,7 +562,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
605562
}
606563

607564
bool allowConcreteGenericParams = false;
608-
const auto *genericParams = GC->getGenericParams();
565+
auto *genericParams = GC->getGenericParams();
609566
const auto *where = GC->getTrailingWhereClause();
610567

611568
if (genericParams) {
@@ -650,10 +607,12 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
650607
return GC->getParentForLookup()->getGenericSignatureOfContext();
651608
}
652609

653-
auto parentSig = GC->getParentForLookup()->getGenericSignatureOfContext();
610+
GenericSignature parentSig;
654611
SmallVector<TypeLoc, 2> inferenceSources;
655612
SmallVector<Requirement, 2> sameTypeReqs;
656613
if (auto VD = dyn_cast_or_null<ValueDecl>(GC->getAsDecl())) {
614+
parentSig = GC->getParentForLookup()->getGenericSignatureOfContext();
615+
657616
auto func = dyn_cast<AbstractFunctionDecl>(VD);
658617
auto subscr = dyn_cast<SubscriptDecl>(VD);
659618

@@ -708,38 +667,23 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
708667
}
709668
}
710669
} else if (auto *ext = dyn_cast<ExtensionDecl>(GC)) {
711-
// Form the interface type of the extension so we can use it as an inference
712-
// source.
713-
//
714-
// FIXME: Push this into the "get interface type" request.
715-
bool mustInferRequirements = false;
716-
Type extInterfaceType =
717-
formExtensionInterfaceType(ext, ext->getExtendedType(),
718-
genericParams, sameTypeReqs,
719-
mustInferRequirements);
720-
721-
auto cannotReuseNominalSignature = [&]() -> bool {
722-
const auto finalDepth = genericParams->getParams().back()->getDepth();
723-
return mustInferRequirements
724-
|| !sameTypeReqs.empty()
725-
|| ext->getTrailingWhereClause()
726-
|| (getExtendedTypeGenericDepth(ext) != finalDepth);
727-
};
670+
parentSig = ext->getExtendedNominal()->getGenericSignatureOfContext();
671+
genericParams = nullptr;
672+
673+
collectAdditionalExtensionRequirements(ext->getExtendedType(), sameTypeReqs);
728674

729-
// Re-use the signature of the type being extended by default.
730-
if (!cannotReuseNominalSignature()) {
731-
return ext->getSelfNominalTypeDecl()->getGenericSignatureOfContext();
675+
// Re-use the signature of the type being extended by default.
676+
if (sameTypeReqs.empty() && !ext->getTrailingWhereClause()) {
677+
return parentSig;
732678
}
733679

734680
// Allow parameters to be equated with concrete types.
735681
allowConcreteGenericParams = true;
736-
737-
inferenceSources.emplace_back(nullptr, extInterfaceType);
738682
}
739683

740684
auto request = InferredGenericSignatureRequest{
741685
parentSig.getPointer(),
742-
GC->getGenericParams(), WhereClauseOwner(GC),
686+
genericParams, WhereClauseOwner(GC),
743687
sameTypeReqs, inferenceSources,
744688
allowConcreteGenericParams};
745689
auto sig = evaluateOrDefault(ctx.evaluator, request,

test/Generics/conditional_conformances.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct RedundantSame<T: P1> {}
4949
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame
5050
// CHECK-NEXT: (normal_conformance type=RedundantSame<T> protocol=P2)
5151
extension RedundantSame: P2 where T: P1 {}
52+
// expected-warning@-1 {{redundant conformance constraint 'T' : 'P1'}}
5253

5354
struct RedundantSuper<T: P4> {}
5455
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper
@@ -334,6 +335,8 @@ struct RedundancyOrderDependenceGood<T: P1, U> {}
334335
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceGood<T, U> protocol=P2
335336
// CHECK-NEXT: same_type: T U)
336337
extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {}
338+
// expected-warning@-1 {{redundant conformance constraint 'U' : 'P1'}}
339+
337340
struct RedundancyOrderDependenceBad<T, U: P1> {}
338341
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad
339342
// 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",

test/SourceKit/DocSupport/doc_swift_module_class_extension.swift.response

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ extension P8 where Self.T : module_with_class_extension.E {
129129
{
130130
key.kind: source.lang.swift.ref.generic_type_param,
131131
key.name: "T",
132-
key.usr: "s:27module_with_class_extension1CCA2A1DCRbzlE1Txmfp",
132+
key.usr: "s:27module_with_class_extension1CC1Txmfp",
133133
key.offset: 130,
134134
key.length: 1
135135
},
@@ -344,7 +344,7 @@ extension P8 where Self.T : module_with_class_extension.E {
344344
{
345345
key.kind: source.lang.swift.ref.generic_type_param,
346346
key.name: "Self",
347-
key.usr: "s:27module_with_class_extension2P8PA2A1DC1TRczrlE4Selfxmfp",
347+
key.usr: "s:27module_with_class_extension2P8P4Selfxmfp",
348348
key.offset: 480,
349349
key.length: 4
350350
},
@@ -397,7 +397,7 @@ extension P8 where Self.T : module_with_class_extension.E {
397397
{
398398
key.kind: source.lang.swift.ref.generic_type_param,
399399
key.name: "Self",
400-
key.usr: "s:27module_with_class_extension2P8PA2A1EC1TRczrlE4Selfxmfp",
400+
key.usr: "s:27module_with_class_extension2P8P4Selfxmfp",
401401
key.offset: 559,
402402
key.length: 4
403403
},
@@ -470,14 +470,19 @@ extension P8 where Self.T : module_with_class_extension.E {
470470
},
471471
{
472472
key.kind: source.lang.swift.decl.extension.class,
473+
key.generic_params: [
474+
{
475+
key.name: "T"
476+
}
477+
],
473478
key.generic_requirements: [
474479
{
475480
key.description: "T : D"
476481
}
477482
],
478483
key.offset: 112,
479484
key.length: 87,
480-
key.fully_annotated_decl: "<decl.extension.class><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.class usr=\"s:27module_with_class_extension1CC\">C</ref.class></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension1CCA2A1DCRbzlE1Txmfp\">T</ref.generic_type_param> : <ref.class usr=\"s:27module_with_class_extension1DC\">D</ref.class></decl.generic_type_requirement></decl.extension.class>",
485+
key.fully_annotated_decl: "<decl.extension.class><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.class usr=\"s:27module_with_class_extension1CC\">C</ref.class></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension1CC1Txmfp\">T</ref.generic_type_param> : <ref.class usr=\"s:27module_with_class_extension1DC\">D</ref.class></decl.generic_type_requirement></decl.extension.class>",
481486
key.extends: {
482487
key.kind: source.lang.swift.ref.class,
483488
key.name: "C",
@@ -630,7 +635,7 @@ extension P8 where Self.T : module_with_class_extension.E {
630635
],
631636
key.offset: 461,
632637
key.length: 77,
633-
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:27module_with_class_extension2P8P\">P8</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension2P8PA2A1DC1TRczrlE4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:27module_with_class_extension2P8P1TQa\">T</ref.associatedtype> : <ref.class usr=\"s:27module_with_class_extension1DC\">D</ref.class></decl.generic_type_requirement></decl.extension.protocol>",
638+
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:27module_with_class_extension2P8P\">P8</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension2P8P4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:27module_with_class_extension2P8P1TQa\">T</ref.associatedtype> : <ref.class usr=\"s:27module_with_class_extension1DC\">D</ref.class></decl.generic_type_requirement></decl.extension.protocol>",
634639
key.extends: {
635640
key.kind: source.lang.swift.ref.protocol,
636641
key.name: "P8",
@@ -656,7 +661,7 @@ extension P8 where Self.T : module_with_class_extension.E {
656661
],
657662
key.offset: 540,
658663
key.length: 77,
659-
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:27module_with_class_extension2P8P\">P8</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension2P8PA2A1EC1TRczrlE4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:27module_with_class_extension2P8P1TQa\">T</ref.associatedtype> : <ref.class usr=\"s:27module_with_class_extension1EC\">E</ref.class></decl.generic_type_requirement></decl.extension.protocol>",
664+
key.fully_annotated_decl: "<decl.extension.protocol><syntaxtype.keyword>extension</syntaxtype.keyword> <decl.name><ref.protocol usr=\"s:27module_with_class_extension2P8P\">P8</ref.protocol></decl.name> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:27module_with_class_extension2P8P4Selfxmfp\">Self</ref.generic_type_param>.<ref.associatedtype usr=\"s:27module_with_class_extension2P8P1TQa\">T</ref.associatedtype> : <ref.class usr=\"s:27module_with_class_extension1EC\">E</ref.class></decl.generic_type_requirement></decl.extension.protocol>",
660665
key.extends: {
661666
key.kind: source.lang.swift.ref.protocol,
662667
key.name: "P8",

0 commit comments

Comments
 (0)