Skip to content

Commit 797a057

Browse files
committed
GSB: Better handling of unresolved DependentMemberTypes in maybeResolveEquivalenceClass()
A DependentMemberType can either have a bound AssociatedTypeDecl, or it might be 'unresolved' and only store an identifier. In maybeResolveEquivalenceClass(), we did not handle the unresolved case when the base type of the DependentMemberType had itself been resolved to a concrete type. Fixes <rdar://problem/71162777>.
1 parent 1a690fc commit 797a057

File tree

3 files changed

+58
-20
lines changed

3 files changed

+58
-20
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,18 @@ static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
18211821
return 0;
18221822
}
18231823

1824+
static void lookupConcreteNestedType(NominalTypeDecl *decl,
1825+
Identifier name,
1826+
SmallVectorImpl<TypeDecl *> &concreteDecls) {
1827+
SmallVector<ValueDecl *, 2> foundMembers;
1828+
decl->getParentModule()->lookupQualified(
1829+
decl, DeclNameRef(name),
1830+
NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers,
1831+
foundMembers);
1832+
for (auto member : foundMembers)
1833+
concreteDecls.push_back(cast<TypeDecl>(member));
1834+
}
1835+
18241836
TypeDecl *EquivalenceClass::lookupNestedType(
18251837
GenericSignatureBuilder &builder,
18261838
Identifier name,
@@ -1893,19 +1905,9 @@ TypeDecl *EquivalenceClass::lookupNestedType(
18931905
// FIXME: Shouldn't we always look here?
18941906
if (!bestAssocType && concreteDecls.empty()) {
18951907
Type typeToSearch = concreteType ? concreteType : superclass;
1896-
auto *decl = typeToSearch ? typeToSearch->getAnyNominal() : nullptr;
1897-
if (decl) {
1898-
SmallVector<ValueDecl *, 2> foundMembers;
1899-
decl->getParentModule()->lookupQualified(
1900-
decl, DeclNameRef(name),
1901-
NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers,
1902-
foundMembers);
1903-
for (auto member : foundMembers) {
1904-
if (auto type = dyn_cast<TypeDecl>(member)) {
1905-
concreteDecls.push_back(type);
1906-
}
1907-
}
1908-
}
1908+
if (typeToSearch)
1909+
if (auto *decl = typeToSearch->getAnyNominal())
1910+
lookupConcreteNestedType(decl, name, concreteDecls);
19091911
}
19101912

19111913
// Infer same-type constraints among same-named associated type anchors.
@@ -3560,8 +3562,6 @@ static Type substituteConcreteType(Type parentType,
35603562
if (parentType->is<ErrorType>())
35613563
return parentType;
35623564

3563-
assert(concreteDecl);
3564-
35653565
auto *dc = concreteDecl->getDeclContext();
35663566

35673567
// Form an unsubstituted type referring to the given type declaration,
@@ -3598,10 +3598,31 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass(
35983598
resolutionKind,
35993599
wantExactPotentialArchetype);
36003600
if (!resolvedBase) return resolvedBase;
3601+
36013602
// If the base is concrete, so is this member.
36023603
if (auto parentType = resolvedBase.getAsConcreteType()) {
3603-
auto concreteType = substituteConcreteType(parentType,
3604-
depMemTy->getAssocType());
3604+
TypeDecl *concreteDecl = depMemTy->getAssocType();
3605+
if (!concreteDecl) {
3606+
// If we have an unresolved dependent member type, perform a
3607+
// name lookup.
3608+
if (auto *decl = parentType->getAnyNominal()) {
3609+
SmallVector<TypeDecl *, 2> concreteDecls;
3610+
lookupConcreteNestedType(decl, depMemTy->getName(), concreteDecls);
3611+
3612+
if (concreteDecls.empty())
3613+
return ResolvedType::forUnresolved(nullptr);
3614+
3615+
auto bestConcreteTypeIter =
3616+
std::min_element(concreteDecls.begin(), concreteDecls.end(),
3617+
[](TypeDecl *type1, TypeDecl *type2) {
3618+
return TypeDecl::compare(type1, type2) < 0;
3619+
});
3620+
3621+
concreteDecl = *bestConcreteTypeIter;
3622+
}
3623+
}
3624+
3625+
auto concreteType = substituteConcreteType(parentType, concreteDecl);
36053626
return ResolvedType::forConcrete(concreteType);
36063627
}
36073628

validation-test/compiler_crashers_2/rdar56398071.swift renamed to validation-test/compiler_crashers_2_fixed/rdar56398071.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: not --crash %target-swift-frontend -primary-file %s -emit-silgen
2-
3-
// REQUIRES: asserts
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir
42

53
public protocol WrappedSignedInteger: SignedInteger where Stride == Int {
64
typealias WrappedInteger = Int
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -emit-ir %s
2+
3+
public struct LowerModel {
4+
public typealias Index = Int
5+
}
6+
7+
public protocol LowerChildA {
8+
typealias Model = LowerModel
9+
typealias ModelIndex = Model.Index
10+
}
11+
12+
public protocol LowerChildB {
13+
typealias Model = LowerModel
14+
typealias ModelIndex = Model.Index
15+
}
16+
17+
public protocol Parent: LowerChildA & LowerChildB {}
18+
19+
public func foo<T : Parent>(_: T, _: T.Model, _: T.ModelIndex) {}

0 commit comments

Comments
 (0)