[NativeAOT] Fix AOT analysis warning IL3050 · Issue #19505 · dotnet/macios (original) (raw)
This issue is a follow-up to #19043
When building apps with NativeAOT, the ILC prints an AOT analysis warning IL3050: ..cctor(): Using member 'System.Enum.GetValues(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling.
The problem is caused by the [DynamicDependency]
attributes we generate in the ApplyPreserveAttributeBase
custom linker step when we're transforming [Preserve(AllMembers = true)]
. There are two cases in which we get this warning:
- the
[Preserve(AllMembers = true)]
is applied to an enum - the class with the attribute contains a nested enum
We transform the attribute by generating a [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(T))]
attribute on the module cctor. This will pull all members of T
, but also all members of its base types. In the case of enums, this unfortunately includes the GetValues(Type)
static method which is annotated with RequiresDynamicCode
.
I see some potential solutions, each of them has a different trade-off:
- Do not preserve nested types
- We change the
DynamicDependency
attribute fromAll
toAll ^ PublicNestedTypes ^ NonPublicNestedTypes
for classes and toPublicFields
for enums. This doesn't seem to be a problem in the xamarin-macios codebase (all tests are passing locally with this change), but it will be a breaking change.
- We change the
- Deprecate
[Preserve]
- We remove all nested enums that cause this problem (
NSObject_Disposer -> NSObject -> Flags, XamarinGCHandleFlags
) and make[Preserve]
attribute obsolete. We would still keep the custom linker steps that transform Preserve into DynamicDependency, but customers won't get this warning unless they have nested enums in their classes. On our end, we would need to remove all uses of[Preserve]
especially in tests (~1200 uses) and in MAUI. The Preserve attributes are baked into bgen-generated binding libraries which could be a problem.
- We remove all nested enums that cause this problem (
- Suppress the warning
- I think it can be argued that nobody expects
Enum.GetValues(Type)
method to be preserved when the[Preserve]
attribute is applied to an enum. We might want to simply suppressIL3050
on the module initializer that we generate. I'm not a fan of this solution since we can't suppress just the warning forGetValues
and we could miss some other warning with the same ID.
- I think it can be argued that nobody expects
What other solutions should we consider?
/cc @rolfbjarne @ivanpovazan @vitek-karas
Steps to Reproduce
- Build the MySingleView test app with NativeAOT:
dotnet publish -f net8.0-ios -r ios-arm64 \
-p:PublishAot=true -p:PublishAotUsingRuntimepack=true \
-p:EnableTrimAnalyzer=true -p:TrimmerSingleWarn=false \
tests/dotnet/MySingleView/
- Inspect warnings
Expected Behavior
There are no build warnings.
Actual Behavior
ILC prints this warning:
ILC : AOT analysis warning IL3050: <Module>..cctor(): Using member 'System.Enum.GetValues(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload or the GetValuesAsUnderlyingType method instead. [/.../xamarin-macios/tests/dotnet/MySingleView/MySingleView.csproj]