Skip to content

Commit 883374e

Browse files
authored
Merge branch 'main' into copilot/fix-9141961-29048891-8f02666a-f3c0-4c69-bf82-fde45e879f9c
2 parents 8521961 + 5bcca43 commit 883374e

4 files changed

Lines changed: 105 additions & 1 deletion

File tree

docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Fix DU case names matching IWSAM member names no longer cause duplicate property entries. (Issue [#14321](https://github.com/dotnet/fsharp/issues/14321), [PR #19341](https://github.com/dotnet/fsharp/pull/19341))
44
* Fix DefaultAugmentation(false) duplicate entry in method table. (Issue [#16565](https://github.com/dotnet/fsharp/issues/16565), [PR #19341](https://github.com/dotnet/fsharp/pull/19341))
55
* Fix abstract event accessors now have SpecialName flag. (Issue [#5834](https://github.com/dotnet/fsharp/issues/5834), [PR #19341](https://github.com/dotnet/fsharp/pull/19341))
6+
* Fix warning 20 ("expression is implicitly ignored") pointing at the wrong range when the last expression in a sequential block (e.g. inside `for`, `while` loops) is non-unit. The squiggle now correctly highlights only the offending expression. ([Issue #5735](https://github.com/dotnet/fsharp/issues/5735), [PR #19504](https://github.com/dotnet/fsharp/pull/19504))
67
* Fix CLIEvent properties to be correctly recognized as events: `IsEvent` returns `true` and `XmlDocSig` uses `E:` prefix instead of `P:`. ([Issue #10273](https://github.com/dotnet/fsharp/issues/10273), [PR #18584](https://github.com/dotnet/fsharp/pull/18584))
78
* Fix extra sequence point at the end of match expressions. ([Issue #12052](https://github.com/dotnet/fsharp/issues/12052), [PR #19278](https://github.com/dotnet/fsharp/pull/19278))
89
* Fix wrong sequence point range for `return`/`yield`/`return!`/`yield!` inside computation expressions. ([Issue #19248](https://github.com/dotnet/fsharp/issues/19248), [PR #19278](https://github.com/dotnet/fsharp/pull/19278))

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5522,7 +5522,16 @@ and TcStmtThatCantBeCtorBody (cenv: cenv) env tpenv synExpr =
55225522
and TcStmt (cenv: cenv) env tpenv synExpr =
55235523
let g = cenv.g
55245524
let expr, ty, tpenv = TcExprOfUnknownType cenv env tpenv synExpr
5525-
let m = synExpr.Range
5525+
5526+
// Use the range of the last expression in a sequential chain for warnings,
5527+
// so that "expression is ignored" diagnostics point at the offending expression
5528+
// rather than the entire sequential body. See https://github.com/dotnet/fsharp/issues/5735
5529+
let rec lastExprRange (e: SynExpr) =
5530+
match e with
5531+
| SynExpr.Sequential(expr2 = expr2) -> lastExprRange expr2
5532+
| _ -> e.Range
5533+
5534+
let m = lastExprRange synExpr
55265535
let wasUnit = UnifyUnitType cenv env m ty expr
55275536
if wasUnit then
55285537
expr, tpenv

tests/FSharp.Compiler.ComponentTests/ErrorMessages/DiagnosticRegressionTests.fs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,43 @@ type Vehicle() = class end
5050
[ (Error 39, Line 3, Col 14, Line 3, Col 28, "The type 'OutOfScopeType' is not defined.")
5151
(Error 267, Line 3, Col 7, Line 3, Col 29, "This is not a valid constant expression or custom attribute value") ]
5252

53+
// https://github.com/dotnet/fsharp/issues/10043
54+
[<Fact>]
55+
let ``Issue 10043 - backtick in type annotation should not report unexpected keyword`` () =
56+
FSharp
57+
"""
58+
let i:float`1 = 3.0
59+
"""
60+
|> typecheck
61+
|> shouldFail
62+
|> withDiagnostics
63+
[ (Error 3563, Line 2, Col 12, Line 2, Col 13, "This is not a valid identifier")
64+
(Error 10, Line 2, Col 13, Line 2, Col 14, "Unexpected integer literal in binding. Expected '=' or other token.") ]
65+
66+
// https://github.com/dotnet/fsharp/issues/10043
67+
[<Fact>]
68+
let ``Issue 10043 - at sign in type annotation should report infix operator`` () =
69+
FSharp
70+
"""
71+
let i:float@1 = 3.0
72+
"""
73+
|> typecheck
74+
|> shouldFail
75+
|> withDiagnostics
76+
[ (Error 615, Line 2, Col 12, Line 2, Col 13, "Unexpected infix operator in type expression") ]
77+
78+
// https://github.com/dotnet/fsharp/issues/10043
79+
[<Fact>]
80+
let ``Issue 10043 - bang in type annotation should report reserved identifier`` () =
81+
FSharp
82+
"""
83+
let i:float!1 = 3.0
84+
"""
85+
|> typecheck
86+
|> shouldFail
87+
|> withDiagnostics
88+
[ (Error 1141, Line 2, Col 7, Line 2, Col 13, "Identifiers followed by '!' are reserved for future use")
89+
(Error 10, Line 2, Col 13, Line 2, Col 14, "Unexpected integer literal in binding. Expected '=' or other token.") ]
5390

5491
// https://github.com/dotnet/fsharp/issues/7177
5592
[<Fact>]

tests/FSharp.Compiler.ComponentTests/ErrorMessages/WarnExpressionTests.fs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,63 @@ while x < 1 do
176176
|> withSingleDiagnostic (Warning 20, Line 6, Col 5, Line 6, Col 9,
177177
"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'.")
178178

179+
// https://github.com/dotnet/fsharp/issues/5735
180+
[<Fact>]
181+
let ``Warn On Last Expression In For Loop - int``() =
182+
FSharp """
183+
module ClassLibrary17
184+
185+
for i in 1 .. 10 do
186+
printfn ""
187+
printfn "" |> ignore
188+
123
189+
"""
190+
|> typecheck
191+
|> shouldFail
192+
|> withSingleDiagnostic (Warning 20, Line 7, Col 5, Line 7, Col 8,
193+
"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'.")
194+
195+
// https://github.com/dotnet/fsharp/issues/5735
196+
[<Fact>]
197+
let ``Warn On Last Expression In For Loop - string``() =
198+
FSharp """
199+
for i in 1 .. 10 do
200+
printfn ""
201+
"hello"
202+
"""
203+
|> typecheck
204+
|> shouldFail
205+
|> withSingleDiagnostic (Warning 20, Line 4, Col 5, Line 4, Col 12,
206+
"The result of this expression has type 'string' 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'.")
207+
208+
// https://github.com/dotnet/fsharp/issues/5735
209+
[<Fact>]
210+
let ``Warn On Last Expression In Integer For Loop``() =
211+
FSharp """
212+
for i = 1 to 10 do
213+
printfn ""
214+
42
215+
"""
216+
|> typecheck
217+
|> shouldFail
218+
|> withSingleDiagnostic (Warning 20, Line 4, Col 5, Line 4, Col 7,
219+
"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'.")
220+
221+
// https://github.com/dotnet/fsharp/issues/5735
222+
[<Fact>]
223+
let ``Warn On Last Expression In While Loop - non-bool``() =
224+
FSharp """
225+
let mutable x = 0
226+
while x < 1 do
227+
printfn "unneeded"
228+
x <- x + 1
229+
123
230+
"""
231+
|> typecheck
232+
|> shouldFail
233+
|> withSingleDiagnostic (Warning 20, Line 6, Col 5, Line 6, Col 8,
234+
"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'.")
235+
179236
[<Fact>]
180237
let ``Warn If Possible Property Setter``() =
181238
FSharp """

0 commit comments

Comments
 (0)