Skip to content

Commit 3372103

Browse files
authored
Merge pull request #70241 from slavapestov/fix-rdar119052782
Sema: Fancier handling of associated type defaults
2 parents 10d672e + 52e3031 commit 3372103

9 files changed

+83
-46
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6055,7 +6055,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
60556055
switch (Options.OpaqueReturnTypePrinting) {
60566056
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference:
60576057
case PrintOptions::OpaqueReturnTypePrintingMode::Description:
6058-
return true;
6058+
return false;
60596059
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
60606060
return opaque->getDecl()->hasExplicitGenericParams();
60616061
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword:
@@ -7413,39 +7413,51 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
74137413
Printer << "each ";
74147414
}
74157415

7416-
void printArchetypeCommon(ArchetypeType *T) {
7417-
if (Options.AlternativeTypeNames) {
7418-
auto found = Options.AlternativeTypeNames->find(T->getCanonicalType());
7419-
if (found != Options.AlternativeTypeNames->end()) {
7420-
if (T->isParameterPack()) printEach();
7421-
Printer << found->second.str();
7422-
return;
7416+
void printArchetypeCommon(Type interfaceTy, ArchetypeType *archetypeTy) {
7417+
if (auto *paramTy = interfaceTy->getAs<GenericTypeParamType>()) {
7418+
assert(archetypeTy->isRoot());
7419+
7420+
if (Options.AlternativeTypeNames) {
7421+
auto found = Options.AlternativeTypeNames->find(CanType(archetypeTy));
7422+
if (found != Options.AlternativeTypeNames->end()) {
7423+
if (paramTy->isParameterPack()) printEach();
7424+
Printer << found->second.str();
7425+
return;
7426+
}
74237427
}
7428+
7429+
visit(paramTy);
7430+
return;
74247431
}
74257432

7426-
auto interfaceType = T->getInterfaceType();
7427-
if (auto *dependentMember = interfaceType->getAs<DependentMemberType>()) {
7428-
visitParentType(T->getParent());
7429-
printDependentMember(dependentMember);
7430-
} else {
7431-
visit(interfaceType);
7433+
auto *memberTy = interfaceTy->castTo<DependentMemberType>();
7434+
if (memberTy->getBase()->is<GenericTypeParamType>())
7435+
visitParentType(archetypeTy->getRoot());
7436+
else {
7437+
printArchetypeCommon(memberTy->getBase(), archetypeTy->getRoot());
7438+
Printer << ".";
74327439
}
7440+
7441+
printDependentMember(memberTy);
74337442
}
74347443

74357444
void visitPrimaryArchetypeType(PrimaryArchetypeType *T) {
7436-
printArchetypeCommon(T);
7445+
printArchetypeCommon(T->getInterfaceType(), T);
74377446
}
74387447

74397448
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
7440-
if (auto parent = T->getParent()) {
7441-
printArchetypeCommon(T);
7449+
auto interfaceTy = T->getInterfaceType();
7450+
auto *paramTy = interfaceTy->getAs<GenericTypeParamType>();
7451+
7452+
if (!paramTy) {
7453+
assert(interfaceTy->is<DependentMemberType>());
7454+
printArchetypeCommon(interfaceTy, T);
74427455
return;
74437456
}
74447457

74457458
// Try to print a named opaque type.
74467459
auto printNamedOpaque = [&] {
7447-
unsigned ordinal =
7448-
T->getInterfaceType()->castTo<GenericTypeParamType>()->getIndex();
7460+
unsigned ordinal = paramTy->getIndex();
74497461
if (auto genericParam = T->getDecl()->getExplicitGenericParam(ordinal)) {
74507462
visit(genericParam->getDeclaredInterfaceType());
74517463
return true;
@@ -7492,9 +7504,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
74927504
Printer.printEscapedStringLiteral(
74937505
decl->getOpaqueReturnTypeIdentifier().str());
74947506

7495-
Printer << ", " << T->getInterfaceType()
7496-
->castTo<GenericTypeParamType>()
7497-
->getIndex();
7507+
Printer << ", " << paramTy->getIndex();
74987508

74997509
// The identifier after the closing parenthesis is irrelevant and can be
75007510
// anything. It just needs to be there for the @_opaqueReturnTypeOf
@@ -7526,7 +7536,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
75267536
}
75277537

75287538
void visitPackArchetypeType(PackArchetypeType *T) {
7529-
printArchetypeCommon(T);
7539+
printArchetypeCommon(T->getInterfaceType(), T);
75307540
}
75317541

75327542
void visitGenericTypeParamType(GenericTypeParamType *T) {

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,8 +701,8 @@ class Verifier : public ASTWalker {
701701
auto interfaceType = archetype->getInterfaceType();
702702
auto contextType = archetypeEnv->mapTypeIntoContext(interfaceType);
703703

704-
if (contextType.getPointer() != archetype) {
705-
Out << "Archetype " << archetype->getString() << "does not appear"
704+
if (!contextType->isEqual(archetype)) {
705+
Out << "Archetype " << archetype->getString() << " does not appear"
706706
<< " inside its own generic environment\n";
707707
Out << "Interface type: " << interfaceType.getString() << "\n";
708708
Out << "Contextual type: " << contextType.getString() << "\n";

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7253,10 +7253,11 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
72537253
DefaultWitnessChecker checker(proto);
72547254

72557255
// Find the default for the given associated type.
7256-
auto findAssociatedTypeDefault = [](AssociatedTypeDecl *assocType)
7256+
auto findAssociatedTypeDefault = [proto](AssociatedTypeDecl *assocType)
72577257
-> std::pair<Type, AssociatedTypeDecl *> {
72587258
auto defaultedAssocType =
7259-
AssociatedTypeInference::findDefaultedAssociatedType(assocType);
7259+
AssociatedTypeInference::findDefaultedAssociatedType(
7260+
proto, proto, assocType);
72607261
if (!defaultedAssocType)
72617262
return {Type(), nullptr};
72627263

lib/Sema/TypeCheckProtocol.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,8 @@ class AssociatedTypeInference {
12711271

12721272
/// Find an associated type declaration that provides a default definition.
12731273
static AssociatedTypeDecl *findDefaultedAssociatedType(
1274-
AssociatedTypeDecl *assocType);
1274+
DeclContext *dc, NominalTypeDecl *adoptee,
1275+
AssociatedTypeDecl *assocType);
12751276
};
12761277

12771278
/// Match the given witness to the given requirement.

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -919,26 +919,31 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitness(ValueDecl *req,
919919
}
920920

921921
AssociatedTypeDecl *AssociatedTypeInference::findDefaultedAssociatedType(
922+
DeclContext *dc,
923+
NominalTypeDecl *adoptee,
922924
AssociatedTypeDecl *assocType) {
923925
// If this associated type has a default, we're done.
924926
if (assocType->hasDefaultDefinitionType())
925927
return assocType;
926928

927-
// Look at overridden associated types.
929+
// Otherwise, look for all associated types with the same name along all the
930+
// protocols that the adoptee conforms to.
931+
SmallVector<ValueDecl *, 4> decls;
932+
auto options = NL_ProtocolMembers | NL_OnlyTypes;
933+
dc->lookupQualified(adoptee, DeclNameRef(assocType->getName()),
934+
SourceLoc(), options, decls);
935+
928936
SmallPtrSet<CanType, 4> canonicalTypes;
929937
SmallVector<AssociatedTypeDecl *, 2> results;
930-
for (auto overridden : assocType->getOverriddenDecls()) {
931-
auto overriddenDefault = findDefaultedAssociatedType(overridden);
932-
if (!overriddenDefault) continue;
933-
934-
Type overriddenType =
935-
overriddenDefault->getDefaultDefinitionType();
936-
assert(overriddenType);
937-
if (!overriddenType) continue;
938+
for (auto *decl : decls) {
939+
if (auto *assocDecl = dyn_cast<AssociatedTypeDecl>(decl)) {
940+
auto defaultType = assocDecl->getDefaultDefinitionType();
941+
if (!defaultType) continue;
938942

939-
CanType key = overriddenType->getCanonicalType();
943+
CanType key = defaultType->getCanonicalType();
940944
if (canonicalTypes.insert(key).second)
941-
results.push_back(overriddenDefault);
945+
results.push_back(assocDecl);
946+
}
942947
}
943948

944949
// If there was a single result, return it.
@@ -999,7 +1004,8 @@ llvm::Optional<AbstractTypeWitness>
9991004
AssociatedTypeInference::computeDefaultTypeWitness(
10001005
AssociatedTypeDecl *assocType) const {
10011006
// Go find a default definition.
1002-
auto *const defaultedAssocType = findDefaultedAssociatedType(assocType);
1007+
auto *const defaultedAssocType = findDefaultedAssociatedType(
1008+
dc, dc->getSelfNominalTypeDecl(), assocType);
10031009
if (!defaultedAssocType)
10041010
return llvm::None;
10051011

test/Generics/opaque_archetype_concrete_requirement_recursive_rejected.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ protocol HasRecursiveP {
3131

3232
extension HasRecursiveP where T == DefinesRecursiveP.T {}
3333
// expected-error@-1 {{cannot build rewrite system for generic signature; rule length limit exceeded}}
34-
// expected-note@-2 {{failed rewrite rule is τ_0_0.[HasRecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[concrete: ((((((((((((@_opaqueReturnTypeOf("$s56opaque_archetype_concrete_requirement_recursive_rejected17DefinesRecursivePV1tQrvp", 0) __.T).T).T).T).T).T).T).T).T).T).T).T).T] => τ_0_0.[HasRecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T]}}
34+
// expected-note@-2 {{failed rewrite rule is τ_0_0.[HasRecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[concrete: (@_opaqueReturnTypeOf("$s56opaque_archetype_concrete_requirement_recursive_rejected17DefinesRecursivePV1tQrvp", 0) __).T.T.T.T.T.T.T.T.T.T.T.T.T] => τ_0_0.[HasRecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T].[RecursiveP:T]}}
3535

test/SILGen/opaque_result_type_private_assoc_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import opaque_result_type_private_assoc_type_other
66

77
// CHECK-LABEL: sil hidden [ossa] @$s033opaque_result_type_private_assoc_C0028usesAssocTypeOfPrivateResultH0yyF : $@convention(thin) () -> () {
88
func usesAssocTypeOfPrivateResultType() {
9-
// CHECK: [[BOX:%.*]] = alloc_stack $Optional<@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __.Element>
9+
// CHECK: [[BOX:%.*]] = alloc_stack $Optional<(@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __).Element>
1010
// CHECK: [[METHOD:%.*]] = witness_method $@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __, #IteratorProtocol.next : <Self where Self : opaque_result_type_private_assoc_type_other.IteratorProtocol> (Self) -> () -> Self.Element? : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.Element>
1111
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<@_opaqueReturnTypeOf("$s033opaque_result_type_private_assoc_C6_other11doSomethingQryF", 0) __>([[BOX]], {{%.*}}) : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.Element>
1212
let iterator = doSomething()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P1 {
4+
associatedtype A
5+
6+
func f(_: A)
7+
}
8+
9+
protocol P2: P1 {
10+
associatedtype A = Int
11+
}
12+
13+
func foo<T: P1>(_: T.Type) -> T.A.Type {}
14+
15+
_ = foo(S.self)
16+
17+
struct S: P2 {
18+
func f(_: A) {}
19+
}

test/decl/protocol/req/associated_type_tuple.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ protocol P1 {
1111
extension Tuple: P1 where repeat each T: P1 {} // expected-error {{type '(repeat each T)' does not conform to protocol 'P1'}}
1212

1313
protocol P2 {
14-
associatedtype A = Int // expected-note {{default type 'Int' for associated type 'A' (from protocol 'P2') is unsuitable for tuple conformance; the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).A)'}}
14+
associatedtype B = Int // expected-note {{default type 'Int' for associated type 'B' (from protocol 'P2') is unsuitable for tuple conformance; the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).B)'}}
1515
}
1616

1717
extension Tuple: P2 where repeat each T: P2 {} // expected-error {{type '(repeat each T)' does not conform to protocol 'P2'}}
1818

1919
protocol P3 {
20-
associatedtype A // expected-note {{unable to infer associated type 'A' for protocol 'P3'}}
21-
func f() -> A
20+
associatedtype C // expected-note {{unable to infer associated type 'C' for protocol 'P3'}}
21+
func f() -> C
2222
}
2323

2424
extension Tuple: P3 where repeat each T: P3 { // expected-error {{type '(repeat each T)' does not conform to protocol 'P3'}}
25-
func f() -> Int {} // expected-note {{cannot infer 'A' = 'Int' in tuple conformance because the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).A)'}}
25+
func f() -> Int {} // expected-note {{cannot infer 'C' = 'Int' in tuple conformance because the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).C)'}}
2626
}

0 commit comments

Comments
 (0)