-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Treat TypedReference
as managed
#66328
Conversation
Note: it's possible this will cause a build break in dotnet/runtime, we should do a test insertion there to make sure we get ahead of any issues. |
@jcouv If you can kick off a build in dotnet/runtime and tag me, I can handle investigating any failures and trying to fix things up. |
2c51bac
to
a4a4a72
Compare
@AaronRobinsonMSFT Here's the PR showing impact on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh, I'd also be concerned that VS is treating TypedReference as unmanaged. Maybe give heads up to infraswat when you merge?
Will do! Also, I started a VS test build (hopefully I did that right). |
```csharp | ||
unsafe | ||
{ | ||
TypeReference* r = null; // warning: This takes the address of, gets the size of, or declares a pointer to a managed type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there would also be errors for example with the unmanaged
constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, we have an error already for TypedReference as a type argument (regardless of constraints). So no other negative effect.
@@ -62,6 +62,9 @@ unsafe void M() | |||
// (10,29): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('RefG<string>') | |||
// var x2 = stackalloc RefG<string>[10]; | |||
Diagnostic(ErrorCode.ERR_ManagedAddr, "RefG<string>").WithArguments("RefG<string>").WithLocation(10, 29), | |||
// (12,29): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('TypedReference') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stackalloc for a managed type wouldn't work at runtime today but could be supported at some point (from offline discussion with David W as part of PR #64294). That's why we kept the CheckManagedAddr
check an error for stackalloc rather than downgrading it to a warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the implementation of TypedReference in the runtime repo, the type doesn't actually contain a reference yet (it's IntPtr). So the error David described wouldn't kick in yet. I'll add stackalloc to the break doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: I've significantly edited this after some discussions on the C# discord, feel free to look through the edits if you want.
I would think stackalloc
should not work for any of the special types TypedReference
, ArgIterator
and RuntimeArgumentHandle
as these can all contain references that only the runtime may understand (and thus keep correct with objects moving around), meaning it should not just be disallowed for TypedReference
. These types would have to be on the stack as their appropriate types for the runtime to be able to understand them, meaning that they shouldn't be able to be stackalloc'd as it could be an invalid operation (apparently current .NET runtime considers ArgIterator
to not have any tracking information, presumably older runtimes also have this, meaning it's not currently invalid, but also not guaranteed to be valid currently). If any of these are not tracked, that is currently an implementation detail and not guaranteed by the spec. Note that in the ECMA-335 spec these types are called byref-like types (I.8.2.1.1), so any restrictions that applies to spans (which are post ECMA-335) should also apply to these types (note also, that the ECMA-335 addendum doesn't change this).
I also do not see what functional difference it would make other than disallowing always incorrect behaviour from being legal in C# without any warning (for something like ArgIterator*
which is not necessarily wrong, but may be) or error (for something like stackalloc ArgIterator[10]
which could be wrong).
Another option could be to add a note to the ECMA-335 addendum stating that ArgIterator
and RuntimeArgumentHandle
do not contain any tracking information, thus making everything valid as it currently is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tagging @AaronRobinsonMSFT in case anything to add.
I'll quote from our chat, "For the current implementation and supported platforms they [ArgIterator and RuntimeArgumentHandle] can be considered unmanaged without issue - they will always point to the stack. I do not expect that we would ever run into a problem with unmanaged constraint for these two."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, that's fair then. I think there should be an addition to the ECMA-335 addendum that these types do not contain any tracking information so that this is actually documented and guaranteed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ill-advised. The ECMA-335 is designed to be agnostic to OS implementation details - even though we violate that occasionally. At present the entire varargs scenario is only supported on Windows and is primarily for the C++/CLI scenario. We could update things and add notes but unless people are using .NET Core and actively innovating in the C++/CLI domain, I don't think doing much them at present is appropriate. The only reason this even came up was because of TypedReference
improvements and @jcouv being curious :) Once we officially decide the varargs message going forward, I agree we should update all of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tagging @AaronRobinsonMSFT in case anything to add. I'll quote from our chat, "For the current implementation and supported platforms they [ArgIterator and RuntimeArgumentHandle] can be considered unmanaged without issue - they will always point to the stack. I do not expect that we would ever run into a problem with unmanaged constraint for these two."
@jcouv Just thought I'd mention that this may not be the case with async2 if it allows byrefs in it at some point, as is widely requested.
/cc @agocke
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as async2 and ArgIterator
and RuntimeArgumentHandle
, it is unlikely and I would push back on adding support for use of either of these types in those scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 2)
It looks like there's a legitimate test failure in the used assemblies leg with test |
@AlekseyTs @cston @RikkiGibson |
a8e8691
to
557fea7
Compare
@@ -9,7 +9,8 @@ Moving forward the `System.TypedReference` type is considered managed. | |||
```csharp | |||
unsafe | |||
{ | |||
TypeReference* r = null; // warning: This takes the address of, gets the size of, or declares a pointer to a managed type | |||
TypedReference* r = null; // warning: This takes the address of, gets the size of, or declares a pointer to a managed type | |||
var a = stackalloc TypedReference[1]; // error: Cannot take the address of, get the size of, or declare a pointer to a managed type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be warning: This takes the address of, ...
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, stackalloc still reports managed types as errors. See #66328 (comment)
@@ -3020,12 +3020,6 @@ protected void SerializeLocalVariableType(LocalVariableTypeEncoder encoder, ILoc | |||
SerializeCustomModifiers(encoder.CustomModifiers(), local.CustomModifiers); | |||
} | |||
|
|||
if (module.IsPlatformType(local.Type, PlatformType.SystemTypedReference)) | |||
{ | |||
encoder.TypedReference(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we have multiple tests creating locals from __makeref
. I also added in test along with TypedReference*
local.
var libSrc = @" | ||
public unsafe class C | ||
{ | ||
public static System.TypedReference* M(System.TypedReference* r) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
Done with review pass (commit 5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 6)
comp.VerifyEmitDiagnostics( | ||
// (4,12): error CS0610: Field or property cannot be of type 'TypedReference' | ||
// public System.TypedReference field; | ||
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(4, 12) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, with a test suggestion.
Fixes #65530
From discussion with runtime team,
ArgIterator
andRuntimeArgumentHandle
should be left as unmanaged for now.Filed API request for SRM: dotnet/runtime#80812