Skip to content

Commit bee7e39

Browse files
github-actions[bot]vitek-karasCopilot
authored
[release/10.0] Narrow Mono AOT typeload error cleanup (#129804)
Backport of #129748 to release/10.0 /cc @vitek-karas ## Customer Impact - [x] Customer reported - [ ] Found internally Fixes #129613 Without this fix, some customer apps fail to AOT compile on .NET 10 with an assertion in `inline_method()` followed by `Failed to AOT compile ... exited with code 134`. In the reported case this blocks publishing an iOS app with Mono AOT, while the same scenario worked on .NET 8. ## Regression - [x] Yes - [ ] No This is a regression between .NET 8 and .NET 9 introduced by #91261. ## Testing - `./build.sh mono -os iossimulator -arch arm64 -c Release -rf mono` - validated manually against the customer issue sample / reduced repro by replaying the exact failing AOT compiler command and confirming the fixed compiler succeeds where the regressed compiler asserts in `inline_method()` - added a direct Mono mini regression in `src/mono/mono/mini/iltests.il` - local regression validation: - `mono iltests.exe --run-only missing_field_then_inline` - `mono --aot=full,static iltests.exe` ## Risk Low. This is a targeted fix in Mono AOT compiler error handling plus a focused regression test. The change modifies a path which always fails to correctly handle the missing field reference and allow the application to compile (the error is then reported at runtime when the affected code path executes). **IMPORTANT**: If this backport is for a servicing release, please verify that: - For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`, not `release/X.0`. - For .NET 10+: The PR target branch is `release/X.0` (no `-staging` suffix). ## Package authoring no longer needed in .NET 9 **IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version. Keep in mind that we still need package authoring in .NET 8 and older versions. --------- Co-authored-by: vitek-karas <10670590+vitek-karas@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ab591ee commit bee7e39

2 files changed

Lines changed: 58 additions & 3 deletions

File tree

src/mono/mono/mini/iltests.il

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,56 @@ L_3:
32243224
IL_000c: ret
32253225
}
32263226

3227+
.class nested private auto ansi beforefieldinit MissingFieldCarrier`1<T>
3228+
extends [mscorlib]System.Object
3229+
{
3230+
.method public hidebysig specialname rtspecialname instance default void .ctor () cil managed
3231+
{
3232+
.maxstack 8
3233+
ldarg.0
3234+
call instance void object::.ctor()
3235+
ret
3236+
}
3237+
}
3238+
3239+
// After lowering the missing-field access into a runtime throw, AOT must also
3240+
// consume the recoverable metadata error so the later accepted inline does not
3241+
// trip inline_method()'s cfg->error assert.
3242+
.method private hidebysig static void missing_field_then_inline<T> () cil managed
3243+
{
3244+
.maxstack 8
3245+
ldnull
3246+
ldfld !0 class Tests/MissingFieldCarrier`1<!!0>::missing
3247+
pop
3248+
ldc.i4.2
3249+
call int32 Tests::always_inline(int32)
3250+
pop
3251+
ret
3252+
}
3253+
3254+
.method public hidebysig static int32 test_0_missing_field_then_inline () cil managed
3255+
{
3256+
.maxstack 8
3257+
.locals init (int32 V_0)
3258+
.try
3259+
{
3260+
call void class Tests::missing_field_then_inline<string> ()
3261+
ldc.i4.1
3262+
stloc.0
3263+
leave.s IL_0011
3264+
}
3265+
catch [mscorlib]System.MissingFieldException
3266+
{
3267+
pop
3268+
ldc.i4.0
3269+
stloc.0
3270+
leave.s IL_0011
3271+
}
3272+
3273+
IL_0011: ldloc.0
3274+
ret
3275+
}
3276+
32273277
.method public hidebysig static int32 test_104_conv_u_and_string() cil managed
32283278
{
32293279
.maxstack 8

src/mono/mono/mini/method-to-ir.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10167,9 +10167,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
1016710167
if (!field || CLASS_HAS_FAILURE (klass)) {
1016810168
HANDLE_TYPELOAD_ERROR (cfg, klass);
1016910169

10170-
// Reached only in AOT. Cannot turn a token into a class. We silence the compilation error
10171-
// and generate a runtime exception.
10172-
if (cfg->error->error_code == MONO_ERROR_BAD_IMAGE)
10170+
/*
10171+
* Reached only in AOT. After lowering the field resolution failure into a runtime
10172+
* throw, consume the expected recoverable metadata errors as well. Memberref field
10173+
* resolution can report MissingField/BadImage directly through cfg->error without
10174+
* setting cfg->exception_type, and leaving one of those live lets an accepted inline
10175+
* trip the inline_method () cfg->error assert later on.
10176+
*/
10177+
if (cfg->error->error_code == MONO_ERROR_BAD_IMAGE || cfg->error->error_code == MONO_ERROR_MISSING_FIELD)
1017310178
clear_cfg_error (cfg);
1017410179

1017510180
// We need to push a dummy value onto the stack, respecting the intended type.

0 commit comments

Comments
 (0)