Skip to content

Commit 57dfb45

Browse files
committed
Sema: Add DeclContext::isGenericTypeContext()
Once nested generic parameter lists are properly chained, we need a way of checking if we're inside a generic type context that's distinct from just checking if we have a generic type signature available. This distinguishes between these two cases: class A<T> { // generic signature func method() -> T { // <T> A<T> -> () -> T } } func f<T>() { class A { // no generic signature func method() -> T { // A -> () -> T } } }
1 parent c258f99 commit 57dfb45

File tree

7 files changed

+31
-18
lines changed

7 files changed

+31
-18
lines changed

include/swift/AST/DeclContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
359359

360360
/// Determine whether the innermost context is generic.
361361
bool isInnermostContextGeneric() const;
362+
363+
/// Determine whether the innermost context is either a generic type context,
364+
/// or a concrete type nested inside a generic type context.
365+
bool isGenericTypeContext() const;
362366

363367
/// Returns true if lookups within this context could affect downstream files.
364368
///

lib/AST/Decl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4138,8 +4138,9 @@ void EnumElementDecl::computeType() {
41384138
if (getArgumentType())
41394139
resultTy = FunctionType::get(getArgumentType(), resultTy);
41404140

4141-
if (auto gp = ED->getGenericParamsOfContext())
4142-
resultTy = PolymorphicFunctionType::get(argTy, resultTy, gp);
4141+
if (ED->isGenericTypeContext())
4142+
resultTy = PolymorphicFunctionType::get(argTy, resultTy,
4143+
ED->getGenericParamsOfContext());
41434144
else
41444145
resultTy = FunctionType::get(argTy, resultTy);
41454146

lib/AST/DeclContext.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,10 +404,11 @@ DeclContext *DeclContext::getModuleScopeContext() const {
404404

405405
/// Determine whether the given context is generic at any level.
406406
bool DeclContext::isGenericContext() const {
407-
for (const DeclContext *dc = this; ; dc = dc->getParent() ) {
407+
for (const DeclContext *dc = this; ; dc = dc->getParent()) {
408408
switch (dc->getContextKind()) {
409409
case DeclContextKind::Module:
410410
case DeclContextKind::FileUnit:
411+
case DeclContextKind::TopLevelCodeDecl:
411412
return false;
412413

413414
case DeclContextKind::Initializer:
@@ -421,10 +422,6 @@ bool DeclContext::isGenericContext() const {
421422
return true;
422423
continue;
423424

424-
case DeclContextKind::TopLevelCodeDecl:
425-
// Check parent context.
426-
continue;
427-
428425
case DeclContextKind::NominalTypeDecl:
429426
if (cast<NominalTypeDecl>(dc)->getGenericParams())
430427
return true;
@@ -440,6 +437,17 @@ bool DeclContext::isGenericContext() const {
440437
llvm_unreachable("illegal declcontext hierarchy");
441438
}
442439

440+
/// Determine whether the given context nested inside a generic type context
441+
/// with no local contexts in between.
442+
bool DeclContext::isGenericTypeContext() const {
443+
for (const auto *dc = this; dc->isTypeContext(); dc = dc->getParent()) {
444+
if (dc->isInnermostContextGeneric())
445+
return true;
446+
}
447+
448+
return false;
449+
}
450+
443451
/// Determine whether the innermost context is generic.
444452
bool DeclContext::isInnermostContextGeneric() const {
445453
switch (getContextKind()) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,7 @@ void swift::configureConstructorType(ConstructorDecl *ctor,
14401440
fnType = FunctionType::get(argType, resultType, extInfo);
14411441
}
14421442
Type selfMetaType = MetatypeType::get(selfType->getInOutObjectType());
1443-
if (outerGenericParams) {
1443+
if (ctor->getDeclContext()->isGenericTypeContext()) {
14441444
allocFnType = PolymorphicFunctionType::get(selfMetaType, fnType,
14451445
outerGenericParams);
14461446
initFnType = PolymorphicFunctionType::get(selfType, fnType,
@@ -3671,7 +3671,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
36713671
GenericParamList *outerGenericParams = nullptr;
36723672
auto patterns = FD->getBodyParamPatterns();
36733673
bool hasSelf = FD->getDeclContext()->isTypeContext();
3674-
if (hasSelf)
3674+
if (FD->getDeclContext()->isGenericTypeContext())
36753675
outerGenericParams = FD->getDeclContext()->getGenericParamsOfContext();
36763676

36773677
for (unsigned i = 0, e = patterns.size(); i != e; ++i) {
@@ -4042,7 +4042,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
40424042
// Assign archetypes.
40434043
finalizeGenericParamList(builder, gp, FD, TC);
40444044
}
4045-
} else if (outerGenericParams) {
4045+
} else if (FD->getDeclContext()->isGenericTypeContext()) {
40464046
if (TC.validateGenericFuncSignature(FD)) {
40474047
markInvalidGenericSignature(FD, TC);
40484048
} else if (!FD->hasType()) {
@@ -5168,7 +5168,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
51685168
auto resultTy = TC.getInterfaceTypeFromInternalType(enumDecl,
51695169
funcTy->getResult());
51705170
auto interfaceTy
5171-
= GenericFunctionType::get(enumDecl->getGenericSignature(),
5171+
= GenericFunctionType::get(enumDecl->getGenericSignatureOfContext(),
51725172
inputTy, resultTy, funcTy->getExtInfo());
51735173

51745174
// Record the interface type.
@@ -5247,7 +5247,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
52475247
// case the enclosing enum type was illegally declared inside of a generic
52485248
// context. (In that case, we'll post a diagnostic while visiting the
52495249
// parent enum.)
5250-
if (ED->getGenericParams())
5250+
if (EED->getDeclContext()->isGenericTypeContext())
52515251
computeEnumElementInterfaceType(EED);
52525252

52535253
// Require the carried type to be materializable.
@@ -5419,7 +5419,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
54195419
// Assign archetypes.
54205420
finalizeGenericParamList(builder, gp, CD, TC);
54215421
}
5422-
} else if (outerGenericParams) {
5422+
} else if (CD->getDeclContext()->isGenericTypeContext()) {
54235423
if (TC.validateGenericFuncSignature(CD)) {
54245424
CD->setInvalid();
54255425
} else {
@@ -5565,7 +5565,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
55655565
GenericParamList *outerGenericParams;
55665566
Type SelfTy = configureImplicitSelf(TC, DD, outerGenericParams);
55675567

5568-
if (outerGenericParams)
5568+
if (DD->getDeclContext()->isGenericTypeContext())
55695569
TC.validateGenericFuncSignature(DD);
55705570

55715571
if (semaFuncParamPatterns(DD)) {
@@ -5574,7 +5574,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
55745574
}
55755575

55765576
Type FnTy;
5577-
if (outerGenericParams)
5577+
if (DD->getDeclContext()->isGenericTypeContext())
55785578
FnTy = PolymorphicFunctionType::get(SelfTy,
55795579
TupleType::getEmpty(TC.Context),
55805580
outerGenericParams);

validation-test/compiler_crashers/25819-std-function-func-swift-type-subst.swift renamed to validation-test/compiler_crashers_fixed/25819-std-function-func-swift-type-subst.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

33
// Distributed under the terms of the MIT license
44
// Test case submitted to project by https://github.com/practicalswift (practicalswift)

validation-test/compiler_crashers/26568-swift-typechecker-validatedecl.swift renamed to validation-test/compiler_crashers_fixed/26568-swift-typechecker-validatedecl.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

validation-test/compiler_crashers/26922-swift-constraints-constraintsystem-opengeneric.swift renamed to validation-test/compiler_crashers_fixed/26922-swift-constraints-constraintsystem-opengeneric.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

33
// Distributed under the terms of the MIT license
44
// Test case submitted to project by https://github.com/practicalswift (practicalswift)

0 commit comments

Comments
 (0)