Skip to content

Commit a88c5ca

Browse files
authored
Merge pull request #82581 from slavapestov/fix-issue-82160
AST: Better cope with UnboundGenericType in TypeBase::getSuperclass()
2 parents 1d5fecb + ff26de7 commit a88c5ca

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

lib/AST/Type.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,10 +2289,24 @@ Type TypeBase::getSuperclass(bool useArchetypes) {
22892289
Type superclassTy = classDecl->getSuperclass();
22902290

22912291
// If there's no superclass, or it is fully concrete, we're done.
2292-
if (!superclassTy || !superclassTy->hasTypeParameter() ||
2293-
hasUnboundGenericType())
2292+
if (!superclassTy || !superclassTy->hasTypeParameter())
22942293
return superclassTy;
22952294

2295+
auto hasUnboundGenericType = [&]() {
2296+
Type t(this);
2297+
while (t) {
2298+
if (t->is<UnboundGenericType>())
2299+
return true;
2300+
t = t->getNominalParent();
2301+
}
2302+
return false;
2303+
};
2304+
2305+
// If we started with an UnboundGenericType, we cannot apply the
2306+
// context substitution map. Return the unbound form of the superclass.
2307+
if (hasUnboundGenericType())
2308+
return superclassTy->getAnyNominal()->getDeclaredType();
2309+
22962310
// Gather substitutions from the self type, and apply them to the original
22972311
// superclass type to form the substituted superclass type.
22982312
auto subMap = getContextSubstitutionMap(classDecl,

lib/Sema/TypeCheckType.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// This file implements validation for Swift types, emitting semantic errors as
14-
// appropriate and checking default initializer values.
13+
// This file implements type resolution, which converts syntactic type
14+
// representations into semantic types, emitting diagnostics as appropriate.
1515
//
1616
//===----------------------------------------------------------------------===//
1717

@@ -6330,14 +6330,23 @@ Type TypeChecker::substMemberTypeWithBase(TypeDecl *member,
63306330
: member->getDeclaredInterfaceType();
63316331
SubstitutionMap subs;
63326332
if (baseTy) {
6333-
// Cope with the presence of unbound generic types, which are ill-formed
6334-
// at this point but break the invariants of getContextSubstitutionMap().
6333+
// If the base type contains an unbound generic type, we cannot
6334+
// proceed to the getContextSubstitutionMap() call below.
6335+
//
6336+
// In general, this means the user program is ill-formed, but we
6337+
// do allow type aliases to be referenced with an unbound generic
6338+
// type as the base, if the underlying type of the type alias
6339+
// does not contain type parameters.
63356340
if (baseTy->hasUnboundGenericType()) {
63366341
memberType = memberType->getReducedType(aliasDecl->getGenericSignature());
63376342

6343+
// This is the error case. The diagnostic is emitted elsewhere,
6344+
// in TypeChecker::isUnsupportedMemberTypeAccess().
63386345
if (memberType->hasTypeParameter())
63396346
return ErrorType::get(memberType);
63406347

6348+
// Otherwise, there's no substitution to be performed, so we
6349+
// just drop the base type.
63416350
return memberType;
63426351
}
63436352

test/decl/typealias/dependent_types.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ let _: GenericStruct.ReferencesConcrete = foo()
6565

6666
class SuperG<T, U> {
6767
typealias Composed = (T, U)
68+
typealias Concrete = Int
6869
}
6970

7071
class SubG<T> : SuperG<T, T> { }
@@ -74,3 +75,16 @@ typealias SubGX<T> = SubG<T?>
7475
func checkSugar(gs: SubGX<Int>.Composed) {
7576
let i4: Int = gs // expected-error{{cannot convert value of type 'SubGX<Int>.Composed' (aka '(Optional<Int>, Optional<Int>)') to specified type 'Int'}}
7677
}
78+
79+
// https://github.com/swiftlang/swift/issues/82160
80+
81+
let x1: SuperG.Concrete = 123
82+
let x2: SubG.Concrete = 123
83+
84+
func f1() -> SuperG.Concrete {
85+
return 123
86+
}
87+
88+
func f2() -> SubG.Concrete {
89+
return 123
90+
}

0 commit comments

Comments
 (0)