Skip to content

Commit eabc8ef

Browse files
committed
AST: Better cope with UnboundGenericType in TypeBase::getSuperclass()
Returning the unsubstituted superclass type is not correct, because it may contain type parameters. Let's form a new UnboundGenericType instead. - Fixes #82160. - Fixes rdar://152989888.
1 parent 0127926 commit eabc8ef

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
@@ -2249,10 +2249,24 @@ Type TypeBase::getSuperclass(bool useArchetypes) {
22492249
Type superclassTy = classDecl->getSuperclass();
22502250

22512251
// If there's no superclass, or it is fully concrete, we're done.
2252-
if (!superclassTy || !superclassTy->hasTypeParameter() ||
2253-
hasUnboundGenericType())
2252+
if (!superclassTy || !superclassTy->hasTypeParameter())
22542253
return superclassTy;
22552254

2255+
auto hasUnboundGenericType = [&]() {
2256+
Type t(this);
2257+
while (t) {
2258+
if (t->is<UnboundGenericType>())
2259+
return true;
2260+
t = t->getNominalParent();
2261+
}
2262+
return false;
2263+
};
2264+
2265+
// If we started with an UnboundGenericType, we cannot apply the
2266+
// context substitution map. Return the unbound form of the superclass.
2267+
if (hasUnboundGenericType())
2268+
return superclassTy->getAnyNominal()->getDeclaredType();
2269+
22562270
// Gather substitutions from the self type, and apply them to the original
22572271
// superclass type to form the substituted superclass type.
22582272
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

@@ -6344,14 +6344,23 @@ Type TypeChecker::substMemberTypeWithBase(TypeDecl *member,
63446344
: member->getDeclaredInterfaceType();
63456345
SubstitutionMap subs;
63466346
if (baseTy) {
6347-
// Cope with the presence of unbound generic types, which are ill-formed
6348-
// at this point but break the invariants of getContextSubstitutionMap().
6347+
// If the base type contains an unbound generic type, we cannot
6348+
// proceed to the getContextSubstitutionMap() call below.
6349+
//
6350+
// In general, this means the user program is ill-formed, but we
6351+
// do allow type aliases to be referenced with an unbound generic
6352+
// type as the base, if the underlying type of the type alias
6353+
// does not contain type parameters.
63496354
if (baseTy->hasUnboundGenericType()) {
63506355
memberType = memberType->getReducedType(aliasDecl->getGenericSignature());
63516356

6357+
// This is the error case. The diagnostic is emitted elsewhere,
6358+
// in TypeChecker::isUnsupportedMemberTypeAccess().
63526359
if (memberType->hasTypeParameter())
63536360
return ErrorType::get(memberType);
63546361

6362+
// Otherwise, there's no substitution to be performed, so we
6363+
// just drop the base type.
63556364
return memberType;
63566365
}
63576366

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)