Skip to content

Commit c3ab99a

Browse files
committed
[Sema] Offer 'is' replacement for unused 'if let' expression when the operand is optional
1 parent b8900de commit c3ab99a

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2893,7 +2893,20 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
28932893
!initExpr->isImplicit()) {
28942894
noParens = isIsTest = true;
28952895
}
2896-
2896+
// In cases where the value is optional, the cast expr is
2897+
// wrapped inside OptionalEvaluationExpr. Unwrap it to get
2898+
// ConditionalCheckedCastExpr.
2899+
if (auto oeExpr =
2900+
dyn_cast<OptionalEvaluationExpr>(initExpr)) {
2901+
if (auto ccExpr = dyn_cast<ConditionalCheckedCastExpr>(
2902+
oeExpr->getSubExpr())) {
2903+
if (!ccExpr->isImplicit()) {
2904+
initExpr = ccExpr;
2905+
noParens = isIsTest = true;
2906+
}
2907+
}
2908+
}
2909+
28972910
auto diagIF = Diags.diagnose(var->getLoc(),
28982911
diag::pbd_never_used_stmtcond,
28992912
var->getName());

test/decl/var/usage.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ func test(_ a : Int?, b : Any) {
330330
if let x = b as? Int { // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}} {{6-14=}} {{16-19=is}}
331331
}
332332

333+
// SR-14646. Special case, turn this into an 'is' test with optional value.
334+
let bb: Any? = 3
335+
if let bbb = bb as? Int { // expected-warning {{value 'bbb' was defined but never used; consider replacing with boolean test}} {{6-16=}} {{19-22=is}}
336+
}
337+
333338
// SR-1112
334339

335340
let xxx: Int? = 0
@@ -356,7 +361,7 @@ let optionalString: String? = "check"
356361
if let string = optionalString {} // expected-warning {{value 'string' was defined but never used; consider replacing with boolean test}} {{4-17=}} {{31-31= != nil}}
357362

358363
let optionalAny: Any? = "check"
359-
if let string = optionalAny as? String {} // expected-warning {{value 'string' was defined but never used; consider replacing with boolean test}} {{4-17=(}} {{39-39=) != nil}}
364+
if let string = optionalAny as? String {} // expected-warning {{value 'string' was defined but never used; consider replacing with boolean test}} {{4-17=}} {{29-32=is}}
360365

361366
// Due to the complexities of global variable tracing, these will not generate warnings
362367
let unusedVariable = ""
@@ -504,3 +509,9 @@ func testVariablesBoundInPatterns() {
504509
break
505510
}
506511
}
512+
// Tests fix to SR-1464
513+
func testUselessCastWithInvalidParam(foo: Any?) -> Int {
514+
class Foo { }
515+
if let bar = foo as? Foo { return 42 } // expected-warning {{value 'bar' was defined but never used; consider replacing with boolean test}} {{6-16=}} {{20-23=is}}
516+
else { return 54 }
517+
}

test/stmt/if_while_var.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ if let x = foo() {
5959

6060
var opt: Int? = .none
6161

62-
if let x = opt {} // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}}
63-
if var x = opt {} // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}}
62+
if let x = opt {} // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}} {{4-12=}} {{15-15= != nil}}
63+
if var x = opt {} // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}} {{4-12=}} {{15-15= != nil}}
6464

6565
// <rdar://problem/20800015> Fix error message for invalid if-let
6666
let someInteger = 1

0 commit comments

Comments
 (0)