Skip to content

Commit 2a6cc12

Browse files
committed
[ConstraintSystem] Downgrade some invalid specialization uses to a warning until Swift 6 language mode
Some invalid specializations were previously allowed by the compiler and we found some existing code that used that (albeit invalid) syntax, so we need to stage that error as a warning until Swift 6 language mode to avoid source compatibility break. Resolves: rdar://134740240
1 parent 00eee36 commit 2a6cc12

File tree

8 files changed

+85
-42
lines changed

8 files changed

+85
-42
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4606,8 +4606,8 @@ NOTE(duplicated_key_declared_here, none,
46064606
"duplicate key declared here", ())
46074607

46084608
// Generic specializations
4609-
ERROR(cannot_explicitly_specialize_generic_function,none,
4610-
"cannot explicitly specialize a generic function", ())
4609+
ERROR(cannot_explicitly_specialize_function,none,
4610+
"cannot explicitly specialize a%select{| generic}0 function", (bool))
46114611
ERROR(not_a_generic_type,none,
46124612
"cannot specialize non-generic type %0", (Type))
46134613
ERROR(not_a_generic_macro,none,

include/swift/Sema/CSFix.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,8 @@ enum class FixKind : uint8_t {
465465
/// Ignore an attempt to specialize a non-generic type.
466466
AllowConcreteTypeSpecialization,
467467

468-
/// Ignore an attempt to specialize a generic function.
469-
AllowGenericFunctionSpecialization,
468+
/// Ignore an attempt to specialize a (generic) function reference.
469+
AllowFunctionSpecialization,
470470

471471
/// Ignore an out-of-place \c then statement.
472472
IgnoreOutOfPlaceThenStmt,
@@ -3750,17 +3750,19 @@ class AllowConcreteTypeSpecialization final : public ConstraintFix {
37503750
}
37513751
};
37523752

3753-
class AllowGenericFunctionSpecialization final : public ConstraintFix {
3753+
class AllowFunctionSpecialization final : public ConstraintFix {
37543754
ValueDecl *Decl;
37553755

3756-
AllowGenericFunctionSpecialization(ConstraintSystem &cs, ValueDecl *decl,
3757-
ConstraintLocator *locator)
3758-
: ConstraintFix(cs, FixKind::AllowGenericFunctionSpecialization, locator),
3756+
AllowFunctionSpecialization(ConstraintSystem &cs, ValueDecl *decl,
3757+
ConstraintLocator *locator,
3758+
FixBehavior fixBehavior)
3759+
: ConstraintFix(cs, FixKind::AllowFunctionSpecialization, locator,
3760+
fixBehavior),
37593761
Decl(decl) {}
37603762

37613763
public:
37623764
std::string getName() const override {
3763-
return "allow generic function specialization";
3765+
return "allow (generic) function specialization";
37643766
}
37653767

37663768
bool diagnose(const Solution &solution, bool asNote = false) const override;
@@ -3769,11 +3771,11 @@ class AllowGenericFunctionSpecialization final : public ConstraintFix {
37693771
return diagnose(*commonFixes.front().first);
37703772
}
37713773

3772-
static AllowGenericFunctionSpecialization *
3774+
static AllowFunctionSpecialization *
37733775
create(ConstraintSystem &cs, ValueDecl *decl, ConstraintLocator *locator);
37743776

37753777
static bool classof(const ConstraintFix *fix) {
3776-
return fix->getKind() == FixKind::AllowGenericFunctionSpecialization;
3778+
return fix->getKind() == FixKind::AllowFunctionSpecialization;
37773779
}
37783780
};
37793781

lib/Sema/CSDiagnostics.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9365,8 +9365,9 @@ bool ConcreteTypeSpecialization::diagnoseAsError() {
93659365
return true;
93669366
}
93679367

9368-
bool GenericFunctionSpecialization::diagnoseAsError() {
9369-
emitDiagnostic(diag::cannot_explicitly_specialize_generic_function);
9368+
bool InvalidFunctionSpecialization::diagnoseAsError() {
9369+
emitDiagnostic(diag::cannot_explicitly_specialize_function,
9370+
bool(Decl->getAsGenericContext()));
93709371
emitDiagnosticAt(Decl, diag::decl_declared_here, Decl);
93719372
return true;
93729373
}

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3133,13 +3133,15 @@ class ConcreteTypeSpecialization final : public FailureDiagnostic {
31333133
bool diagnoseAsError() override;
31343134
};
31353135

3136-
class GenericFunctionSpecialization final : public FailureDiagnostic {
3136+
/// Diagnose attempts to specialize (generic) function references.
3137+
class InvalidFunctionSpecialization final : public FailureDiagnostic {
31373138
ValueDecl *Decl;
31383139

31393140
public:
3140-
GenericFunctionSpecialization(const Solution &solution, ValueDecl *decl,
3141-
ConstraintLocator *locator)
3142-
: FailureDiagnostic(solution, locator), Decl(decl) {}
3141+
InvalidFunctionSpecialization(const Solution &solution, ValueDecl *decl,
3142+
ConstraintLocator *locator,
3143+
FixBehavior fixBehavior)
3144+
: FailureDiagnostic(solution, locator, fixBehavior), Decl(decl) {}
31433145

31443146
bool diagnoseAsError() override;
31453147
};

lib/Sema/CSFix.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,16 +2618,21 @@ AllowConcreteTypeSpecialization *AllowConcreteTypeSpecialization::create(
26182618
cs, concreteTy, decl, locator, fixBehavior);
26192619
}
26202620

2621-
bool AllowGenericFunctionSpecialization::diagnose(const Solution &solution,
2622-
bool asNote) const {
2623-
GenericFunctionSpecialization failure(solution, Decl, getLocator());
2621+
bool AllowFunctionSpecialization::diagnose(const Solution &solution,
2622+
bool asNote) const {
2623+
InvalidFunctionSpecialization failure(solution, Decl, getLocator(),
2624+
fixBehavior);
26242625
return failure.diagnose(asNote);
26252626
}
26262627

2627-
AllowGenericFunctionSpecialization *AllowGenericFunctionSpecialization::create(
2628-
ConstraintSystem &cs, ValueDecl *decl, ConstraintLocator *locator) {
2628+
AllowFunctionSpecialization *
2629+
AllowFunctionSpecialization::create(ConstraintSystem &cs, ValueDecl *decl,
2630+
ConstraintLocator *locator) {
2631+
auto fixBehavior = cs.getASTContext().isSwiftVersionAtLeast(6)
2632+
? FixBehavior::Error
2633+
: FixBehavior::DowngradeToWarning;
26292634
return new (cs.getAllocator())
2630-
AllowGenericFunctionSpecialization(cs, decl, locator);
2635+
AllowFunctionSpecialization(cs, decl, locator, fixBehavior);
26312636
}
26322637

26332638
bool IgnoreOutOfPlaceThenStmt::diagnose(const Solution &solution,

lib/Sema/CSSimplify.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14069,6 +14069,13 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1406914069

1407014070
auto genericParams = getGenericParams(decl);
1407114071
if (!decl->getAsGenericContext() || !genericParams) {
14072+
if (isa<AbstractFunctionDecl>(decl)) {
14073+
return recordFix(AllowFunctionSpecialization::create(
14074+
*this, decl, getConstraintLocator(locator)))
14075+
? SolutionKind::Error
14076+
: SolutionKind::Solved;
14077+
}
14078+
1407214079
// Allow concrete macros to have specializations with just a warning.
1407314080
return recordFix(AllowConcreteTypeSpecialization::create(
1407414081
*this, type1, decl, getConstraintLocator(locator),
@@ -14111,10 +14118,7 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1411114118
// FIXME: We could support explicit function specialization.
1411214119
if (openedGenericParams.empty() ||
1411314120
(isa<AbstractFunctionDecl>(decl) && !hasParameterPack)) {
14114-
if (!shouldAttemptFixes())
14115-
return SolutionKind::Error;
14116-
14117-
return recordFix(AllowGenericFunctionSpecialization::create(
14121+
return recordFix(AllowFunctionSpecialization::create(
1411814122
*this, decl, getConstraintLocator(locator)))
1411914123
? SolutionKind::Error
1412014124
: SolutionKind::Solved;
@@ -15246,7 +15250,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1524615250
case FixKind::AllowAssociatedValueMismatch:
1524715251
case FixKind::GenericArgumentsMismatch:
1524815252
case FixKind::AllowConcreteTypeSpecialization:
15249-
case FixKind::AllowGenericFunctionSpecialization:
15253+
case FixKind::AllowFunctionSpecialization:
1525015254
case FixKind::IgnoreGenericSpecializationArityMismatch:
1525115255
case FixKind::IgnoreKeyPathSubscriptIndexMismatch:
1525215256
case FixKind::AllowMemberRefOnExistential: {

test/Parse/generic_disambiguation.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -verify-additional-prefix swift5-
2+
// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift6-
23

34
struct A<B> { // expected-note{{generic type 'A' declared here}}
45
init(x:Int) {}
@@ -40,7 +41,9 @@ _ = (a < b, c > d)
4041
_ = a>(b)
4142
_ = a > (b)
4243

43-
generic<Int>(0) // expected-error{{cannot explicitly specialize a generic function}}
44+
generic<Int>(0)
45+
// expected-swift5-warning@-1{{cannot explicitly specialize a generic function}}
46+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
4447

4548
A<B>.c()
4649
A<A<B>>.c()
Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -verify-additional-prefix swift5-
2+
// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift6-
23

34
extension Int {
4-
func foo() -> Int {}
5+
func foo() -> Int {} // expected-note 2 {{'foo()' declared here}}
56
var bar: Int {
67
get {}
78
}
@@ -14,28 +15,53 @@ extension Int {
1415

1516
// https://github.com/swiftlang/swift/issues/74857
1617
func test(i: Int) {
17-
let _ = i.foo<Int>() // expected-error {{cannot specialize non-generic type '() -> Int'}}
18+
let _ = i.foo<Int>()
19+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
20+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
1821

19-
let _ = i.gen<Int>() // expected-error {{cannot explicitly specialize a generic function}}
20-
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
22+
let _ = i.gen<Int>()
23+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
24+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
25+
// expected-error@-3 {{generic parameter 'T' could not be inferred}}
2126

22-
let _ = 0.foo<Int>() // expected-error {{cannot specialize non-generic type '() -> Int'}}
27+
let _ = 0.foo<Int>()
28+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
29+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
2330

24-
let _ = i.gen<Int> // expected-error {{cannot explicitly specialize a generic function}}
25-
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
26-
let _ = i.bar<Int> // expected-error {{cannot specialize non-generic type 'Int'}}
27-
let _ = 0.bar<Int> // expected-error {{cannot specialize non-generic type 'Int'}}
31+
let _ = i.gen<Int>
32+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
33+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
34+
// expected-error@-3 {{generic parameter 'T' could not be inferred}}
35+
let _ = i.bar<Int>
36+
// expected-swift5-error@-1 {{cannot specialize non-generic type 'Int'}}
37+
// expected-swift6-error@-2 {{cannot specialize non-generic type 'Int'}}
38+
let _ = 0.bar<Int>
39+
// expected-swift5-error@-1 {{cannot specialize non-generic type 'Int'}}
40+
// expected-swift6-error@-2 {{cannot specialize non-generic type 'Int'}}
2841
}
2942

3043
extension Bool {
3144
func foo<T>() -> T {} // expected-note {{'foo()' declared here}}
3245
}
3346

34-
let _: () -> Bool = false.foo<Int> // expected-error {{cannot explicitly specialize a generic function}}
47+
let _: () -> Bool = false.foo<Int>
48+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
49+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
3550

3651
func foo(_ x: Int) {
3752
_ = {
38-
_ = x<String> // expected-error {{cannot specialize non-generic type 'Int'}}
53+
_ = x<String>
54+
// expected-swift5-error@-1 {{cannot specialize non-generic type 'Int'}}
55+
// expected-swift6-error@-2 {{cannot specialize non-generic type 'Int'}}
3956
}
4057
}
4158

59+
do {
60+
struct Test<T> {
61+
init(_: (T) -> Void) {} // expected-note {{'init(_:)' declared here}}
62+
}
63+
64+
_ = Test.init<Int>({ (_: Int) -> Void in })
65+
// expected-swift5-warning@-1 {{cannot explicitly specialize a generic function}}
66+
// expected-swift6-error@-2 {{cannot explicitly specialize a generic function}}
67+
}

0 commit comments

Comments
 (0)