-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Make Enum.GetValues
AOT-safe
#72236
Make Enum.GetValues
AOT-safe
#72236
Conversation
...at the cost of a small compat break. We return `int[]` instead of `SomeInt32Enum[]`. Fixes dotnet#72140. We can also delete intrinsic handling of `Enum.GetValues` in dataflow analysis but I don't want to conflict with Vitek's dotnet#71485.
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Who owns the System.Enum surface area? I presume this needs to go through a back-compat review |
Only changing it for NativeAOT. |
Woops, missed that this was the nativeaot runtime |
return result; | ||
// Compat: we should be returning SomeInt32Enum[]. Instead we return Int32[]. | ||
// This is a tradeoff since SomeInt32Enum[] type might not have been pregenerated. | ||
return (Array)Enum.GetEnumInfo(this).ValuesAsUnderlyingType.Clone(); |
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.
What guarantees that int[]
will exist though? Or for that matter other enum backing types, like byte[]
, short[]
and so on.
The comment here assumes that they are available, without explanation. I think it would be good to add a short explanation.
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.
What guarantees that
int[]
will exist though?
Good old new
keyword:
runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/EnumInfo.cs
Lines 53 to 64 in 6f13196
ValuesAsUnderlyingType = Type.GetTypeCode(UnderlyingType) switch | |
{ | |
TypeCode.Byte => new byte[numValues], | |
TypeCode.SByte => new sbyte[numValues], | |
TypeCode.UInt16 => new ushort[numValues], | |
TypeCode.Int16 => new short[numValues], | |
TypeCode.UInt32 => new uint[numValues], | |
TypeCode.Int32 => new int[numValues], | |
TypeCode.UInt64 => new ulong[numValues], | |
TypeCode.Int64 => new long[numValues], | |
_ => throw new NotSupportedException(), | |
}; |
I'll add a comment.
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.
Sorry - I was too lazy to lookup what ValuesAsUnderlyingType
does :-(
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
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 but there seems to be some related test failures
- System.Reflection.Tests
- System.Runtime.Tests
- System.IO.FileSystem.DisabledFileLocking.Tests, not clear if the failure is related to the enum change
- System.Collections.NonGeneric.Tests
- System.Numerics.Vectors.Tests
The System.Numerics.Vectors.Tests is #72149. I think that failure is non-deterministic. I'm not sure if it really should be closed unfortunately. I'm looking into the appcompat implications of the other failures (whether we just fixup/disable/add new tests and be done with it, or whether it's blockers). |
I looked at the failing tests. The main implication is that if one does So the compat concern is basically that. Would someone call It's basically what the tests do:
Couple other alternative:
|
This is unfortunate. I would expect in most code, the expectations on post operations after the call to this API, would be to see the Enum type and not the underlying type. I think we need to give an indicator to the developer of the behavioral change in native AOT but can see as you indicated. the options you listed above might be getting too late now. I think keeping it unsafe with the recommended message to use the generic API might be the best option :-( |
The biggest issue is that the generic overload wasn't there in .Net Standard 2.0, so a lot of libraries targetting that use the type one. As such, having it work properly would be really useful. Personally I've always copied the data to properly typed arrays, but I've seen samples that just cast the arrays to the enum array type. |
If we cannot fix the existing API, can we introduce a new one? I am thinking Libraries that target NS2.0 would be able to use this API using reflection light-up and still be AOT compatible. It is not the case with the generic overload. Calling the generic overload via reflection requires MakeGenericMethod that comes with the same AOT problem. |
|
Another option that does not require new APIs and that is compatible with NS2.0: Enumerate the enum members as field info. It comes with performance penalty.
|
Can we make the NativeAOT compiler recognize |
The AOT compiler does that today: runtime/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs Lines 549 to 571 in 5fc5c68
The problem is what to do with runtime/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs Line 174 in 215b39a
|
Thanks for the data Stephen! The data binding scenario is very likely the reason why .NET Native backtracked on this too (nobody could remember why we backtracked there, only that we backtracked). I've submitted an API proposal for the API Jan proposed here: #72498. I marked it blocking. If we can get it approved soon, I think it would be reasonable to land before RC 1 snaps off. |
The next step is to get #72498 API approved. This PR can be closed. |
...at the cost of a small compat break. We return
int[]
instead ofSomeInt32Enum[]
.Fixes #72140.
We can also delete intrinsic handling of
Enum.GetValues
in dataflow analysis but I don't want to conflict with Vitek's #71485 right now.Cc @dotnet/ilc-contrib