Skip to content

Commit e4fb0b8

Browse files
authored
Fix IsByRefLikeAttribute types being incorrectly suppressed in completion lists (#18784)
1 parent 9d2797a commit e4fb0b8

File tree

5 files changed

+33
-3
lines changed

5 files changed

+33
-3
lines changed

docs/release-notes/.FSharp.Compiler.Service/10.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* Completion: fix previous namespace considered opened [PR #18609](https://github.com/dotnet/fsharp/pull/18609)
1717
* Fix active pattern typechecking regression. ([Issue #18638](https://github.com/dotnet/fsharp/issues/18638), [PR #18642](https://github.com/dotnet/fsharp/pull/18642))
1818
* Fix nullness warnings when casting non-nullable values to `IEquatable<T>` to match C# behavior. ([Issue #18759](https://github.com/dotnet/fsharp/issues/18759))
19+
* Fix IsByRefLikeAttribute types being incorrectly suppressed in completion lists. Types like `Span<T>` and `ReadOnlySpan<T>` now appear correctly in IntelliSense.
1920

2021
### Changed
2122
* Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645))

src/Compiler/Checking/AttributeChecking.fs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,17 @@ let private CheckProvidedAttributes (g: TcGlobals) m (provAttribs: Tainted<IProv
441441
/// Indicate if a list of IL attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense.
442442
let CheckILAttributesForUnseen (g: TcGlobals) cattrs _m =
443443
let (AttribInfo(tref, _)) = g.attrib_SystemObsolete
444-
Option.isSome (TryDecodeILAttribute tref cattrs)
444+
let hasObsolete = Option.isSome (TryDecodeILAttribute tref cattrs)
445+
if hasObsolete then
446+
// Exclude types marked with IsByRefLikeAttribute from being considered obsolete,
447+
// even if ObsoleteAttribute is present. This avoids improper suppression of types
448+
// like Span and ReadOnlySpan in completion lists due to their dual attributes.
449+
match g.attrib_IsByRefLikeAttribute_opt with
450+
| Some (AttribInfo(isByRefLikeTref, _)) ->
451+
not (Option.isSome (TryDecodeILAttribute isByRefLikeTref cattrs))
452+
| None -> true
453+
else
454+
false
445455

446456
/// Checks the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows
447457
/// items to be suppressed from intellisense.
@@ -460,8 +470,13 @@ let CheckFSharpAttributesForHidden g attribs =
460470
| _ -> false)
461471

462472
/// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense.
463-
let CheckFSharpAttributesForObsolete g attribs =
464-
not (isNil attribs) && (HasFSharpAttribute g g.attrib_SystemObsolete attribs)
473+
let CheckFSharpAttributesForObsolete (g:TcGlobals) attribs =
474+
not (isNil attribs) &&
475+
(HasFSharpAttribute g g.attrib_SystemObsolete attribs) &&
476+
// Exclude types marked with IsByRefLikeAttribute from being considered obsolete,
477+
// even if ObsoleteAttribute is present. This avoids improper suppression of types
478+
// like Span and ReadOnlySpan in completion lists due to their dual attributes.
479+
not (HasFSharpAttributeOpt g g.attrib_IsByRefLikeAttribute_opt attribs)
465480

466481
/// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense.
467482
/// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows

src/Compiler/TypedTree/TcGlobals.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,7 @@ type TcGlobals(
14811481
member val enum_DynamicallyAccessedMemberTypes = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes"
14821482

14831483
member val attrib_SystemObsolete = findSysAttrib "System.ObsoleteAttribute"
1484+
member val attrib_IsByRefLikeAttribute_opt = tryFindSysAttrib "System.Runtime.CompilerServices.IsByRefLikeAttribute"
14841485
member val attrib_DllImportAttribute = tryFindSysAttrib "System.Runtime.InteropServices.DllImportAttribute"
14851486
member val attrib_StructLayoutAttribute = findSysAttrib "System.Runtime.InteropServices.StructLayoutAttribute"
14861487
member val attrib_TypeForwardedToAttribute = findSysAttrib "System.Runtime.CompilerServices.TypeForwardedToAttribute"

src/Compiler/TypedTree/TcGlobals.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ type internal TcGlobals =
498498

499499
member attrib_SystemObsolete: BuiltinAttribInfo
500500

501+
member attrib_IsByRefLikeAttribute_opt: BuiltinAttribInfo option
502+
501503
member attrib_ThreadStaticAttribute: BuiltinAttribInfo option
502504

503505
member attrib_TypeForwardedToAttribute: BuiltinAttribInfo

tests/FSharp.Compiler.Service.Tests/CompletionTests.fs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,14 @@ module Module =
360360
361361
"""
362362
assertHasNoItemsWithNames ["E"] info
363+
364+
#if NETCOREAPP
365+
[<Fact>]
366+
let ``Span appears in completion and is not marked obsolete`` () =
367+
let info = Checker.getCompletionInfo """
368+
let test = System.Sp{caret}
369+
"""
370+
// Verify that Span appears in completion when typing "System.Sp"
371+
// and is not suppressed due to IsByRefLikeAttribute
372+
assertHasItemWithNames ["Span"] info
373+
#endif

0 commit comments

Comments
 (0)