Skip to content

Commit 2eb25d4

Browse files
authored
Merge pull request #7356 from slavapestov/fix-nested-type-extension
Sema: Fix crash when defining an extension of a nested type with constrains
2 parents ff826e3 + 707083d commit 2eb25d4

File tree

5 files changed

+44
-25
lines changed

5 files changed

+44
-25
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class ArchetypeBuilder {
270270
/// where \c Dictionary requires that its key type be \c Hashable,
271271
/// the requirement \c K : Hashable is inferred from the parameter type,
272272
/// because the type \c Dictionary<K,V> cannot be formed without it.
273-
void inferRequirements(TypeLoc type, GenericParamList *genericParams);
273+
void inferRequirements(TypeLoc type, unsigned minDepth, unsigned maxDepth);
274274

275275
/// Infer requirements from the given pattern, recursively.
276276
///

lib/AST/ArchetypeBuilder.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,21 +1654,23 @@ void ArchetypeBuilder::addRequirement(const Requirement &req,
16541654
class ArchetypeBuilder::InferRequirementsWalker : public TypeWalker {
16551655
ArchetypeBuilder &Builder;
16561656
SourceLoc Loc;
1657-
unsigned Depth;
1657+
unsigned MinDepth;
1658+
unsigned MaxDepth;
16581659

16591660
/// We cannot add requirements to archetypes from outer generic parameter
16601661
/// lists.
16611662
bool isOuterArchetype(PotentialArchetype *PA) {
16621663
unsigned ParamDepth = PA->getRootGenericParamKey().Depth;
1663-
assert(ParamDepth <= Depth);
1664-
return ParamDepth < Depth;
1664+
assert(ParamDepth <= MaxDepth);
1665+
return ParamDepth < MinDepth;
16651666
}
16661667

16671668
public:
16681669
InferRequirementsWalker(ArchetypeBuilder &builder,
16691670
SourceLoc loc,
1670-
unsigned Depth)
1671-
: Builder(builder), Loc(loc), Depth(Depth) { }
1671+
unsigned MinDepth,
1672+
unsigned MaxDepth)
1673+
: Builder(builder), Loc(loc), MinDepth(MinDepth), MaxDepth(MaxDepth) { }
16721674

16731675
Action walkToTypePost(Type ty) override {
16741676
auto boundGeneric = ty->getAs<BoundGenericType>();
@@ -1776,24 +1778,26 @@ class ArchetypeBuilder::InferRequirementsWalker : public TypeWalker {
17761778
};
17771779

17781780
void ArchetypeBuilder::inferRequirements(TypeLoc type,
1779-
GenericParamList *genericParams) {
1781+
unsigned minDepth,
1782+
unsigned maxDepth) {
17801783
if (!type.getType())
17811784
return;
1782-
if (genericParams == nullptr)
1783-
return;
17841785
// FIXME: Crummy source-location information.
17851786
InferRequirementsWalker walker(*this, type.getSourceRange().Start,
1786-
genericParams->getDepth());
1787+
minDepth, maxDepth);
17871788
type.getType().walk(walker);
17881789
}
17891790

17901791
void ArchetypeBuilder::inferRequirements(ParameterList *params,
17911792
GenericParamList *genericParams) {
17921793
if (genericParams == nullptr)
17931794
return;
1794-
1795+
1796+
unsigned depth = genericParams->getDepth();
17951797
for (auto P : *params)
1796-
inferRequirements(P->getTypeLoc(), genericParams);
1798+
inferRequirements(P->getTypeLoc(),
1799+
/*minDepth=*/depth,
1800+
/*maxDepth=*/depth);
17971801
}
17981802

17991803
/// Perform typo correction on the given nested type, producing the

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4822,7 +4822,10 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
48224822

48234823
// Infer requirements from the result type.
48244824
if (!FD->getBodyResultTypeLoc().isNull()) {
4825-
builder.inferRequirements(FD->getBodyResultTypeLoc(), gp);
4825+
unsigned depth = gp->getDepth();
4826+
builder.inferRequirements(FD->getBodyResultTypeLoc(),
4827+
/*minDepth=*/depth,
4828+
/*maxDepth=*/depth);
48264829
}
48274830

48284831
// Revert the types within the signature so it can be type-checked with
@@ -7383,15 +7386,9 @@ checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
73837386

73847387
// Local function used to infer requirements from the extended type.
73857388
auto inferExtendedTypeReqs = [&](ArchetypeBuilder &builder) {
7386-
// Find the outermost generic parameter list. This tricks the inference
7387-
// into performing inference for all levels of generic parameters.
7388-
// FIXME: This is a hack. The inference shouldn't arbitrarily limit what it
7389-
// can infer.
7390-
GenericParamList *outermostList = genericParams;
7391-
while (auto next = outermostList->getOuterParameters())
7392-
outermostList = next;
7393-
7394-
builder.inferRequirements(TypeLoc::withoutLoc(extInterfaceType), outermostList);
7389+
builder.inferRequirements(TypeLoc::withoutLoc(extInterfaceType),
7390+
/*minDepth=*/0,
7391+
/*maxDepth=*/genericParams->getDepth());
73957392
};
73967393

73977394
// Validate the generic type signature.

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ void TypeChecker::checkGenericParamList(ArchetypeBuilder *builder,
267267
builder->addGenericParameter(param);
268268
}
269269

270+
unsigned depth = genericParams->getDepth();
271+
270272
// Now, check the inheritance clauses of each parameter.
271273
for (auto param : *genericParams) {
272274
checkInheritanceClause(param, resolver);
@@ -276,7 +278,9 @@ void TypeChecker::checkGenericParamList(ArchetypeBuilder *builder,
276278

277279
// Infer requirements from the inherited types.
278280
for (const auto &inherited : param->getInherited()) {
279-
builder->inferRequirements(inherited, genericParams);
281+
builder->inferRequirements(inherited,
282+
/*minDepth=*/depth,
283+
/*maxDepth=*/depth);
280284
}
281285
}
282286
}
@@ -393,8 +397,12 @@ static bool checkGenericFuncSignature(TypeChecker &tc,
393397
}
394398

395399
// Infer requirements from it.
396-
if (builder && fn->getBodyResultTypeLoc().getTypeRepr()) {
397-
builder->inferRequirements(fn->getBodyResultTypeLoc(), genericParams);
400+
if (builder && genericParams &&
401+
fn->getBodyResultTypeLoc().getTypeRepr()) {
402+
unsigned depth = genericParams->getDepth();
403+
builder->inferRequirements(fn->getBodyResultTypeLoc(),
404+
/*minDepth=*/depth,
405+
/*maxDepth=*/depth);
398406
}
399407
}
400408
}

test/decl/nested/type_in_type.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,13 @@ extension OuterNonGenericClass.InnerNonGenericBase {
351351
extension OuterNonGenericClass.InnerNonGenericClass1 {
352352
static let anotherPropUsingMember = originalValue
353353
}
354+
355+
// rdar://problem/30353095: Extensions of nested types with generic
356+
// requirements placed on type parameters
357+
struct OuterWithConstraint<T : HasAssocType> {
358+
struct InnerWithConstraint<U : HasAssocType> { }
359+
}
360+
361+
extension OuterWithConstraint.InnerWithConstraint {
362+
func foo<V>(v: V) where T.FirstAssocType == U.SecondAssocType {}
363+
}

0 commit comments

Comments
 (0)