From 3bf9355ae170b5ad3b6e581a3567648aa33b5efc Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 08:26:29 +0200 Subject: [PATCH 1/5] tests: failing repro for #5538 provided-ctor Go-to-Definition (RED) Adds two regression tests in Project25 that exercise GetDeclarationLocation on a provided constructor call (Item.CtorGroup whose head is ProvidedMeth). The constructor's MyType has no TypeProviderDefinitionLocationAttribute, so the current implementation returns DeclNotFound (ProvidedMember ".ctor") instead of jumping to the user's ype T = MyType line. A subsequent commit will fix this in SymbolHelpers.fs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../ProjectAnalysisTests.fs | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs index 6b4f6d946f6..2b1ef8ebe68 100644 --- a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs @@ -3788,6 +3788,84 @@ let ``Test Project25 symbol uses of type-provided members`` () = [| ("file1", ((5, 8), (5, 21))) // line 5: T().DoNothing ("file1", ((10, 8), (10, 26))) |] // line 10: MyType().DoNothing +[] +let ``GetDeclarationLocation on a provided-ctor without DefinitionLocationAttribute returns DeclFound (regression #5538)`` () = + let wholeProjectResults = + Project25.checker.ParseAndCheckProject(Project25.options.Value) + |> Async.RunImmediate + + wholeProjectResults.Diagnostics.Length |> shouldEqual 0 + + let parseResults, checkAnswer = + Project25.checker.ParseAndCheckFileInProject( + Project25.fileName1, + 0, + SourceText.ofString (FileSystem.OpenFileForReadShim(Project25.fileName1).ReadAllText()), + Project25.options.Value) + |> Async.RunImmediate + + let checkResults = + match checkAnswer with + | FSharpCheckFileAnswer.Succeeded r -> r + | _ -> failwith "type-check did not finish" + + ignore parseResults + + // line 5: `let _ = T().DoNothing()` + // col-index 8 is `T`, end of identifier is col 9. + // `T` at this position resolves to Item.CtorGroup(ProvidedMeth :: _), + // which is the broken case in issue #5538. + let declLocation = + checkResults.GetDeclarationLocation( + line = 5, + colAtEndOfNames = 9, + lineText = "let _ = T().DoNothing()", + names = [ "T" ]) + + match declLocation with + | FindDeclResult.DeclFound _ -> () + | FindDeclResult.DeclNotFound reason -> + failwithf "expected DeclFound for provided-ctor `T()`, got DeclNotFound %A" reason + | FindDeclResult.ExternalDecl _ -> + failwith "expected DeclFound for provided-ctor `T()`, got ExternalDecl" + +[] +let ``GetDeclarationLocation on a provided-ctor invoked through the original provided name returns DeclFound (regression #5538)`` () = + let wholeProjectResults = + Project25.checker.ParseAndCheckProject(Project25.options.Value) + |> Async.RunImmediate + + wholeProjectResults.Diagnostics.Length |> shouldEqual 0 + + let _, checkAnswer = + Project25.checker.ParseAndCheckFileInProject( + Project25.fileName1, + 0, + SourceText.ofString (FileSystem.OpenFileForReadShim(Project25.fileName1).ReadAllText()), + Project25.options.Value) + |> Async.RunImmediate + + let checkResults = + match checkAnswer with + | FSharpCheckFileAnswer.Succeeded r -> r + | _ -> failwith "type-check did not finish" + + // line 10: `let _ = MyType().DoNothing()` + // col-index 8 is `M`, end of identifier `MyType` is col 14. + let declLocation = + checkResults.GetDeclarationLocation( + line = 10, + colAtEndOfNames = 14, + lineText = "let _ = MyType().DoNothing()", + names = [ "MyType" ]) + + match declLocation with + | FindDeclResult.DeclFound _ -> () + | FindDeclResult.DeclNotFound reason -> + failwithf "expected DeclFound for provided-ctor `MyType()`, got DeclNotFound %A" reason + | FindDeclResult.ExternalDecl _ -> + failwith "expected DeclFound for provided-ctor `MyType()`, got ExternalDecl" + [] let ``Test Project25 symbol uses of type-provided types`` () = let wholeProjectResults = Project25.checker.ParseAndCheckProject(Project25.options.Value) |> Async.RunImmediate From 75dc4f37337ebca2cb16d672fc930cd41eb5affe Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 09:01:37 +0200 Subject: [PATCH 2/5] compiler: fall back to declaring tycon range for provided ctors (#5538, GREEN) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Compiler/Symbols/SymbolHelpers.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 742e7640293..15663e860ed 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -62,7 +62,9 @@ module internal SymbolHelpers = let rangeOfMethInfo (g: TcGlobals) preferFlag (minfo: MethInfo) = match minfo with #if !NO_TYPEPROVIDERS - | ProvidedMeth(_, mi, _, _) -> Construct.ComputeDefinitionLocationOfProvidedItem mi + | ProvidedMeth(_, mi, _, _) -> + Construct.ComputeDefinitionLocationOfProvidedItem mi + |> Option.orElseWith (fun () -> Some(rangeOfEntityRef preferFlag minfo.DeclaringTyconRef)) #endif | DefaultStructCtor(_, AppTy g (tcref, _)) -> Some(rangeOfEntityRef preferFlag tcref) | _ -> minfo.ArbitraryValRef |> Option.map (rangeOfValRef preferFlag) From c79d4976ba8d3f6dd997c946440d1d6a3796a699 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 09:31:19 +0200 Subject: [PATCH 3/5] compiler: mirror provided-item declaring-tycon fallback in prop/event range (#5538) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Compiler/Symbols/SymbolHelpers.fs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 15663e860ed..442fb873fc6 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -55,7 +55,9 @@ module internal SymbolHelpers = let rangeOfPropInfo preferFlag (pinfo: PropInfo) = match pinfo with #if !NO_TYPEPROVIDERS - | ProvidedProp(_, pi, _) -> Construct.ComputeDefinitionLocationOfProvidedItem pi + | ProvidedProp(_, pi, _) -> + Construct.ComputeDefinitionLocationOfProvidedItem pi + |> Option.orElseWith (fun () -> Some(rangeOfEntityRef preferFlag pinfo.DeclaringTyconRef)) #endif | _ -> pinfo.ArbitraryValRef |> Option.map (rangeOfValRef preferFlag) @@ -72,7 +74,9 @@ module internal SymbolHelpers = let rangeOfEventInfo preferFlag (einfo: EventInfo) = match einfo with #if !NO_TYPEPROVIDERS - | ProvidedEvent (_, ei, _) -> Construct.ComputeDefinitionLocationOfProvidedItem ei + | ProvidedEvent(_, ei, _) -> + Construct.ComputeDefinitionLocationOfProvidedItem ei + |> Option.orElseWith (fun () -> Some(rangeOfEntityRef preferFlag einfo.DeclaringTyconRef)) #endif | _ -> einfo.ArbitraryValRef |> Option.map (rangeOfValRef preferFlag) From 391ad97609965669ab6325094e0424e3cb4c6420 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 12:02:57 +0200 Subject: [PATCH 4/5] release-notes: fix Go-to-Definition for provided constructors (#5538) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 965957dbc0c..1127d2f3417 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -75,6 +75,7 @@ ([PR #19724](https://github.com/dotnet/fsharp/pull/19724)) * Emit debug points at a stack-empty position ([PR #19877](https://github.com/dotnet/fsharp/pull/19877)) * Fix spurious XmlDoc warnings (unknown parameter / no documentation for parameter) under `--warnon:3390` when a get/set property documents the full parameter set across both accessors. ([Issue #13684](https://github.com/dotnet/fsharp/issues/13684), [PR #19884](https://github.com/dotnet/fsharp/pull/19884)) +* Fix Go-to-Definition for provided constructors that lack `TypeProviderDefinitionLocationAttribute`. Navigation now falls back to the declaring type instead of silently failing. ([Issue #5538](https://github.com/dotnet/fsharp/issues/5538)) ### Added From 1d5474b8ec643610828a5e37a978210430aa72a2 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 13:04:01 +0200 Subject: [PATCH 5/5] release-notes: add PR link for #5538 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 1127d2f3417..c36cddf803d 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -75,7 +75,7 @@ ([PR #19724](https://github.com/dotnet/fsharp/pull/19724)) * Emit debug points at a stack-empty position ([PR #19877](https://github.com/dotnet/fsharp/pull/19877)) * Fix spurious XmlDoc warnings (unknown parameter / no documentation for parameter) under `--warnon:3390` when a get/set property documents the full parameter set across both accessors. ([Issue #13684](https://github.com/dotnet/fsharp/issues/13684), [PR #19884](https://github.com/dotnet/fsharp/pull/19884)) -* Fix Go-to-Definition for provided constructors that lack `TypeProviderDefinitionLocationAttribute`. Navigation now falls back to the declaring type instead of silently failing. ([Issue #5538](https://github.com/dotnet/fsharp/issues/5538)) +* Fix Go-to-Definition for provided constructors that lack `TypeProviderDefinitionLocationAttribute`. Navigation now falls back to the declaring type instead of silently failing. ([Issue #5538](https://github.com/dotnet/fsharp/issues/5538), [PR #19917](https://github.com/dotnet/fsharp/pull/19917)) ### Added