Skip to content

Commit d56cbfa

Browse files
committed
Sema: Check generic parameter inheritance clause after creating archetype
This fixes a crash with invalid code where the inheritance clause refers back to itself, eg struct E<F : F.A> {}.
1 parent 54033af commit d56cbfa

File tree

5 files changed

+35
-11
lines changed

5 files changed

+35
-11
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ class ArchetypeBuilder {
218218
/// \returns true if an error occurred, false otherwise.
219219
bool addGenericParameter(GenericTypeParamDecl *GenericParam);
220220

221+
/// Add the requirements placed on the given abstract type parameter
222+
/// to the given potential archetype.
223+
///
224+
/// \returns true if an error occurred, false otherwise.
225+
bool addGenericParameterRequirements(GenericTypeParamDecl *GenericParam);
226+
221227
/// \brief Add a new generic parameter for which there may be requirements.
222228
///
223229
/// \returns true if an error occurred, false otherwise.

lib/AST/ArchetypeBuilder.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,13 @@ bool ArchetypeBuilder::addGenericParameter(GenericTypeParamDecl *GenericParam) {
736736
GenericParam->getDeclaredType()->castTo<GenericTypeParamType>(),
737737
RootProtocol,
738738
GenericParam->getName());
739-
740-
if (!PA)
741-
return true;
739+
740+
return (!PA);
741+
}
742+
743+
bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *GenericParam) {
744+
GenericTypeParamKey Key{GenericParam->getDepth(), GenericParam->getIndex()};
745+
auto PA = Impl->PotentialArchetypes[Key];
742746

743747
// Add the requirements from the declaration.
744748
llvm::SmallPtrSet<ProtocolDecl *, 8> visited;

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,20 +257,25 @@ bool TypeChecker::checkGenericParamList(ArchetypeBuilder *builder,
257257
options = TR_GenericSignature;
258258
}
259259

260-
// Visit each of the generic parameters.
260+
// First, set the depth of each generic parameter, and add them to the
261+
// archetype builder. Do this before checking the inheritance clause,
262+
// since it may itself be dependent on one of these parameters.
261263
unsigned depth = genericParams->getDepth();
262264
for (auto param : *genericParams) {
263-
// Check the generic type parameter.
264-
// Set the depth of this type parameter.
265265
param->setDepth(depth);
266266

267-
// Check the inheritance clause of this type parameter.
268-
checkInheritanceClause(param, resolver);
269-
270267
if (builder) {
271-
// Add the generic parameter to the builder.
272268
if (builder->addGenericParameter(param))
273269
invalid = true;
270+
}
271+
}
272+
273+
// Now, check the inheritance clauses of each parameter.
274+
for (auto param : *genericParams) {
275+
checkInheritanceClause(param, resolver);
276+
277+
if (builder) {
278+
builder->addGenericParameterRequirements(param);
274279

275280
// Infer requirements from the inherited types.
276281
for (const auto &inherited : param->getInherited()) {

test/Generics/generic_types.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,12 @@ class X6<T> {
323323
init(_ value: T2) {}
324324
}
325325
}
326+
327+
// Invalid inheritance clause
328+
329+
struct UnsolvableInheritance1<T : T.A> {}
330+
// expected-error@-1 {{inheritance from non-protocol, non-class type 'T.A'}}
331+
332+
struct UnsolvableInheritance2<T : U.A, U : T.A> {}
333+
// expected-error@-1 {{inheritance from non-protocol, non-class type 'U.A'}}
334+
// expected-error@-2 {{inheritance from non-protocol, non-class type 'T.A'}}

validation-test/compiler_crashers/26549-swift-typechecker-resolvetypeincontext.swift renamed to validation-test/compiler_crashers_fixed/26549-swift-typechecker-resolvetypeincontext.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: not --crash %target-swift-frontend %s -parse
1+
// RUN: not %target-swift-frontend %s -parse
22
// Distributed under the terms of the MIT license
33
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
44
// Test case found by fuzzing

0 commit comments

Comments
 (0)