Skip to content

Commit 07191e3

Browse files
authored
Merge pull request swiftlang#38006 from slavapestov/generic-args-on-self-5.5
Sema: Reject generic arguments applied to 'Self' [5.5]
2 parents bc6ea39 + 57ee86a commit 07191e3

File tree

3 files changed

+78
-30
lines changed

3 files changed

+78
-30
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,6 +3649,10 @@ ERROR(not_a_generic_definition,none,
36493649
"cannot specialize a non-generic definition", ())
36503650
ERROR(not_a_generic_type,none,
36513651
"cannot specialize non-generic type %0", (Type))
3652+
ERROR(cannot_specialize_self,none,
3653+
"cannot specialize 'Self'", ())
3654+
NOTE(specialize_explicit_type_instead,none,
3655+
"did you mean to explicitly reference %0 instead?", (Type))
36523656
ERROR(type_parameter_count_mismatch,none,
36533657
"generic type %0 specialized with %select{too many|too few}3 type "
36543658
"parameters (got %2, but expected %1)",

lib/Sema/TypeCheckType.cpp

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,25 @@ static SelfTypeKind getSelfTypeKind(DeclContext *dc,
13381338
}
13391339
}
13401340

1341+
static void diagnoseGenericArgumentsOnSelf(TypeResolution resolution,
1342+
ComponentIdentTypeRepr *comp,
1343+
DeclContext *typeDC) {
1344+
ASTContext &ctx = resolution.getASTContext();
1345+
auto &diags = ctx.Diags;
1346+
1347+
auto *selfNominal = typeDC->getSelfNominalTypeDecl();
1348+
auto declaredType = selfNominal->getDeclaredType();
1349+
1350+
diags.diagnose(comp->getNameLoc(), diag::cannot_specialize_self);
1351+
1352+
if (selfNominal->isGeneric() && !isa<ProtocolDecl>(selfNominal)) {
1353+
diags.diagnose(comp->getNameLoc(), diag::specialize_explicit_type_instead,
1354+
declaredType)
1355+
.fixItReplace(comp->getNameLoc().getSourceRange(),
1356+
declaredType.getString());
1357+
}
1358+
}
1359+
13411360
/// Resolve the given identifier type representation as an unqualified type,
13421361
/// returning the type it references.
13431362
///
@@ -1431,40 +1450,48 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14311450
return ErrorType::get(ctx);
14321451
}
14331452

1434-
// If we found nothing, complain and give ourselves a chance to recover.
1435-
if (current.isNull()) {
1436-
// Dynamic 'Self' in the result type of a function body.
1437-
if (id.isSimpleName(ctx.Id_Self)) {
1438-
if (auto *typeDC = DC->getInnermostTypeContext()) {
1439-
// FIXME: The passed-in TypeRepr should get 'typechecked' as well.
1440-
// The issue is though that ComponentIdentTypeRepr only accepts a ValueDecl
1441-
// while the 'Self' type is more than just a reference to a TypeDecl.
1442-
auto selfType = resolution.mapTypeIntoContext(
1443-
typeDC->getSelfInterfaceType());
1444-
1445-
// Check if we can reference Self here, and if so, what kind of Self it is.
1446-
switch (getSelfTypeKind(DC, options)) {
1447-
case SelfTypeKind::StaticSelf:
1448-
return selfType;
1449-
case SelfTypeKind::DynamicSelf:
1450-
return DynamicSelfType::get(selfType, ctx);
1451-
case SelfTypeKind::InvalidSelf:
1452-
break;
1453-
}
1454-
}
1455-
}
1453+
// If we found a type declaration with the given name, return it now.
1454+
if (current) {
1455+
comp->setValue(currentDecl, currentDC);
1456+
return current;
1457+
}
14561458

1457-
// If we're not allowed to complain or we couldn't fix the
1458-
// source, bail out.
1459-
if (options.contains(TypeResolutionFlags::SilenceErrors))
1460-
return ErrorType::get(ctx);
1459+
// 'Self' inside of a nominal type refers to that type.
1460+
if (id.isSimpleName(ctx.Id_Self)) {
1461+
if (auto *typeDC = DC->getInnermostTypeContext()) {
1462+
// FIXME: The passed-in TypeRepr should get 'typechecked' as well.
1463+
// The issue is though that ComponentIdentTypeRepr only accepts a ValueDecl
1464+
// while the 'Self' type is more than just a reference to a TypeDecl.
1465+
auto selfType = resolution.mapTypeIntoContext(
1466+
typeDC->getSelfInterfaceType());
1467+
1468+
// Check if we can reference 'Self' here, and if so, what kind of Self it is.
1469+
auto selfTypeKind = getSelfTypeKind(DC, options);
1470+
1471+
// We don't allow generic arguments on 'Self'.
1472+
if (selfTypeKind != SelfTypeKind::InvalidSelf &&
1473+
isa<GenericIdentTypeRepr>(comp)) {
1474+
diagnoseGenericArgumentsOnSelf(resolution, comp, typeDC);
1475+
}
14611476

1462-
return diagnoseUnknownType(resolution, nullptr, SourceRange(), comp,
1463-
lookupOptions);
1477+
switch (selfTypeKind) {
1478+
case SelfTypeKind::StaticSelf:
1479+
return selfType;
1480+
case SelfTypeKind::DynamicSelf:
1481+
return DynamicSelfType::get(selfType, ctx);
1482+
case SelfTypeKind::InvalidSelf:
1483+
break;
1484+
}
1485+
}
14641486
}
14651487

1466-
comp->setValue(currentDecl, currentDC);
1467-
return current;
1488+
// If we're not allowed to complain, bail out.
1489+
if (options.contains(TypeResolutionFlags::SilenceErrors))
1490+
return ErrorType::get(ctx);
1491+
1492+
// Complain and give ourselves a chance to recover.
1493+
return diagnoseUnknownType(resolution, nullptr, SourceRange(), comp,
1494+
lookupOptions);
14681495
}
14691496

14701497
static void diagnoseAmbiguousMemberType(Type baseTy, SourceRange baseRange,

test/type/self.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,20 @@ do {
360360
}
361361
}
362362
}
363+
364+
// https://bugs.swift.org/browse/SR-14731
365+
struct Generic<T> {
366+
func foo() -> Self<Int> {}
367+
// expected-error@-1 {{cannot specialize 'Self'}}
368+
// expected-note@-2 {{did you mean to explicitly reference 'Generic' instead?}}{{17-21=Generic}}
369+
}
370+
371+
struct NonGeneric {
372+
func foo() -> Self<Int> {}
373+
// expected-error@-1 {{cannot specialize 'Self'}}
374+
}
375+
376+
protocol P {
377+
func foo() -> Self<Int>
378+
// expected-error@-1 {{cannot specialize non-generic type 'Self'}}
379+
}

0 commit comments

Comments
 (0)