You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Treat span-like types with a unit of measure as byref-like #20907
A measure-annotated abbreviation of Span<int> is not treated as byref-like when its unit of measure is anything other than 1. The compiler then accepts code that captures such a value in a closure or uses its type as a type argument, and the program fails at run time.
openSystem[<Measure>]typekg[<MeasureAnnotatedAbbreviation>]typeTaggedSpan<[<Measure>]'u>= Span<int>letsize(s:TaggedSpan<'u>)=0letcapture(s:TaggedSpan<kg>)=lett= s infun()-> size t
letinstantiate(s:TaggedSpan<kg>)= id s
[<EntryPoint>]letmain args =lets= Unchecked.defaultof<TaggedSpan<kg>>if args.Length =0then capture s ()else size (instantiate s)
Actual: this compiles with the .NET SDK 10.0.402 compiler and with main at fbc9be3. Compiled without optimization:
With no arguments, capture throws TypeLoadException: A ByRef or ByRef-like type cannot be used as the type for an instance field in a non-ByRef-like type.
With an argument, instantiate throws VerificationException: Method Microsoft.FSharp.Core.Operators.Identity: type argument 'System.Span`1[System.Int32]' violates the constraint of type parameter 'T'.
Expected: the errors the compiler reports when kg is replaced by 1: FS0406 on the closure in capture, and FS0412 on id s and on Unchecked.defaultof.
isByrefLikeTyconRef does not look at the representation of a measure-annotated type, and stripTyEqns reduces such a type to its representation only when the measure is dimensionless, so TaggedSpan<kg> is not recognised as byref-like. I found this while reviewing #20856, whose tests define TaggedSpan. I have a fix ready.
Note
Prepared with AI assistance (Anthropic Claude, OpenAI Codex); Peter reviewed it.
Activity