Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix reporting IsFromComputationExpression for inappropriate symbols #17375

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Fix for exponential runtime in CE builders when using nested implicit yields [PR #17096](https://github.com/dotnet/fsharp/pull/17096)
* Fix several AND operator parser bugs and regressions ([Issue #16447](https://github.com/dotnet/fsharp/issues/16447), [Issue #17134](https://github.com/dotnet/fsharp/issues/17134), [Issue #16309](https://github.com/dotnet/fsharp/issues/16309), [PR #17113](https://github.com/dotnet/fsharp/pull/17113))
* Treat exceptions as types in a namespace for graph based type checking ([Issue #17262](https://github.com/dotnet/fsharp/issues/17262), [PR #17268](https://github.com/dotnet/fsharp/pull/17268))
* Fix reporting IsFromComputationExpression only for CE builder type constructors and let bindings. ([PR #17375](https://github.com/dotnet/fsharp/pull/17375))

### Added

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,20 @@ let _pythags = seqbuilder {{
|> FSharp
|> typecheck
|> shouldSucceed

[<Fact>]
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
50 changes: 45 additions & 5 deletions tests/FSharp.Compiler.Service.Tests/Symbols.fs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 _
Expand All @@ -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
| _ -> ()
Expand Down
Loading