Skip to content

Commit 769c4c1

Browse files
committed
Sema: Fix some crashes with invalid nesting of extensions and protocols
Make sure we consistently use getParentForLookup() and not getParent() when looking at generic DeclContexts. This is because an extension or protocol that is nested inside of another generic context must never inherit generic parameters from the parent context. We already had this invariant enforced in some places, but now that we do it more consistently we can fix more crashes of this kind. Fixes <rdar://problem/58813746>, <https://bugs.swift.org/browse/SR-13004>.
1 parent c46eb22 commit 769c4c1

File tree

6 files changed

+41
-30
lines changed

6 files changed

+41
-30
lines changed

lib/AST/DeclContext.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,9 @@ bool DeclContext::isGenericContext() const {
301301
if (auto GC = decl->getAsGenericContext()) {
302302
if (GC->getGenericParams())
303303
return true;
304-
305-
// Extensions do not capture outer generic parameters.
306-
if (isa<ExtensionDecl>(decl))
307-
break;
308304
}
309305
}
310-
} while ((dc = dc->getParent()));
306+
} while ((dc = dc->getParentForLookup()));
311307

312308
return false;
313309
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,11 @@ Type ConstraintSystem::openUnboundGenericType(
676676
for (auto pair : subs) {
677677
auto found = replacements.find(
678678
cast<GenericTypeParamType>(pair.first));
679-
assert(found != replacements.end() &&
680-
"Missing generic parameter?");
679+
if (found == replacements.end()) {
680+
// Can happen with invalid generic code.
681+
continue;
682+
}
683+
681684
addConstraint(ConstraintKind::Bind, found->second, pair.second,
682685
locator);
683686
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,19 +1782,19 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
17821782
return;
17831783
}
17841784

1785-
// We don't support nested types in generics yet.
1786-
if (NTD->isGenericContext()) {
1787-
auto DC = NTD->getDeclContext();
1788-
if (auto proto = DC->getSelfProtocolDecl()) {
1789-
if (DC->getExtendedProtocolDecl()) {
1790-
NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension,
1791-
NTD->getName(), proto->getName());
1792-
} else {
1793-
NTD->diagnose(diag::unsupported_type_nested_in_protocol,
1794-
NTD->getName(), proto->getName());
1795-
}
1785+
// We don't support nested types in protocols.
1786+
if (auto proto = DC->getSelfProtocolDecl()) {
1787+
if (DC->getExtendedProtocolDecl()) {
1788+
NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension,
1789+
NTD->getName(), proto->getName());
1790+
} else {
1791+
NTD->diagnose(diag::unsupported_type_nested_in_protocol,
1792+
NTD->getName(), proto->getName());
17961793
}
1794+
}
17971795

1796+
// We don't support nested types in generic functions yet.
1797+
if (NTD->isGenericContext()) {
17981798
if (DC->isLocalContext() && DC->isGenericContext()) {
17991799
// A local generic context is a generic function.
18001800
if (auto AFD = dyn_cast<AbstractFunctionDecl>(DC)) {

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -646,10 +646,10 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
646646
if (auto subscript = dyn_cast<SubscriptDecl>(accessor->getStorage()))
647647
return subscript->getGenericSignature();
648648

649-
return GC->getParent()->getGenericSignatureOfContext();
649+
return GC->getParentForLookup()->getGenericSignatureOfContext();
650650
}
651651

652-
auto parentSig = GC->getParent()->getGenericSignatureOfContext();
652+
auto parentSig = GC->getParentForLookup()->getGenericSignatureOfContext();
653653
SmallVector<TypeLoc, 2> inferenceSources;
654654
SmallVector<Requirement, 2> sameTypeReqs;
655655
if (auto VD = dyn_cast_or_null<ValueDecl>(GC->getAsDecl())) {
@@ -731,19 +731,10 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
731731

732732
// Allow parameters to be equated with concrete types.
733733
allowConcreteGenericParams = true;
734-
// Extensions must occur at the top level, they have no
735-
// (valid) parent signature.
736-
parentSig = nullptr;
734+
737735
inferenceSources.emplace_back(nullptr, extInterfaceType);
738736
}
739737

740-
// EGREGIOUS HACK: The GSB cannot handle the addition of parent signatures
741-
// from malformed decls in many cases. Check the invalid bit and null out the
742-
// parent signature.
743-
if (auto *DD = GC->getParent()->getAsDecl()) {
744-
parentSig = DD->isInvalid() ? nullptr : parentSig;
745-
}
746-
747738
return TypeChecker::checkGenericSignature(
748739
GC, GC, parentSig,
749740
allowConcreteGenericParams,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
3+
struct CommandContext<Command> {
4+
init() {
5+
let input = [1,2,3].filter {
6+
7+
extension CommandContext {
8+
struct Options {
9+
subscript<T>(path: T) -> Int {
10+
fatalError()
11+
}
12+
}
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
3+
func verifyDecoder<Decoder>() {
4+
5+
extension ByteToMessageDecoderVerifier {
6+
7+
class RecordingChannel {
8+
func readInbound<T>(foo bar: Int) {}

0 commit comments

Comments
 (0)