Skip to content

Commit 57ee86a

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 c7cbe62 commit 57ee86a

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
@@ -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: 26 additions & 0 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
///
@@ -1448,6 +1467,13 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14481467

14491468
// Check if we can reference 'Self' here, and if so, what kind of Self it is.
14501469
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+
}
1476+
14511477
switch (selfTypeKind) {
14521478
case SelfTypeKind::StaticSelf:
14531479
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)