diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md index 4888bd1aad6..f9e23daca3d 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md @@ -1,6 +1,7 @@ ### Fixed * Compiler hangs when compiling inline recursive invocation ([Issue #17376](https://github.com/dotnet/fsharp/issues/17376), [PR #17394](https://github.com/dotnet/fsharp/pull/17394)) +* Fix reporting IsFromComputationExpression only for CE builder type constructors and let bindings. ([PR #17375](https://github.com/dotnet/fsharp/pull/17375)) ### Added diff --git a/src/Compiler/Checking/CheckComputationExpressions.fs b/src/Compiler/Checking/CheckComputationExpressions.fs index 4fc0c8844ef..9703087e92b 100644 --- a/src/Compiler/Checking/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/CheckComputationExpressions.fs @@ -252,7 +252,7 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol // An unparameterized custom builder, e.g., `query`, `async`. | Expr.Val(vref, _, m) // A parameterized custom builder, e.g., `builder<…>`, `builder ()`. - | Expr.App(funcExpr = Expr.Val(vref, _, m)) -> + | Expr.App(funcExpr = Expr.Val(vref, _, m)) when not vref.IsMember || vref.IsConstructor -> let item = Item.CustomBuilder(vref.DisplayName, vref) CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) valRefEq cenv.g vref cenv.g.query_value_vref diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 21c1c0de20f..af588b04975 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -135,3 +135,20 @@ let _pythags = seqbuilder {{ |> FSharp |> typecheck |> shouldSucceed + + [] + let ``A CE returned from type member succeeds``() = + FSharp """ +module ComputationExpressionTests +type Builder () = + member _.Bind(x, f) = f x + member _.Return(x) = x + +type A = + static member Prop = Builder () + +let x = A.Prop { return 0 } + """ + |> compile + |> shouldSucceed + |> ignore diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index 2a46d5492f9..c63dca9f6de 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -1,6 +1,5 @@ module FSharp.Compiler.Service.Tests.Symbols -open System open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Service.Tests.Common open FSharp.Compiler.Symbols @@ -1090,19 +1089,32 @@ let builder = Builder () let x = builder { return 3 } let y = builder let z = Builder () { return 3 } + +type A () = + let builder = Builder () + let _ = builder { return 3 } + + static member Builder = Builder () + +type System.Object with + static member Builder = Builder () + +let c = A.Builder { return 3 } +let d = System.Object.Builder { return 3 } """ + shouldEqual checkResults.Diagnostics [||] shouldEqual [ // type Builder () = (2, 5), false - // … = Builder () - (6, 14), false - // let builder = … (6, 4), false + // … = Builder () + (6, 14), false + // let x = builder { return 3 } (8, 8), false // Item.Value _ (8, 8), true // Item.CustomBuilder _ @@ -1112,9 +1124,37 @@ let z = Builder () { return 3 } // let z = Builder () { return 3 } (10, 8), false + + // let builder = … + (13, 8), false + + // … = Builder () + (13, 18), false + + // let x = builder { return 3 } + (14, 12), false // Item.Value _ + (14, 12), true // Item.CustomBuilder _ + + // static member Builder = … + (16, 18), false + + // … = Builder () + (16, 28), false + + // static member Builder = … + (19, 18), false + + // … = Builder () + (19, 28), false + + // A.Builder { return 3 } + (21, 8), false + + // System.Object.Builder { return 3 } + (22, 8), false ] [ - for symbolUse in checkResults.GetAllUsesOfAllSymbolsInFile() do + for symbolUse in checkResults.GetAllUsesOfAllSymbolsInFile() |> Seq.sortBy (fun x -> x.Range.StartLine, x.Range.StartColumn) do match symbolUse.Symbol.DisplayName with | "Builder" | "builder" -> (symbolUse.Range.StartLine, symbolUse.Range.StartColumn), symbolUse.IsFromComputationExpression | _ -> ()