[mono][AOT] gsharedvt method calling INumberBase<T>.TryParse fails in aot-only mode

Đang mở
#137,120 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
38/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
csharp

Hướng nghiên cứu

Start by tracing Mono full AOT generic sharing for the constrained INumber<T>.TryParse call in BareHolder<T>.Set; the report points to mini-generic-sharing.c and mini_instantiate_gshared_info. Reproduce with the provided iOS AOT setup, comparing the reflection-created closed type with direct construction and interpreter mode. Done when the generic value type parses successfully in AOT-only mode without JIT compilation.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

area-Codegen-AOT-mono untriaged
Description

With Mono full AOT on iOS (UseInterpreter=false), a method on a generic type over a value type that calls T.TryParse(string, NumberStyles, IFormatProvider, out T) fails if the AOT compiler never saw the closed type and it has to run as gsharedvt code. The same method works when the closed type is constructed directly, and with the interpreter.

This came from MudBlazor's slider crashing MAUI Blazor Hybrid apps on iPhone (https://github.com/MudBlazor/MudBlazor/issues/14134). Blazor creates components from a Type and names MudSlider<int> only as a type argument, so the slider always runs as gsharedvt code.

Reproduction Steps

A class library (built with Optimize=true):

using System.Globalization;
using System.Numerics;

public abstract class BareBase
{
    public abstract bool Set(string text);
    public abstract string Text { get; }
}

public sealed class BareHolder<T> : BareBase where T : struct, INumber<T>
{
    private T _value;

    public override string Text => _value.ToString(null, CultureInfo.InvariantCulture);

    public override bool Set(string text)
    {
        if (!T.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
        {
            return false;
        }

        _value = result;
        return true;
    }
}

public static class BareFactory
{
    public static BareBase Create<THolder>() where THolder : BareBase => (BareBase)Activator.CreateInstance(typeof(THolder))!;
}

Called from an iOS app (net10.0-ios, UseInterpreter=false, MtouchLink=SdkOnly):

BareFactory.Create<BareHolder<long>>().Set("181"); // throws
new BareHolder<short>().Set("181");               // works
Expected behavior

Set parses the value, as it does with the interpreter or when the closed type is constructed directly.

Actual behavior
System.ExecutionEngineException: Attempting to JIT compile method 'bool Issue14134.BareHolder`1<long>:Set (string)' while running in aot-only mode.

When the call is inside an async method, the runtime aborts instead:

* Assertion at src/mono/mono/mini/mini-generic-sharing.c:2761, condition `is_ok (error)' not met, function:mini_instantiate_gshared_info, Attempting to JIT compile method 'void Issue14134.SvmAsyncHolder`1/<SetValueTextAsync>d__5<long>:MoveNext ()' while running in aot-only mode.

The reporter's physical iPhone build asserted iface_offset != -1 in mini-generic-sharing.c instead.

Regression?

Unknown.

Known Workarounds
  • Construct the closed type where the AOT compiler sees it, for example new BareHolder<long>() in a method that never runs.
  • Avoid T.TryParse: double.TryParse or decimal.TryParse followed by T.CreateSaturating works in the same gsharedvt context, as do T.Zero, T.One and T.CreateTruncating. MudBlazor does this in https://github.com/MudBlazor/MudBlazor/pull/14136.

Moving T.TryParse into a separate generic method doesn't help. The gsharedvt caller resolves that method on entry and Mono tries to JIT it, even when the call isn't reached.

Configuration

.NET SDK 10.0.403, runtime 10.0.14 (10.0.13 too), iOS workload 27.1.10018, Xcode 27.1, iOS 27.1 arm64 simulator, Debug and Release.

Other information

Possibly related: https://github.com/dotnet/runtime/issues/118697

Ngôn ngữ chính
C#
Star
18.4k
Fork
5.8k
Merge trung bình
2 ngày 12 giờ
Pull request đã merge (30 ngày)
581

Chuẩn bị môi trường

Mở trong Codespaces

Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của dotnet/runtime

Tất cả issue của dotnet/runtime

Issue tương tự

Thêm issue về C#

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.