Skip to content

Commit 7707133

Browse files
committed
[TypeChecker] Fix assertion failure when using Self in extension that’s not on top-level
We fail to resolve the extended type if an extension is not declared at the top level. This causes us to diagnose a lookup failure on `Self`. If the extended type is a protocol, we thus end up with a nominal Self type that’s not a class, violating the assertion that’s currently in place. To fix the crasher, convert the assertion to an `if` condition and issue a generic "cannot find type 'Self' in scope" in the else case. Cherry-picking 78d6fb2 from the `main` branch.
1 parent 47ca24d commit 7707133

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,21 +1131,26 @@ static Type diagnoseUnknownType(TypeResolution resolution,
11311131
NominalTypeDecl *nominal = nullptr;
11321132
if ((nominalDC = dc->getInnermostTypeContext()) &&
11331133
(nominal = nominalDC->getSelfNominalTypeDecl())) {
1134-
// Attempt to refer to 'Self' within a non-protocol nominal
1135-
// type. Fix this by replacing 'Self' with the nominal type name.
1136-
assert(isa<ClassDecl>(nominal) && "Must be a class");
1134+
if (isa<ClassDecl>(nominal)) {
1135+
// Attempt to refer to 'Self' within a non-protocol nominal
1136+
// type. Fix this by replacing 'Self' with the nominal type name.
11371137

1138-
// Produce a Fix-It replacing 'Self' with the nominal type name.
1139-
auto name = getDeclNameFromContext(dc, nominal);
1140-
diags.diagnose(comp->getNameLoc(), diag::dynamic_self_invalid, name)
1141-
.fixItReplace(comp->getNameLoc().getSourceRange(), name);
1138+
// Produce a Fix-It replacing 'Self' with the nominal type name.
1139+
auto name = getDeclNameFromContext(dc, nominal);
1140+
diags.diagnose(comp->getNameLoc(), diag::dynamic_self_invalid, name)
1141+
.fixItReplace(comp->getNameLoc().getSourceRange(), name);
11421142

1143-
auto type = resolution.mapTypeIntoContext(
1144-
dc->getInnermostTypeContext()->getSelfInterfaceType());
1143+
auto type = resolution.mapTypeIntoContext(
1144+
dc->getInnermostTypeContext()->getSelfInterfaceType());
11451145

1146-
comp->overwriteNameRef(DeclNameRef(nominal->getName()));
1147-
comp->setValue(nominal, nominalDC->getParent());
1148-
return type;
1146+
comp->overwriteNameRef(DeclNameRef(nominal->getName()));
1147+
comp->setValue(nominal, nominalDC->getParent());
1148+
return type;
1149+
} else {
1150+
diags.diagnose(comp->getNameLoc(), diag::cannot_find_type_in_scope,
1151+
comp->getNameRef());
1152+
return ErrorType::get(ctx);
1153+
}
11491154
}
11501155
// Attempt to refer to 'Self' from a free function.
11511156
diags.diagnose(comp->getNameLoc(), diag::dynamic_self_non_method,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
protocol Foo {}
3+
4+
func withTrailingClosure(x: (Int) -> Void) {}
5+
6+
_ = withTrailingClosure { (x) in
7+
extension Foo {
8+
func foo() {
9+
_ = MemoryLayout<Self>.size
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)