Skip to content

Commit 0950a2d

Browse files
authored
Merge pull request swiftlang#33033 from CodaFi/would-that-it-were-so-simple
2 parents a8f02db + 8a7a1d9 commit 0950a2d

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2743,7 +2743,7 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
27432743
// let x = foo()
27442744
// ->
27452745
// _ = foo()
2746-
if (auto *pbd = var->getParentPatternBinding())
2746+
if (auto *pbd = var->getParentPatternBinding()) {
27472747
if (pbd->getSingleVar() == var && pbd->getInit(0) != nullptr &&
27482748
!isa<TypedPattern>(pbd->getPattern(0))) {
27492749
unsigned varKind = var->isLet();
@@ -2755,7 +2755,8 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
27552755
.fixItReplace(replaceRange, "_");
27562756
continue;
27572757
}
2758-
2758+
}
2759+
27592760
// If the variable is defined in a pattern in an if/while/guard statement,
27602761
// see if we can produce a tuned fixit. When we have something like:
27612762
//
@@ -2808,6 +2809,30 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
28082809
}
28092810
}
28102811
}
2812+
2813+
// If the variable is defined in a pattern that isn't one of the usual
2814+
// conditional statements, try to detect and rewrite "simple" binding
2815+
// patterns:
2816+
// case .pattern(let x):
2817+
// ->
2818+
// case .pattern(_):
2819+
if (auto *pattern = var->getParentPattern()) {
2820+
BindingPattern *foundVP = nullptr;
2821+
pattern->forEachNode([&](Pattern *P) {
2822+
if (auto *VP = dyn_cast<BindingPattern>(P))
2823+
if (VP->getSingleVar() == var)
2824+
foundVP = VP;
2825+
});
2826+
2827+
if (foundVP) {
2828+
unsigned varKind = var->isLet();
2829+
Diags
2830+
.diagnose(var->getLoc(), diag::variable_never_used,
2831+
var->getName(), varKind)
2832+
.fixItReplace(foundVP->getSourceRange(), "_");
2833+
continue;
2834+
}
2835+
}
28112836

28122837
// Otherwise, this is something more complex, perhaps
28132838
// let (a,b) = foo()

test/Constraints/patterns.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ default:
131131

132132
// <rdar://problem/19382878> Introduce new x? pattern
133133
switch Optional(42) {
134-
case let x?: break // expected-warning{{immutable value 'x' was never used; consider replacing with '_' or removing it}}
134+
case let x?: break // expected-warning{{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{10-11=_}}
135135
case nil: break
136136
}
137137

test/Parse/switch.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func parseError4(x: Int) {
2828

2929
func parseError5(x: Int) {
3030
switch x {
31-
case let z // expected-error {{expected ':' after 'case'}} expected-warning {{immutable value 'z' was never used}} {{12-13=_}}
31+
case let z // expected-error {{expected ':' after 'case'}} expected-warning {{immutable value 'z' was never used}} {{8-13=_}}
3232
}
3333
}
3434

test/decl/var/usage.swift

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,9 @@ func testFixitsInStatementsWithPatterns(_ a : Int?) {
304304

305305
// <rdar://22774938> QoI: "never used" in an "if let" should rewrite expression to use != nil
306306
func test(_ a : Int?, b : Any) {
307-
if true == true, let x = a { // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{24-25=_}}
307+
if true == true, let x = a { // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{20-25=_}}
308308
}
309-
if let x = a, let y = a { // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{10-11=_}}
309+
if let x = a, let y = a { // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{6-11=_}}
310310
_ = y
311311
}
312312

@@ -447,3 +447,51 @@ func testForwardReferenceCapture() {
447447
innerFunc()
448448
print(x)
449449
}
450+
451+
// rdar://47240768 Expand the definition of "simple" pattern to variables bound in patterns
452+
func testVariablesBoundInPatterns() {
453+
enum StringB {
454+
case simple(b: Bool)
455+
case tuple(b: (Bool, Bool))
456+
case optional(b: Bool?)
457+
}
458+
459+
// Because Swift enables all kinds of creative binding forms, make sure that
460+
// variable patterns occuring directly under a `let` or `var` have that
461+
// introducer stripped by the fixit. All other cases are currently too
462+
// complicated for the VarDeclUsageChecker.
463+
switch StringB.simple(b: true) {
464+
case .simple(b: let b) where false: // expected-warning {{immutable value 'b' was never used; consider replacing with '_' or removing it}} {{19-24=_}}
465+
break
466+
case .simple(b: var b) where false: // expected-warning {{variable 'b' was never used; consider replacing with '_' or removing it}} {{19-24=_}}
467+
break
468+
case var .simple(b: b): // expected-warning {{variable 'b' was never used; consider replacing with '_' or removing it}} {{23-24=_}}
469+
break
470+
case .tuple(b: let (b1, b2)) where false:
471+
// expected-warning@-1 {{immutable value 'b1' was never used; consider replacing with '_' or removing it}} {{23-25=_}}
472+
// expected-warning@-2 {{immutable value 'b2' was never used; consider replacing with '_' or removing it}} {{27-29=_}}
473+
break
474+
case .tuple(b: (let b1, let b2)) where false:
475+
// expected-warning@-1 {{immutable value 'b1' was never used; consider replacing with '_' or removing it}} {{19-25=_}}
476+
// expected-warning@-2 {{immutable value 'b2' was never used; consider replacing with '_' or removing it}} {{27-33=_}}
477+
break
478+
case .tuple(b: (var b1, var b2)) where false:
479+
// expected-warning@-1 {{variable 'b1' was never used; consider replacing with '_' or removing it}} {{19-25=_}}
480+
// expected-warning@-2 {{variable 'b2' was never used; consider replacing with '_' or removing it}} {{27-33=_}}
481+
break
482+
case var .tuple(b: (b1, b2)) where false:
483+
// expected-warning@-1 {{variable 'b1' was never used; consider replacing with '_' or removing it}} {{23-25=_}}
484+
// expected-warning@-2 {{variable 'b2' was never used; consider replacing with '_' or removing it}} {{27-29=_}}
485+
break
486+
case .tuple(b: let b): // expected-warning {{immutable value 'b' was never used; consider replacing with '_' or removing it}} {{18-23=_}}
487+
break
488+
case .optional(b: let x?) where false: // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{25-26=_}}
489+
break
490+
case .optional(b: let .some(x)) where false: // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{31-32=_}}
491+
break
492+
case let .optional(b: x?): // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}} {{25-26=_}}
493+
break
494+
case let .optional(b: .none): // expected-warning {{'let' pattern has no effect; sub-pattern didn't bind any variables}} {{8-12=}}
495+
break
496+
}
497+
}

0 commit comments

Comments
 (0)