diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 9f31d7f600e..67473e5d658 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -5585,9 +5585,13 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy.Commit, env.AccessRights) TcConstExpr cenv overallTy env m tpenv synConst | SynExpr.DotLambda (synExpr, m, trivia) -> - if env.NameEnv.eUnqualifiedItems |> Map.containsKey "_arg1" - then + match env.NameEnv.eUnqualifiedItems |> Map.tryFind "_arg1" with + // Compiler-generated _arg items can have more forms, the real underscore will be 1-character wide + | Some (Item.Value(valRef)) when valRef.Range.StartColumn+1 = valRef.Range.EndColumn -> warning(Error(FSComp.SR.tcAmbiguousDiscardDotLambda(), trivia.UnderscoreRange)) + | Some _ -> () + | None -> () + let unaryArg = mkSynId trivia.UnderscoreRange (cenv.synArgNameGenerator.New()) let svar = mkSynCompGenSimplePatVar unaryArg let pushedExpr = pushUnaryArg synExpr unaryArg diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 9894d505948..831120c812d 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -389,6 +389,7 @@ type PhasedDiagnostic with | 3559 -> false // typrelNeverRefinedAwayFromTop - off by default | 3579 -> false // alwaysUseTypedStringInterpolation - off by default | 3582 -> false // infoIfFunctionShadowsUnionCase - off by default + | 3570 -> false // tcAmbiguousDiscardDotLambda - off by default | _ -> match x.Exception with | DiagnosticEnabledWithLanguageFeature(_, _, _, enabled) -> enabled diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs index f0e5c77e865..1cf65b8c482 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs @@ -182,7 +182,32 @@ let ``ToString with F# 7`` () = |> typecheck |> shouldFail |> withSingleDiagnostic (Error 3350, Line 1, Col 16, Line 1, Col 18, "Feature 'underscore dot shorthand for accessor only function' is not available in F# 7.0. Please use language version 8.0 or greater." ) - + +[] +[] +[ _.ToString() """)>] +[ 5 |> _.ToString()) """)>] +let ``Regression 16276 - hidden discard value`` (code) = + Fsx code + |> withLangVersion80 + |> typecheck + |> shouldSucceed + +[] +let ``Regression 16276 - hidden discard value - nested`` () = + Fsx """ +let f (a, (b, c)) = + let _ = 42 + let _ = 43 + (fun (a, (b, c)) -> + let _ = 458 + (fun _ -> 5 |> _.ToString()))""" + |> withLangVersion80 + |> withWarnOn 3570 + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Warning 3570, Line 7, Col 24, Line 7, Col 25, "The meaning of _ is ambiguous here. It cannot be used for a discarded variable and a function shorthand in the same scope.") + [] let ``Simple anonymous unary function shorthands compile`` () = FSharp """ @@ -207,6 +232,7 @@ module One let a : string = {| Inner = (fun x -> x.ToString()) |} |> _.Inner([5] |> _.[0]) """ |> withLangVersion80 + |> withWarnOn 3570 |> typecheck |> shouldFail |> withDiagnostics [ @@ -222,6 +248,7 @@ let b : int -> int -> string = function |5 -> (fun _ -> "Five") |_ -> _.ToString let c : string = let _ = "test" in "asd" |> _.ToString() """ |> withLangVersion80 + |> withWarnOn 3570 |> typecheck |> shouldFail |> withSingleDiagnostic (Warning 3570, Line 3, Col 43, Line 3, Col 44, "The meaning of _ is ambiguous here. It cannot be used for a discarded variable and a function shorthand in the same scope.") \ No newline at end of file