diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 2317eb007da..f820d62d023 100755 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -531,7 +531,7 @@ let UseOfAddressOfOperatorE() = DeclareResourceString("UseOfAddressOfOperator"," let DefensiveCopyWarningE() = DeclareResourceString("DefensiveCopyWarning","%s") let DeprecatedThreadStaticBindingWarningE() = DeclareResourceString("DeprecatedThreadStaticBindingWarning","") let FunctionValueUnexpectedE() = DeclareResourceString("FunctionValueUnexpected","%s") -let UnitTypeExpected1E() = DeclareResourceString("UnitTypeExpected1","%s") +let UnitTypeExpected1E() = DeclareResourceString("UnitTypeExpected1","") let UnitTypeExpected2E() = DeclareResourceString("UnitTypeExpected2","%s") let RecursiveUseCheckedAtRuntimeE() = DeclareResourceString("RecursiveUseCheckedAtRuntime","") let LetRecUnsound1E() = DeclareResourceString("LetRecUnsound1","%s") @@ -1185,7 +1185,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = if perhapsProp then os.Append(UnitTypeExpected2E().Format (NicePrint.stringOfTy denv ty)) |> ignore else - os.Append(UnitTypeExpected1E().Format (NicePrint.stringOfTy denv ty)) |> ignore + os.Append(UnitTypeExpected1E().Format) |> ignore | RecursiveUseCheckedAtRuntime _ -> os.Append(RecursiveUseCheckedAtRuntimeE().Format) |> ignore | LetRecUnsound (_,[v],_) -> diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index f95cf777b4a..f028e00b6f8 100644 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -892,7 +892,7 @@ This expression is a function value, i.e. is missing arguments. Its type is {0}. - This expression should have type 'unit', but has type '{0}'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name. + The result of this expression 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'. This expression should have type 'unit', but has type '{0}'. If assigning to a property use the syntax 'obj.Prop <- expr'. diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs index f527a126c76..e703b6ac2a4 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs @@ -2,7 +2,7 @@ #light // Verify warning when 'do-bindings' do not return unit. -//This expression should have type 'unit', but has type 'int' +//The result of this expression is implicitly ignored let square x = x * x diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs index 1f96f9e14f8..72abc807372 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. // //The value or constructor 'a' is not defined$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ module A = let a = 3 in a + 1 |> ignore;; a > 4;; diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs index d49ef5d5bff..b3799eb1539 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ // module B = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs index 41759f95d54..e0af19fb87c 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ // module C = let a = 3 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs index 5899d4bbbd2..36e735c458e 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ // module D = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs index 183ff1a0e89..68dad9c89db 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. //The type 'int' does not match the type 'unit'$ //Type mismatch\. Expecting a. ''a -> 'b' .but given a. ''a -> unit' .The type 'int' does not match the type 'unit'$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ module E = let a = 3 in a + 1 |> ignore diff --git a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs index 516306e9269..bdb54bf3d7b 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs @@ -2,7 +2,7 @@ #light // Verify warning if a finally block does not return 'unit' -//This expression should have type 'unit', but has type 'bool' +//The result of this expression is implicitly ignored let x : int = try diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs index d36c7227514..453173b9192 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs @@ -1,7 +1,7 @@ // #Conformance #DataExpressions #Query // Where expressions require parenthesis //'where' is not used correctly\. This is a custom operation in this query or computation expression\.$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ let query = query { for i in [1..10] do diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs index 1f0a23ab75e..b930cbaba00 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs @@ -2,7 +2,7 @@ // Regression test for FSHARP1.0:5590 // This code used to compile, but fail peverification // Now, it just does not compile anymore telling the user to annotated it a bit. -//This expression should have type 'unit', but has type 'int'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ //Active pattern '\|A1\|A2\|A3\|' has a result type containing type variables that are not determined by the input\. The common cause is a when a result case is not mentioned, e\.g\. 'let \(\|A\|B\|\) \(x:int\) = A x'\. This can be fixed with a type constraint, e\.g\. 'let \(\|A\|B\|\) \(x:int\) : Choice = A x'$ let (|A1|A2|A3|) (inp:int) : Choice = printfn "hello" diff --git a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs index cac6c4ad929..b68027a1693 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:3596 // Make sure that error spans correctly across multiple lines -//This expression should have type 'unit' +//The result of this expression is implicitly ignored #nowarn "988" let f g x = g x diff --git a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs index c402ba1b347..f6f6443df63 100644 --- a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs +++ b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:2391, FSHARP1.0:1479 -//This expression should have type 'unit', but has type 'seq.Quotations.Var.' +//The result of this expression is implicitly ignored #light "off" <@@ 1 @@>.GetFreeVars() diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs index 9e3adbb5d47..3fe0919320d 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 -//This expression should have type 'unit', but has type 'int'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ async { 1; return 2 } |> ignore diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs index 888b8f9e104..4dd57691e8d 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ let rec loop() = async { let x = 1 in loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs index af12902b2a6..a9bb89c9dac 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ let rec loop() = async { loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs index e612c237631..dfba108aac0 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs @@ -1,6 +1,6 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' let rec loop2() = async.Delay(fun () -> loop2(); ()); diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs index d12252d42c8..b86efb67132 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//The result of this expression 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'.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' // Note: interestingly, this looks much better if a method call is not used let delay x = async.Delay x diff --git a/tests/fsharpqa/Source/Misc/Parsing02.fs b/tests/fsharpqa/Source/Misc/Parsing02.fs index d4db9a719bc..9a17369e870 100644 --- a/tests/fsharpqa/Source/Misc/Parsing02.fs +++ b/tests/fsharpqa/Source/Misc/Parsing02.fs @@ -1,10 +1,10 @@ // #Regression #Misc // Verify warnings associated with top level expressions getting discarded -//This expression should have type 'unit', but has type '\( \^a -> unit\) \* int' -//This expression should have type 'unit', but has type '\('a \[\] -> unit \[\]\) \* string \[\]' +//The result of this expression is implicitly ignored +//The result of this expression is implicitly ignored -// Note the comma between printf "%A", this results in a tuple expr which probabaly wasn't intended. +// Note the comma between printf "%A", this results in a tuple expr which probably wasn't intended. let arr = [|"Foo"; "Bar"|] printf "%d", arr.Length diff --git a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs new file mode 100644 index 00000000000..e43c60b38d9 --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs @@ -0,0 +1,5 @@ +// #Warnings +//The result of this expression 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'.$ + +1 + 2 +printfn "%d" 3 diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index cb14235cc9c..da119ba25d2 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -14,3 +14,4 @@ SOURCE=DowncastInsteadOfUpcast.fs # DowncastInsteadOfUpcast.fs SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs + SOURCE=WarnIfExpressionResultUnused.fs # WarnIfExpressionResultUnused.fs