Skip to content

Commit 8cd89bd

Browse files
committed
Sema: Fix archetype vs interface type mixup with type in generic function
1 parent f902ce1 commit 8cd89bd

File tree

7 files changed

+47
-12
lines changed

7 files changed

+47
-12
lines changed

include/swift/AST/Types.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,12 @@ class alignas(1 << TypeAlignInBits) TypeBase {
767767

768768
/// \brief Retrieve the superclass of this type.
769769
///
770+
/// \param useArchetypes Whether to use context archetypes for outer generic
771+
/// parameters if the class is nested inside a generic function.
772+
///
770773
/// \returns The superclass of this type, or a null type if it has no
771774
/// superclass.
772-
Type getSuperclass();
775+
Type getSuperclass(bool useArchetypes = true);
773776

774777
/// \brief True if this type is the exact superclass of another type.
775778
///
@@ -797,7 +800,11 @@ class alignas(1 << TypeAlignInBits) TypeBase {
797800
///
798801
/// Calling `C<String, NSObject>`->getSuperclassForDecl(`A`) will return
799802
/// `A<Int, NSObject>`.
800-
Type getSuperclassForDecl(const ClassDecl *classDecl);
803+
///
804+
/// \param useArchetypes Whether to use context archetypes for outer generic
805+
/// parameters if the class is nested inside a generic function.
806+
Type getSuperclassForDecl(const ClassDecl *classDecl,
807+
bool useArchetypes = true);
801808

802809
/// \brief Whether this type or its superclasses has some form of generic
803810
/// context.

lib/AST/Type.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,7 @@ bool TypeBase::satisfiesClassConstraint() {
14611461
return mayHaveSuperclass() || isObjCExistentialType();
14621462
}
14631463

1464-
Type TypeBase::getSuperclass() {
1464+
Type TypeBase::getSuperclass(bool useArchetypes) {
14651465
auto *nominalDecl = getAnyNominal();
14661466
auto *classDecl = dyn_cast_or_null<ClassDecl>(nominalDecl);
14671467

@@ -1496,7 +1496,9 @@ Type TypeBase::getSuperclass() {
14961496
ModuleDecl *module = classDecl->getModuleContext();
14971497
auto subMap = getContextSubstitutionMap(module,
14981498
classDecl,
1499-
classDecl->getGenericEnvironment());
1499+
(useArchetypes
1500+
? classDecl->getGenericEnvironment()
1501+
: nullptr));
15001502
return superclassTy.subst(subMap);
15011503
}
15021504

@@ -3220,7 +3222,8 @@ static Type getConcreteTypeForSuperclassTraversing(Type t) {
32203222
return t;
32213223
}
32223224

3223-
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
3225+
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
3226+
bool useArchetypes) {
32243227
Type t = getConcreteTypeForSuperclassTraversing(this);
32253228

32263229
while (t) {
@@ -3233,7 +3236,7 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
32333236
if (nominalDecl == baseClass)
32343237
return t;
32353238

3236-
t = t->getSuperclass();
3239+
t = t->getSuperclass(useArchetypes);
32373240
}
32383241
llvm_unreachable("no inheritance relationship between given classes");
32393242
}

lib/Sema/GenericTypeResolver.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class GenericTypeResolver {
3636
public:
3737
virtual ~GenericTypeResolver();
3838

39+
virtual bool usesArchetypes() = 0;
40+
3941
/// Resolve the given interface type to a contextual type if necessary.
4042
virtual Type mapTypeIntoContext(Type type) = 0;
4143

@@ -66,6 +68,8 @@ class GenericTypeResolver {
6668
/// and only trivially resolves dependent member types.
6769
class DependentGenericTypeResolver : public GenericTypeResolver {
6870
public:
71+
virtual bool usesArchetypes() { return false; }
72+
6973
virtual Type mapTypeIntoContext(Type type);
7074

7175
virtual Type resolveDependentMemberType(Type baseTy,
@@ -93,6 +97,8 @@ class GenericTypeToArchetypeResolver : public GenericTypeResolver {
9397
explicit GenericTypeToArchetypeResolver(DeclContext *dc)
9498
: GenericEnv(dc->getGenericEnvironmentOfContext()) { }
9599

100+
virtual bool usesArchetypes() { return true; }
101+
96102
virtual Type mapTypeIntoContext(Type type);
97103

98104
virtual Type resolveDependentMemberType(Type baseTy, DeclContext *DC,
@@ -111,6 +117,8 @@ class GenericTypeToArchetypeResolver : public GenericTypeResolver {
111117
/// protocols.
112118
class ProtocolRequirementTypeResolver : public GenericTypeResolver {
113119
public:
120+
virtual bool usesArchetypes() { return false; }
121+
114122
virtual Type mapTypeIntoContext(Type type);
115123

116124
virtual Type resolveDependentMemberType(Type baseTy, DeclContext *DC,
@@ -137,6 +145,8 @@ class CompleteGenericTypeResolver : public GenericTypeResolver {
137145
public:
138146
CompleteGenericTypeResolver(TypeChecker &tc, GenericSignature *genericSig);
139147

148+
virtual bool usesArchetypes() { return false; }
149+
140150
virtual Type mapTypeIntoContext(Type type);
141151

142152
virtual Type resolveDependentMemberType(Type baseTy,

lib/Sema/TypeCheckType.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ Type TypeChecker::resolveTypeInContext(
309309

310310
// Finally, substitute the base type into the member type.
311311
return substMemberTypeWithBase(fromDC->getParentModule(), typeDecl,
312-
selfType);
312+
selfType, resolver->usesArchetypes());
313313
}
314314

315315
static TypeResolutionOptions
@@ -3017,14 +3017,15 @@ Type TypeResolver::buildProtocolType(
30173017

30183018
Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
30193019
TypeDecl *member,
3020-
Type baseTy) {
3020+
Type baseTy,
3021+
bool useArchetypes) {
30213022
Type sugaredBaseTy = baseTy;
30223023

30233024
// For type members of a base class, make sure we use the right
30243025
// derived class as the parent type.
30253026
if (auto *ownerClass = member->getDeclContext()
30263027
->getAsClassOrClassExtensionContext()) {
3027-
baseTy = baseTy->getSuperclassForDecl(ownerClass);
3028+
baseTy = baseTy->getSuperclassForDecl(ownerClass, useArchetypes);
30283029
}
30293030

30303031
if (baseTy->is<ModuleType>()) {

lib/Sema/TypeChecker.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,10 @@ class TypeChecker final : public LazyResolver {
11031103
/// \param member The member whose type projection is being computed.
11041104
/// \param baseTy The base type that will be substituted for the 'Self' of the
11051105
/// member.
1106-
Type substMemberTypeWithBase(ModuleDecl *module, TypeDecl *member, Type baseTy);
1106+
/// \param useArchetypes Whether to use context archetypes for outer generic
1107+
/// parameters if the class is nested inside a generic function.
1108+
Type substMemberTypeWithBase(ModuleDecl *module, TypeDecl *member, Type baseTy,
1109+
bool useArchetypes = true);
11071110

11081111
/// \brief Retrieve the superclass type of the given type, or a null type if
11091112
/// the type has no supertype.

test/decl/nested/type_in_function.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,14 @@ func freeFunction() {
147147
// expected-error@-1 {{can only be used as a generic constraint because it has Self or associated type requirements}}
148148
}
149149
}
150+
151+
// Superclass lookup archetype vs interface type mixup
152+
class Generic<T> {
153+
struct Nested {}
154+
155+
func outerMethod() {
156+
class Inner : Generic<T> { // expected-error {{type 'Inner' cannot be nested in generic function 'outerMethod()'}}
157+
func innerMethod() -> Nested {}
158+
}
159+
}
160+
}

validation-test/compiler_crashers/28836-functy-hasarchetype.swift renamed to validation-test/compiler_crashers_fixed/28836-functy-hasarchetype.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
class a<a{protocol P{}func a{protocol P{class a:a{func a:P

0 commit comments

Comments
 (0)