-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change TypedReference to standard ref struct semantics + support __makeref(ref struct) #65255
Comments
The issue with There are a couple of ways we can approach this. The first is that we go the full distance and support everything The second approach is that we limit the set of int i = 42;
Span<int> span = stackalloc int[42];
TypedReference tr1 = __makeref(ref i); // okay
TypedReference tr2 = __makeref(span); // okay
TypedReference tr3 = __makeref(ref span); // error A third approach is to support a Before going any route though we'd need some more input from the runtime team. Essentially we'd need to see samples of what code you want to write, the full set of scenarios you want to support, etc ... Samples are critical to us getting the right defaults with lifetime rules. Note: while
Removing the restriction is easy, adding the correct lifetime rules for
From a language perspective I don't think we need a switch. I think that we can simply assume that if a runtime supports |
Posting a few thoughts I had after reading through the reflection invoke API draft about how I'll be honest, one thing I did not realize is that That does mean though that even the simple examples jump straight into the complicated Span<byte> span = ...;
TypedReference tr = __makeref(span); This effectively creates a ref field that points to a ref struct TR {
ref Span<byte> field;
internal TR(ref Span<byte> span) {
field = ref span;
}
}
TR tr = new(ref span); That means that unless we limit void Swap(ref Span<byte> p1, ref Span<byte> p2);
void Swap(TypedReference p1, TypedReference p2); The MAMM rules would suddenly start needing to treat every // This is an API shape that meets the Swap criteria.
void M(TypedReference tr1, TypedReference tr2)
G(TypedReference p1) {
Span<byte> span = stackalloc byte[42];
// Error!!!
// Have to assume `span` assigned out through p1 which is a stack safety issue
M(p1, __makeref(span));
} The good news though is that this is an extremely controlled
That gives us safety and puts the burden on correctness for the very small number of cases which grab the Still need to think deeper about this and spec it out but I think this is the outline of a way forward here. @RikkiGibson will be doing the spec work on this. |
To support
ref struct
with reflection (invoking and passing), the current 8.0 runtime plan for "safe" code is to leverage the existingTypedReference
type to create and obtainref struct
references through the existing__makeref
and__refvalue
keywords.In addition,
TypedReference
, being a stack-only construct, was added in 1.0 well beforeref struct
support (or byref-like types) and currently has more restricted compiler semantics thanref struct
causing various limitations such as the inability to useref struct
as a field. This has been discussed as fixing or sunsetting "restricted types" inhttps://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/low-level-struct-improvements.md but this has not yet been addressed. See also #64811. cc @jaredpar
An alternative to supporting
__makeref\__refvalue\__reftype
withref struct
but much more expensive, is to support generic method parameters forref struct
. This could be added in the future and new static methods added toTypedReference
to support that. However, based on prior discussions, adding support for__makeref
et al. would be much easier for now.Misc prototyping in the
roslyn
repro to remove the various compiler restrictions shows the 8.0 .NET runtime seems to handle the changes fine. Whether the runtime needs a new "feature switch" should be discussed -- I assume most runtimes, if they supportref struct
andTypedReference
and__makeref
et al., should work as-is without additional work. cc @AaronRobinsonMSFT @jkotasVersion Used:
MSBuild17.4.0+18d5aef85
(C# 11)Steps to Reproduce:
Sample code that repro some of the restricted usages of
TypedReference
but are valid withref structs
such asSpan<object>
.:Related Links:
The text was updated successfully, but these errors were encountered: