I propose we allow ByRefLike and ReadOnly struct anonymous records.
You can create struct anonymous records as such today:
let f (r: struct {| IntVal: int |}) = r.IntVal
f {| IntVal=12 |}
// Or if you don't like structness inference: f struct {| IntVal=12 |}
However, there is no ability to make them ByRefLike, which means you cannot have them contain other ByRefLike structs such as Span<'T>.
A possible declaration syntax might look like this:
// Attribute
let f ([<IsByRefLike>] r: {| S: Span<int> |}) = S.Length
// Keyword
let a (r: byref struct {| S: Span<int> |}) = S.Length
let b (r: struct byref {| S: Span<int> |}) = S.Length
let c (r: byreflike {| S: Span<int> |}) = S.Length // 'byrefLike' implies struct
It would be sort of nonsense to have you require an attribute to instantiate one, so a keyword would likely be needed:
a byref struct {| S = Span<int>.Empty |}
b struct byref {| S = Span<int>.Empty |}
c byreflike {| S = Span<int>.Empty |} // 'byrefLike' implies struct
Or perhaps structness inference would take care of the instantiation site:
// Inferred to by a ByRefLike struct anonymous record
a {| S = Span<int>.Empty |}
Similarly, there is no way to define a IsReadOnly struct anonymous record. Possible declaration syntax:
// Attribute
let f ([<IsReadOnly>] r: {| F: FooReadOnly<int> |}) = S.Length
// Keyword
let a (r: readonly struct {| F: FooReadOnly<int> |}) = S.Length
let b (r: struct readonly {| F: FooReadOnly<int> |}) = S.Length
let c (r: readonly {| F: FooReadOnly<int> |}) = S.Length // 'readonly' implies struct
And an instantiation syntax:
a readonly struct {| F = FooReadOnly<int>.Empty |}
b struct readonly {| F = FooReadOnly<int>.Empty |}
c readonly {| F = FooReadOnly<int>.Empty |} // 'byrefLike' implies struct
Declaration syntax options for having both:
// Attribute declaration
let f ([<IsReadOnly; IsByRefLike>] r: {| S: ReadOnlySpan<int> |}) = S.Length
// Syntax declarations
let a (r: byreflike readonly struct {| S: ReadOnlySpan<int> |}) = S.Length
let b (r: struct byreflike readonly {| S: ReadOnlySpan<int> |}) = S.Length
let c (r: byreflike readonly {| S: ReadOnlySpan<int> |}) = S.Length // 'byrefLike' and 'readonly' imply struct
Instantiation syntax for having both:
a byref readonly struct {| R = ReadOnlySpan<int>.Empty |}
b struct byref readonly {| R = ReadOnlySpan<int>.Empty |}
c byreflike readonly struct {| R = ReadOnlySpan<int>.Empty |}
Structness inference could capture both IsByRefLike and IsReadOnly:
f {| R = ReadOnlySpan<int>.Empty |} // Only works if the input type is byref-like and readonly
Pros and Cons
Advantages:
- Parity with records
- Allows you to use these more ephemeral constructs in the perf-sensitive environments ByRefLike structs are intended for
Disadvantages:
- I can't think of an explicit instantiation syntax that doesn't kind of suck
- This can make an input parameter heavy syntax-wise
- These kinds of structs are done with attributes in F# today, but to enable them for anonymous records would require a keyword due to the lack of support for attributes on function parameters
- Allowing a keyword instead of an attribute is inconsistent with how you define ByRefLike structs today in F#
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
I propose we allow ByRefLike and ReadOnly struct anonymous records.
You can create struct anonymous records as such today:
However, there is no ability to make them ByRefLike, which means you cannot have them contain other ByRefLike structs such as
Span<'T>.A possible declaration syntax might look like this:
It would be sort of nonsense to have you require an attribute to instantiate one, so a keyword would likely be needed:
Or perhaps structness inference would take care of the instantiation site:
Similarly, there is no way to define a
IsReadOnlystruct anonymous record. Possible declaration syntax:And an instantiation syntax:
Declaration syntax options for having both:
Instantiation syntax for having both:
Structness inference could capture both
IsByRefLikeandIsReadOnly:Pros and Cons
Advantages:
Disadvantages:
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply: