Skip to content

Commit c90d64d

Browse files
committed
Sema: Reject generic arguments applied to 'Self'
Previously these were simply ignored. Fixes https://bugs.swift.org/browse/SR-14731 / rdar://problem/79051797.
1 parent 19ab767 commit c90d64d

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
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: 26 additions & 0 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
///
@@ -1452,6 +1471,13 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14521471

14531472
// Check if we can reference 'Self' here, and if so, what kind of Self it is.
14541473
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+
}
1480+
14551481
switch (selfTypeKind) {
14561482
case SelfTypeKind::StaticSelf:
14571483
return selfType;

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)