From 95994f106d272cbda8b7d877aff3b1dd1af9fe88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 10:30:08 +0000 Subject: [PATCH 1/7] Initial plan From 6ffdaeac3a550d68b546dcddf0683f131cdd8a40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:09:11 +0000 Subject: [PATCH 2/7] Implement IsByRefLikeAttribute exclusion in CheckFSharpAttributesForObsolete Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- src/Compiler/Checking/AttributeChecking.fs | 11 ++++++++++- .../FSharp.Editor.Tests/CompletionProviderTests.fs | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 6e6cef5461b..d5bf6b0d473 100755 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -461,7 +461,16 @@ let CheckFSharpAttributesForHidden g attribs = /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. let CheckFSharpAttributesForObsolete g attribs = - not (isNil attribs) && (HasFSharpAttribute g g.attrib_SystemObsolete attribs) + not (isNil attribs) && + (HasFSharpAttribute g g.attrib_SystemObsolete attribs) && + // Exclude types marked with IsByRefLikeAttribute from being considered obsolete, + // even if ObsoleteAttribute is present. This avoids improper suppression of types + // like Span and ReadOnlySpan in completion lists due to their dual attributes. + not (attribs |> List.exists (fun (Attrib(tcref, _, _, _, _, _, _)) -> + match tcref.CompiledRepresentation with + | CompiledTypeRepr.ILAsmNamed(typeRef, _, _) -> + typeRef.FullName = tname_IsByRefLikeAttribute + | _ -> false)) /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. /// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index 4377253d1ad..51cee9fb192 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -2130,6 +2130,17 @@ Ops.() VerifyCompletionList(fileContents, "Ops.Foo.(", [], [ "|>>"; "(|>>)" ]) VerifyCompletionList(fileContents, "Ops.(", [], [ "|>>"; "(|>>)" ]) + [] + let ``Span and ReadOnlySpan appear in completion and are not marked obsolete`` () = + let fileContents = + """ +let test = System.Sp +""" + + // Verify that both Span and ReadOnlySpan appear in completion + // and are not suppressed due to IsByRefLikeAttribute + VerifyCompletionList(fileContents, "System.Sp", [ "Span"; "ReadOnlySpan" ], []) + [] let ``Check code generation for completion to overridable slots`` () = let fileContents = From 32d02ade267b8c481969c958affc1a37c353ef40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:31:51 +0000 Subject: [PATCH 3/7] Fix IsByRefLikeAttribute exclusion using proper TcGlobals pattern - Add attrib_IsByRefLikeAttribute_opt to TcGlobals as optional attribute - Fix CheckFSharpAttributesForObsolete to use HasFSharpAttributeOpt pattern - Add proper signature in TcGlobals.fsi - Update test to expect only 'Span' for 'System.Sp' completion Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- src/Compiler/Checking/AttributeChecking.fs | 8 ++------ src/Compiler/TypedTree/TcGlobals.fs | 1 + src/Compiler/TypedTree/TcGlobals.fsi | 2 ++ .../tests/FSharp.Editor.Tests/CompletionProviderTests.fs | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index d5bf6b0d473..1c13d226d57 100755 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -460,17 +460,13 @@ let CheckFSharpAttributesForHidden g attribs = | _ -> false) /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. -let CheckFSharpAttributesForObsolete g attribs = +let CheckFSharpAttributesForObsolete (g:TcGlobals) attribs = not (isNil attribs) && (HasFSharpAttribute g g.attrib_SystemObsolete attribs) && // Exclude types marked with IsByRefLikeAttribute from being considered obsolete, // even if ObsoleteAttribute is present. This avoids improper suppression of types // like Span and ReadOnlySpan in completion lists due to their dual attributes. - not (attribs |> List.exists (fun (Attrib(tcref, _, _, _, _, _, _)) -> - match tcref.CompiledRepresentation with - | CompiledTypeRepr.ILAsmNamed(typeRef, _, _) -> - typeRef.FullName = tname_IsByRefLikeAttribute - | _ -> false)) + not (HasFSharpAttributeOpt g g.attrib_IsByRefLikeAttribute_opt attribs) /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. /// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 8f82eebc078..e97e774d7b8 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -1481,6 +1481,7 @@ type TcGlobals( member val enum_DynamicallyAccessedMemberTypes = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes" member val attrib_SystemObsolete = findSysAttrib "System.ObsoleteAttribute" + member val attrib_IsByRefLikeAttribute_opt = tryFindSysAttrib "System.Runtime.CompilerServices.IsByRefLikeAttribute" member val attrib_DllImportAttribute = tryFindSysAttrib "System.Runtime.InteropServices.DllImportAttribute" member val attrib_StructLayoutAttribute = findSysAttrib "System.Runtime.InteropServices.StructLayoutAttribute" member val attrib_TypeForwardedToAttribute = findSysAttrib "System.Runtime.CompilerServices.TypeForwardedToAttribute" diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi index f7a3ca11e0c..f4b866d8fbc 100644 --- a/src/Compiler/TypedTree/TcGlobals.fsi +++ b/src/Compiler/TypedTree/TcGlobals.fsi @@ -498,6 +498,8 @@ type internal TcGlobals = member attrib_SystemObsolete: BuiltinAttribInfo + member attrib_IsByRefLikeAttribute_opt: BuiltinAttribInfo option + member attrib_ThreadStaticAttribute: BuiltinAttribInfo option member attrib_TypeForwardedToAttribute: BuiltinAttribInfo diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index 51cee9fb192..273e7ad8d6f 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -2131,15 +2131,15 @@ Ops.() VerifyCompletionList(fileContents, "Ops.(", [], [ "|>>"; "(|>>)" ]) [] - let ``Span and ReadOnlySpan appear in completion and are not marked obsolete`` () = + let ``Span appears in completion and is not marked obsolete`` () = let fileContents = """ let test = System.Sp """ - // Verify that both Span and ReadOnlySpan appear in completion - // and are not suppressed due to IsByRefLikeAttribute - VerifyCompletionList(fileContents, "System.Sp", [ "Span"; "ReadOnlySpan" ], []) + // Verify that Span appears in completion when typing "System.Sp" + // and is not suppressed due to IsByRefLikeAttribute + VerifyCompletionList(fileContents, "System.Sp", [ "Span" ], []) [] let ``Check code generation for completion to overridable slots`` () = From 0a90d013a01b89c4d4da57862f2f65b80594a48a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:54:02 +0000 Subject: [PATCH 4/7] Add release notes for IsByRefLikeAttribute completion fix Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/10.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index 70920a02872..d460d72a3ac 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -15,6 +15,7 @@ * Completion: fix previous namespace considered opened [PR #18609](https://github.com/dotnet/fsharp/pull/18609) * Fix active pattern typechecking regression. ([Issue #18638](https://github.com/dotnet/fsharp/issues/18638), [PR #18642](https://github.com/dotnet/fsharp/pull/18642)) * Fix nullness warnings when casting non-nullable values to `IEquatable` to match C# behavior. ([Issue #18759](https://github.com/dotnet/fsharp/issues/18759)) +* Fix IsByRefLikeAttribute types being incorrectly suppressed in completion lists. Types like `Span` and `ReadOnlySpan` now appear correctly in IntelliSense. ### Changed * Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645)) From fd59bfe7228ded68abd9fc82953a73366d50d1a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:40:40 +0000 Subject: [PATCH 5/7] Move Span completion test to FSharp.Compiler.Service.Tests with .NET Core conditioning Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../CompletionTests.fs | 15 +++++++++++++++ .../CompletionProviderTests.fs | 11 ----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index c356991673e..4def76b60c6 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -360,3 +360,18 @@ module Module = """ assertHasNoItemsWithNames ["E"] info + +#if NETCOREAPP +[] +let ``Span appears in completion and is not marked obsolete`` () = + let info = Checker.getCompletionInfo """ +let test = System.Sp{caret} +""" + // Debug: Print all completion items that start with "Sp" + let spItems = info.Items |> Array.filter (fun item -> item.NameInCode.StartsWith("Sp")) |> Array.map (_.NameInCode) + printfn "Items starting with 'Sp': %A" spItems + + // Verify that Span appears in completion when typing "System.Sp" + // and is not suppressed due to IsByRefLikeAttribute + assertHasItemWithNames ["Span"] info +#endif diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index 273e7ad8d6f..4377253d1ad 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -2130,17 +2130,6 @@ Ops.() VerifyCompletionList(fileContents, "Ops.Foo.(", [], [ "|>>"; "(|>>)" ]) VerifyCompletionList(fileContents, "Ops.(", [], [ "|>>"; "(|>>)" ]) - [] - let ``Span appears in completion and is not marked obsolete`` () = - let fileContents = - """ -let test = System.Sp -""" - - // Verify that Span appears in completion when typing "System.Sp" - // and is not suppressed due to IsByRefLikeAttribute - VerifyCompletionList(fileContents, "System.Sp", [ "Span" ], []) - [] let ``Check code generation for completion to overridable slots`` () = let fileContents = From eb6e2617016ef83a101406f80723d05c5aca247f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 31 Jul 2025 10:00:56 +0000 Subject: [PATCH 6/7] Clean up debug code and finalize IsByRefLikeAttribute completion fix Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- tests/FSharp.Compiler.Service.Tests/CompletionTests.fs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index 4def76b60c6..6b875777538 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -367,10 +367,6 @@ let ``Span appears in completion and is not marked obsolete`` () = let info = Checker.getCompletionInfo """ let test = System.Sp{caret} """ - // Debug: Print all completion items that start with "Sp" - let spItems = info.Items |> Array.filter (fun item -> item.NameInCode.StartsWith("Sp")) |> Array.map (_.NameInCode) - printfn "Items starting with 'Sp': %A" spItems - // Verify that Span appears in completion when typing "System.Sp" // and is not suppressed due to IsByRefLikeAttribute assertHasItemWithNames ["Span"] info From 2f4b4f848cef886c0f6edac3d6b60cb00d964964 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 31 Jul 2025 16:20:42 +0000 Subject: [PATCH 7/7] Fix IsByRefLikeAttribute exclusion for IL types in completion filtering The original fix only handled F# types through CheckFSharpAttributesForObsolete but types like Span and ReadOnlySpan are .NET types that go through IL attribute checking. Updated CheckILAttributesForUnseen to also exclude types with IsByRefLikeAttribute from being considered obsolete, ensuring they appear in completion lists despite having ObsoleteAttribute. Co-authored-by: abonie <20281641+abonie@users.noreply.github.com> --- src/Compiler/Checking/AttributeChecking.fs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 1c13d226d57..8df68aa0e2e 100755 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -441,7 +441,17 @@ let private CheckProvidedAttributes (g: TcGlobals) m (provAttribs: Tainted + not (Option.isSome (TryDecodeILAttribute isByRefLikeTref cattrs)) + | None -> true + else + false /// Checks the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows /// items to be suppressed from intellisense.