Description
[FeatureGuard(typeof(RequiresDynamicCodeAttribute))] + [FeatureSwitchDefinition] on a feature switch property correctly suppresses IL3050 warnings on all NativeAOT platforms except Android. The regression appeared between SDK builds 26166.111 and 26203.107.
Bisect
| SDK |
dotnet/runtime SHA |
Android AOT |
11.0.100-preview.3.26166.111 |
c38f37a3a1c3 |
✅ No IL3050 |
11.0.100-preview.3.26203.107 |
d23e53a91dcd |
❌ IL3050 emitted |
No MAUI code changed between these builds — only the SDK version bump (dotnet/maui#34852).
Root Cause: PR #124801
"Decouple ILC from ManagedAssemblyToLink" (15da4216aef1) landed between these two runtime SHAs. This PR:
- Removed
_ComputeManagedAssemblyForILLink from Microsoft.NETCore.Native.targets
- Changed
@(ManagedAssemblyToLink) construction from @(ManagedBinary) to @(IntermediateAssembly)
- Was specifically made for Android NativeAOT where
RunILLink=true
The Android SDK (36.99.0-preview.3.10) already has a partial workaround referencing this PR (clearing _IlcManagedInputAssemblies), confirming it disrupted the Android NativeAOT pipeline. The IL3050 regression appears to be a residual effect.
Why Android-Only
| Platform |
RunILLink |
Feature switch processing |
| iOS/macCatalyst/macOS |
false |
ILC is the sole trimmer — applies --feature substitution directly ✅ |
| Android |
true |
ILLink runs first, then ILC gets linked output. PR #124801 changed this flow ❌ |
On non-Android platforms, ILC reads all original assemblies and applies feature switches internally via --feature:Microsoft.Maui.RuntimeFeature.IsHybridWebViewSupported=false. This works correctly.
On Android (RunILLink=true), the decoupling in PR #124801 appears to have disrupted how RuntimeHostConfigurationOption items flow to ILC's --feature arguments, or ILC is now receiving a mix of linked/unlinked assemblies where the feature switch hasn't been substituted.
Reproduction
In dotnet/maui, RuntimeFeature.IsHybridWebViewSupported is configured with:
[FeatureSwitchDefinition] + [FeatureGuard(typeof(RequiresDynamicCodeAttribute))]
- MSBuild:
MauiHybridWebViewSupported=false when PublishAot=true, mapped to RuntimeHostConfigurationOption with Trim="true"
The guarded call site:
if (RuntimeFeature.IsHybridWebViewSupported)
{
AddHybridWebViewHandler(handlersCollection); // [RequiresDynamicCode]
}
dotnet publish -r osx-arm64 -p:PublishAot=true → no IL3050 ✅
dotnet publish -r android-arm64 -p:PublishAot=true → IL3050 emitted ❌
Suggested Investigation
A binlog comparison between the two SDK versions would confirm the exact failure point:
- Are
--feature: flags present for IsHybridWebViewSupported in ILC's command line on Android?
- Does
@(ManagedAssemblyToLink) contain linked or unlinked Microsoft.Maui assemblies when ILC runs?
- Did the
_IlcManagedInputAssemblies clearing workaround in the Android SDK affect ILC's analysis scope?
MAUI Workaround
Applied [UnconditionalSuppressMessage] on the helper method (dotnet/maui#34986), matching the pattern used by ServiceProvider in dotnet/runtime per dotnet/linker#2715.
Context
cc @AustinWise @sbomer @simonrozsival
Description
[FeatureGuard(typeof(RequiresDynamicCodeAttribute))]+[FeatureSwitchDefinition]on a feature switch property correctly suppresses IL3050 warnings on all NativeAOT platforms except Android. The regression appeared between SDK builds26166.111and26203.107.Bisect
11.0.100-preview.3.26166.111c38f37a3a1c311.0.100-preview.3.26203.107d23e53a91dcdNo MAUI code changed between these builds — only the SDK version bump (dotnet/maui#34852).
Root Cause: PR #124801
"Decouple ILC from ManagedAssemblyToLink" (
15da4216aef1) landed between these two runtime SHAs. This PR:_ComputeManagedAssemblyForILLinkfromMicrosoft.NETCore.Native.targets@(ManagedAssemblyToLink)construction from@(ManagedBinary)to@(IntermediateAssembly)RunILLink=trueThe Android SDK (
36.99.0-preview.3.10) already has a partial workaround referencing this PR (clearing_IlcManagedInputAssemblies), confirming it disrupted the Android NativeAOT pipeline. The IL3050 regression appears to be a residual effect.Why Android-Only
RunILLinkfalse--featuresubstitution directly ✅trueOn non-Android platforms, ILC reads all original assemblies and applies feature switches internally via
--feature:Microsoft.Maui.RuntimeFeature.IsHybridWebViewSupported=false. This works correctly.On Android (
RunILLink=true), the decoupling in PR #124801 appears to have disrupted howRuntimeHostConfigurationOptionitems flow to ILC's--featurearguments, or ILC is now receiving a mix of linked/unlinked assemblies where the feature switch hasn't been substituted.Reproduction
In dotnet/maui,
RuntimeFeature.IsHybridWebViewSupportedis configured with:[FeatureSwitchDefinition]+[FeatureGuard(typeof(RequiresDynamicCodeAttribute))]MauiHybridWebViewSupported=falsewhenPublishAot=true, mapped toRuntimeHostConfigurationOptionwithTrim="true"The guarded call site:
dotnet publish -r osx-arm64 -p:PublishAot=true→ no IL3050 ✅dotnet publish -r android-arm64 -p:PublishAot=true→ IL3050 emitted ❌Suggested Investigation
A binlog comparison between the two SDK versions would confirm the exact failure point:
--feature:flags present forIsHybridWebViewSupportedin ILC's command line on Android?@(ManagedAssemblyToLink)contain linked or unlinked Microsoft.Maui assemblies when ILC runs?_IlcManagedInputAssembliesclearing workaround in the Android SDK affect ILC's analysis scope?MAUI Workaround
Applied
[UnconditionalSuppressMessage]on the helper method (dotnet/maui#34986), matching the pattern used byServiceProviderin dotnet/runtime per dotnet/linker#2715.Context
[UnconditionalSuppressMessage]workaroundcc @AustinWise @sbomer @simonrozsival