Skip to content

Commit 8edf426

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 9297a35 commit 8edf426

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
@@ -1809,6 +1809,18 @@ static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
18091809
return 0;
18101810
}
18111811

1812+
static void lookupConcreteNestedType(NominalTypeDecl *decl,
1813+
Identifier name,
1814+
SmallVectorImpl<TypeDecl *> &concreteDecls) {
1815+
SmallVector<ValueDecl *, 2> foundMembers;
1816+
decl->getParentModule()->lookupQualified(
1817+
decl, DeclNameRef(name),
1818+
NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers,
1819+
foundMembers);
1820+
for (auto member : foundMembers)
1821+
concreteDecls.push_back(cast<TypeDecl>(member));
1822+
}
1823+
18121824
TypeDecl *EquivalenceClass::lookupNestedType(
18131825
GenericSignatureBuilder &builder,
18141826
Identifier name,
@@ -1881,19 +1893,9 @@ TypeDecl *EquivalenceClass::lookupNestedType(
18811893
// FIXME: Shouldn't we always look here?
18821894
if (!bestAssocType && concreteDecls.empty()) {
18831895
Type typeToSearch = concreteType ? concreteType : superclass;
1884-
auto *decl = typeToSearch ? typeToSearch->getAnyNominal() : nullptr;
1885-
if (decl) {
1886-
SmallVector<ValueDecl *, 2> foundMembers;
1887-
decl->getParentModule()->lookupQualified(
1888-
decl, DeclNameRef(name),
1889-
NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers,
1890-
foundMembers);
1891-
for (auto member : foundMembers) {
1892-
if (auto type = dyn_cast<TypeDecl>(member)) {
1893-
concreteDecls.push_back(type);
1894-
}
1895-
}
1896-
}
1896+
if (typeToSearch)
1897+
if (auto *decl = typeToSearch->getAnyNominal())
1898+
lookupConcreteNestedType(decl, name, concreteDecls);
18971899
}
18981900

18991901
// Infer same-type constraints among same-named associated type anchors.
@@ -3531,8 +3533,6 @@ static Type substituteConcreteType(Type parentType,
35313533
if (parentType->is<ErrorType>())
35323534
return parentType;
35333535

3534-
assert(concreteDecl);
3535-
35363536
auto *dc = concreteDecl->getDeclContext();
35373537

35383538
// Form an unsubstituted type referring to the given type declaration,
@@ -3569,10 +3569,31 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass(
35693569
resolutionKind,
35703570
wantExactPotentialArchetype);
35713571
if (!resolvedBase) return resolvedBase;
3572+
35723573
// If the base is concrete, so is this member.
35733574
if (auto parentType = resolvedBase.getAsConcreteType()) {
3574-
auto concreteType = substituteConcreteType(parentType,
3575-
depMemTy->getAssocType());
3575+
TypeDecl *concreteDecl = depMemTy->getAssocType();
3576+
if (!concreteDecl) {
3577+
// If we have an unresolved dependent member type, perform a
3578+
// name lookup.
3579+
if (auto *decl = parentType->getAnyNominal()) {
3580+
SmallVector<TypeDecl *, 2> concreteDecls;
3581+
lookupConcreteNestedType(decl, depMemTy->getName(), concreteDecls);
3582+
3583+
if (concreteDecls.empty())
3584+
return ResolvedType::forUnresolved(nullptr);
3585+
3586+
auto bestConcreteTypeIter =
3587+
std::min_element(concreteDecls.begin(), concreteDecls.end(),
3588+
[](TypeDecl *type1, TypeDecl *type2) {
3589+
return TypeDecl::compare(type1, type2) < 0;
3590+
});
3591+
3592+
concreteDecl = *bestConcreteTypeIter;
3593+
}
3594+
}
3595+
3596+
auto concreteType = substituteConcreteType(parentType, concreteDecl);
35763597
return ResolvedType::forConcrete(concreteType);
35773598
}
35783599

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)