Skip to content

Commit 0a9e1c2

Browse files
committed
Sema: Merge two places where we resolve 'Self'
1 parent 2559ce1 commit 0a9e1c2

File tree

4 files changed

+55
-60
lines changed

4 files changed

+55
-60
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,35 +1048,6 @@ static std::string getDeclNameFromContext(DeclContext *dc,
10481048
}
10491049
}
10501050

1051-
//
1052-
// SE-0068 is "Expanding Swift Self to class members and value types"
1053-
// Returns a Type if 'Self' is available in the current implementation.
1054-
// Errs on the side of returning `Self` in most circumstances which is
1055-
// subsequently validated in the various vistors in TypeCheckDecl.cpp.
1056-
//
1057-
// https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
1058-
//
1059-
static Type SelfAllowedBySE0068(TypeResolution resolution,
1060-
TypeResolutionOptions options) {
1061-
auto dc = resolution.getDeclContext();
1062-
ASTContext &ctx = dc->getASTContext();
1063-
DeclContext *nominalDC = nullptr;
1064-
NominalTypeDecl *nominal = nullptr;
1065-
if ((nominalDC = dc->getInnermostTypeContext()) &&
1066-
(nominal = nominalDC->getSelfNominalTypeDecl())) {
1067-
assert(!isa<ProtocolDecl>(nominal) && "Cannot be a protocol");
1068-
1069-
if (!options.is(TypeResolverContext::GenericRequirement)) {
1070-
Type SelfType = nominal->getSelfInterfaceType();
1071-
if (nominalDC->getSelfClassDecl() != nullptr)
1072-
SelfType = DynamicSelfType::get(SelfType, ctx);
1073-
return resolution.mapTypeIntoContext(SelfType);
1074-
}
1075-
}
1076-
1077-
return Type();
1078-
}
1079-
10801051
/// Diagnose a reference to an unknown type.
10811052
///
10821053
/// This routine diagnoses a reference to an unknown type, and
@@ -1104,19 +1075,13 @@ static Type diagnoseUnknownType(TypeResolution resolution,
11041075
(nominal = nominalDC->getSelfNominalTypeDecl())) {
11051076
// Attempt to refer to 'Self' within a non-protocol nominal
11061077
// type. Fix this by replacing 'Self' with the nominal type name.
1107-
assert(!isa<ProtocolDecl>(nominal) && "Cannot be a protocol");
1078+
assert(isa<ClassDecl>(nominal) && "Must be a class");
11081079

11091080
// Produce a Fix-It replacing 'Self' with the nominal type name.
11101081
auto name = getDeclNameFromContext(dc, nominal);
11111082
diags.diagnose(comp->getIdLoc(), diag::self_in_nominal, name)
11121083
.fixItReplace(comp->getIdLoc(), name);
11131084

1114-
// If this is a requirement, replacing 'Self' with a valid type will
1115-
// result in additional unnecessary diagnostics (does not refer to a
1116-
// generic parameter or associated type). Simply return an error type.
1117-
if (options.is(TypeResolverContext::GenericRequirement))
1118-
return ErrorType::get(ctx);
1119-
11201085
auto type = resolution.mapTypeIntoContext(
11211086
dc->getInnermostTypeContext()->getSelfInterfaceType());
11221087

@@ -1256,6 +1221,41 @@ static Type diagnoseUnknownType(TypeResolution resolution,
12561221
return ErrorType::get(ctx);
12571222
}
12581223

1224+
enum class SelfTypeKind {
1225+
StaticSelf,
1226+
DynamicSelf,
1227+
InvalidSelf
1228+
};
1229+
1230+
static SelfTypeKind getSelfTypeKind(DeclContext *dc,
1231+
TypeResolutionOptions options) {
1232+
auto *typeDC = dc->getInnermostTypeContext();
1233+
1234+
// For protocols, skip this code path and find the 'Self' generic parameter.
1235+
if (typeDC->getSelfProtocolDecl())
1236+
return SelfTypeKind::InvalidSelf;
1237+
1238+
// In enums and structs, 'Self' is just a shorthand for the nominal type,
1239+
// and can be used anywhere.
1240+
if (!typeDC->getSelfClassDecl())
1241+
return SelfTypeKind::StaticSelf;
1242+
1243+
// In local functions inside classes, 'Self' is the DynamicSelfType and can
1244+
// be used anywhere.
1245+
if (dc->isLocalContext())
1246+
return SelfTypeKind::DynamicSelf;
1247+
1248+
// In class methods, 'Self' is the DynamicSelfType and can only appear in
1249+
// the return type.
1250+
switch (options.getBaseContext()) {
1251+
case TypeResolverContext::FunctionResult:
1252+
case TypeResolverContext::PatternBindingDecl:
1253+
return SelfTypeKind::DynamicSelf;
1254+
default:
1255+
return SelfTypeKind::InvalidSelf;
1256+
}
1257+
}
1258+
12591259
/// Resolve the given identifier type representation as an unqualified type,
12601260
/// returning the type it references.
12611261
///
@@ -1282,31 +1282,29 @@ resolveTopLevelIdentTypeComponent(TypeResolution resolution,
12821282
// Resolve the first component, which is the only one that requires
12831283
// unqualified name lookup.
12841284
auto DC = resolution.getDeclContext();
1285+
auto id = comp->getIdentifier();
12851286

12861287
// Dynamic 'Self' in the result type of a function body.
1287-
if (comp->getIdentifier() == ctx.Id_Self) {
1288-
switch (options.getBaseContext()) {
1289-
case TypeResolverContext::FunctionResult: {
1290-
if (auto *typeDC = DC->getInnermostTypeContext()) {
1291-
// FIXME: The passed-in TypeRepr should get 'typechecked' as well.
1292-
// The issue is though that ComponentIdentTypeRepr only accepts a ValueDecl
1293-
// while the 'Self' type is more than just a reference to a TypeDecl.
1294-
auto selfType = resolution.mapTypeIntoContext(
1295-
typeDC->getSelfInterfaceType());
1296-
if (!typeDC->getSelfClassDecl())
1297-
return selfType;
1288+
if (id == ctx.Id_Self) {
1289+
if (auto *typeDC = DC->getInnermostTypeContext()) {
1290+
// FIXME: The passed-in TypeRepr should get 'typechecked' as well.
1291+
// The issue is though that ComponentIdentTypeRepr only accepts a ValueDecl
1292+
// while the 'Self' type is more than just a reference to a TypeDecl.
1293+
auto selfType = resolution.mapTypeIntoContext(
1294+
typeDC->getSelfInterfaceType());
1295+
1296+
// Check if we can reference Self here, and if so, what kind of Self it is.
1297+
switch (getSelfTypeKind(DC, options)) {
1298+
case SelfTypeKind::StaticSelf:
1299+
return selfType;
1300+
case SelfTypeKind::DynamicSelf:
12981301
return DynamicSelfType::get(selfType, ctx);
1302+
case SelfTypeKind::InvalidSelf:
1303+
break;
12991304
}
1300-
1301-
break;
1302-
}
1303-
default:
1304-
break;
13051305
}
13061306
}
13071307

1308-
auto id = comp->getIdentifier();
1309-
13101308
NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
13111309
if (options.contains(TypeResolutionFlags::KnownNonCascadingDependency))
13121310
lookupOptions |= NameLookupFlags::KnownPrivate;
@@ -1375,10 +1373,6 @@ resolveTopLevelIdentTypeComponent(TypeResolution resolution,
13751373
if (options.contains(TypeResolutionFlags::SilenceErrors))
13761374
return ErrorType::get(ctx);
13771375

1378-
if (id == ctx.Id_Self)
1379-
if (auto SelfType = SelfAllowedBySE0068(resolution, options))
1380-
return SelfType;
1381-
13821376
return diagnoseUnknownType(resolution, nullptr, SourceRange(), comp,
13831377
options, lookupOptions);
13841378
}

test/decl/ext/generic.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ extension GenericClass : P3 where T : P3 { }
150150

151151
extension GenericClass where Self : P3 { }
152152
// expected-error@-1{{'Self' is only available in a protocol or as the result of a method in a class; did you mean 'GenericClass'?}} {{30-34=GenericClass}}
153+
// expected-error@-2{{'GenericClass<T>' in conformance requirement does not refer to a generic parameter or associated type}}
153154

154155
protocol P4 {
155156
associatedtype T

test/type/self.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ final class FinalMario : Mario {
4747

4848
class A<T> {
4949
typealias _Self = Self
50-
// expected-error@-1 {{'Self' is not available in a typealias}}
50+
// expected-error@-1 {{'Self' is only available in a protocol or as the result of a method in a class; did you mean 'A'?}}
5151
let b: Int
5252
required init(a: Int) {
5353
print("\(Self.self).\(#function)")

validation-test/compiler_crashers_2_fixed/0164-sr7989.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ struct Var<N> {}
88
extension Var : P2 where N : P1 { }
99

1010
protocol P3 {}
11-
extension Var : P3 where Self : P2 {} // expected-error {{'Self' is only available in a protocol or as the result of a method in a class; did you mean 'Var'?}}
11+
extension Var : P3 where Self : P2 {} // expected-error {{type 'Var<N>' in conformance requirement does not refer to a generic parameter or associated type}}

0 commit comments

Comments
 (0)