Skip to content

Commit cfd6913

Browse files
authored
Merge pull request swiftlang#37891 from slavapestov/generic-args-on-self
Sema: Reject generic arguments applied to 'Self'
2 parents c93390f + c90d64d commit cfd6913

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
@@ -3654,6 +3654,10 @@ ERROR(not_a_generic_definition,none,
36543654
"cannot specialize a non-generic definition", ())
36553655
ERROR(not_a_generic_type,none,
36563656
"cannot specialize non-generic type %0", (Type))
3657+
ERROR(cannot_specialize_self,none,
3658+
"cannot specialize 'Self'", ())
3659+
NOTE(specialize_explicit_type_instead,none,
3660+
"did you mean to explicitly reference %0 instead?", (Type))
36573661
ERROR(type_parameter_count_mismatch,none,
36583662
"generic type %0 specialized with %select{too many|too few}3 type "
36593663
"parameters (got %2, but expected %1)",

lib/Sema/TypeCheckType.cpp

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,25 @@ static SelfTypeKind getSelfTypeKind(DeclContext *dc,
13421342
}
13431343
}
13441344

1345+
static void diagnoseGenericArgumentsOnSelf(TypeResolution resolution,
1346+
ComponentIdentTypeRepr *comp,
1347+
DeclContext *typeDC) {
1348+
ASTContext &ctx = resolution.getASTContext();
1349+
auto &diags = ctx.Diags;
1350+
1351+
auto *selfNominal = typeDC->getSelfNominalTypeDecl();
1352+
auto declaredType = selfNominal->getDeclaredType();
1353+
1354+
diags.diagnose(comp->getNameLoc(), diag::cannot_specialize_self);
1355+
1356+
if (selfNominal->isGeneric() && !isa<ProtocolDecl>(selfNominal)) {
1357+
diags.diagnose(comp->getNameLoc(), diag::specialize_explicit_type_instead,
1358+
declaredType)
1359+
.fixItReplace(comp->getNameLoc().getSourceRange(),
1360+
declaredType.getString());
1361+
}
1362+
}
1363+
13451364
/// Resolve the given identifier type representation as an unqualified type,
13461365
/// returning the type it references.
13471366
///
@@ -1435,40 +1454,48 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14351454
return ErrorType::get(ctx);
14361455
}
14371456

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

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

1466-
return diagnoseUnknownType(resolution, nullptr, SourceRange(), comp,
1467-
lookupOptions);
1481+
switch (selfTypeKind) {
1482+
case SelfTypeKind::StaticSelf:
1483+
return selfType;
1484+
case SelfTypeKind::DynamicSelf:
1485+
return DynamicSelfType::get(selfType, ctx);
1486+
case SelfTypeKind::InvalidSelf:
1487+
break;
1488+
}
1489+
}
14681490
}
14691491

1470-
comp->setValue(currentDecl, currentDC);
1471-
return current;
1492+
// If we're not allowed to complain, bail out.
1493+
if (options.contains(TypeResolutionFlags::SilenceErrors))
1494+
return ErrorType::get(ctx);
1495+
1496+
// Complain and give ourselves a chance to recover.
1497+
return diagnoseUnknownType(resolution, nullptr, SourceRange(), comp,
1498+
lookupOptions);
14721499
}
14731500

14741501
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)