Skip to content

Commit c1473e8

Browse files
committed
[Diagnostics] Improve warning suggestion for var in for loop
When iterator consists of tuple of variable and iteration only mutates the tuple partially, improve the warning message from "changing to 'let" to "changing the pattern to '(..., case let, ...)"
1 parent db6bc98 commit c1473e8

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7032,6 +7032,10 @@ WARNING(variable_never_mutated, none,
70327032
"variable %0 was never mutated; "
70337033
"consider %select{removing 'var' to make it|changing to 'let'}1 constant",
70347034
(Identifier, bool))
7035+
WARNING(variable_tuple_elt_never_mutated, none,
7036+
"variable %0 was never mutated; "
7037+
"consider changing the pattern to 'case (..., let %1, ...)'",
7038+
(Identifier, StringRef))
70357039
WARNING(variable_never_read, none,
70367040
"variable %0 was written to, but never read",
70377041
(Identifier))

lib/Sema/MiscDiagnostics.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4102,8 +4102,20 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
41024102

41034103
// If this is a parameter explicitly marked 'var', remove it.
41044104
if (FixItLoc.isInvalid()) {
4105-
Diags.diagnose(var->getLoc(), diag::variable_never_mutated,
4106-
var->getName(), true);
4105+
bool suggestCaseLet = false;
4106+
if (auto *stmt = var->getRecursiveParentPatternStmt()) {
4107+
// Suggest 'var' -> 'case let' conversion
4108+
// in case of 'for' loop and invalid because it's
4109+
// tuple variable.
4110+
suggestCaseLet = isa<ForEachStmt>(stmt);
4111+
}
4112+
if (suggestCaseLet)
4113+
Diags.diagnose(var->getLoc(), diag::variable_tuple_elt_never_mutated,
4114+
var->getName(), var->getNameStr());
4115+
else
4116+
Diags.diagnose(var->getLoc(), diag::variable_never_mutated,
4117+
var->getName(), true);
4118+
41074119
}
41084120
else {
41094121
bool suggestLet = true;

test/decl/var/usage.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,3 +563,11 @@ func testUselessCastWithInvalidParam(foo: Any?) -> Int {
563563
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}}
564564
else { return 54 }
565565
}
566+
567+
// https://github.com/swiftlang/swift/issues/72811
568+
func testEnumeratedForLoop(a: [Int]) {
569+
for var (b, c) in a.enumerated() { // expected-warning {{variable 'b' was never mutated; consider changing the pattern to 'case (..., let b, ...)'}}
570+
c = b
571+
let _ = c
572+
}
573+
}

0 commit comments

Comments
 (0)