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