Skip to content

[NativeAOT] Fix AOT analysis warning IL3050 #19505

@simonrozsival

Description

@simonrozsival

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 from All to All ^ PublicNestedTypes ^ NonPublicNestedTypes for classes and to PublicFields 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.
  • 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.
  • 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 suppress IL3050 on the module initializer that we generate. I'm not a fan of this solution since we can't suppress just the warning for GetValues and we could miss some other warning with the same ID.

What other solutions should we consider?

/cc @rolfbjarne @ivanpovazan @vitek-karas

Steps to Reproduce

  1. 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/
  1. 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]

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions