Warning 20 range: also walk through let/use bindings (follow-up to #19504)#19896
Warning 20 range: also walk through let/use bindings (follow-up to #19504)#19896T-Gro wants to merge 1 commit into
Conversation
- Walk through let/use bindings in addition to Sequential when locating
the offending expression for warning 20. Fixes the case Eugene flagged:
for _ in [] do
let x = 1
x
- Fix wrong issue link (#5735 -> #5418) in code comment, release notes,
and test annotations.
- Add regression tests for the let/use case (single + nested bindings).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
Warning No PR link found in some release notes, please consider adding it.
|
abonie
left a comment
There was a problem hiding this comment.
🤖 AI-generated review — verify before acting on findings.
| |> typecheck | ||
| |> shouldFail | ||
| |> withSingleDiagnostic (Warning 20, Line 5, Col 5, Line 5, Col 10, | ||
| "The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.") |
There was a problem hiding this comment.
[Test Coverage / LOW] The PR title and release note both say "let/use", but the two new tests only cover let bindings. The use path goes through the identical code (SynExpr.LetOrUse is one union case for both), so it works — but there is no regression guard for it.
Suggested addition:
// https://github.com/dotnet/fsharp/issues/5418
[<Fact>]
let ``Warn On Last Expression In For Loop - non-unit after use binding``() =
FSharp """
type D() =
interface System.IDisposable with
member _.Dispose() = ()
member _.Value = 1
for _ in [] do
use d = new D()
d.Value
"""
|> typecheck
|> shouldFail
|> withSingleDiagnostic (Warning 20, Line 8, Col 5, Line 8, Col 12,
"The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.")There was a problem hiding this comment.
If adding more cases, a case with a computation expression could be useful.
| // Use the range of the last expression in a sequential chain (also walking through | ||
| // 'let'/'use' bindings) for warnings, so that "expression is ignored" diagnostics point | ||
| // at the offending expression rather than the entire sequential body. | ||
| // See https://github.com/dotnet/fsharp/issues/5418 |
There was a problem hiding this comment.
@T-Gro Could you cherry-pick the comments rules from the other PR?
| "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.") | ||
|
|
||
| // https://github.com/dotnet/fsharp/issues/5735 | ||
| // https://github.com/dotnet/fsharp/issues/5418 |
There was a problem hiding this comment.
These comments are also redundant: the resulting commit is going to have the link to the PR with all the needed context.
| |> typecheck | ||
| |> shouldFail | ||
| |> withSingleDiagnostic (Warning 20, Line 5, Col 5, Line 5, Col 10, | ||
| "The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.") |
There was a problem hiding this comment.
If adding more cases, a case with a computation expression could be useful.
Follow-up to #19504 addressing review feedback from @auduchinok.
#19504 fixed warning 20 ("expression is implicitly ignored") to point at the last expression of a sequential body inside
for/while. The walk only descended throughSynExpr.Sequential, so when the last expression was the body of alet/usebinding, the squiggle covered the wholeletexpression instead of just the offending tail:This PR also descends through
SynExpr.LetOrUse, so the squiggle lands onxalone in cases like the one above.It also corrects the issue reference cited by the original PR (#5418 — "Wrong expression is ignored warning range"; the previously cited #5735 is unrelated to this diagnostic).
Tracking: #5418