-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AOT fails on mono-ios with "Method has zero rva" in PolyType-generated methods #73
Comments
dotnet/runtime#91066 (comment) My app is targeting .NET 8. Given the comment that arm64 would only be fixed in .NET 9, I'll try retargeting. |
Unfortunately once I target .NET 9, the SDK requires me to use Xcode 16.1, but then I hit a new bug: I hate iOS development. |
Judging by the error message it's crashing because of the unsafe accessors correct? In ns2.0 the source generator replaces those with regular reflection, would it make sense to have a setting that defaults back to reflection everywhere? Alternatively, updating the accessibility modifiers to at least be internal is one potential workaround. |
I don't think so. At least not at this point. Because what you propose would influence source generation, so it would have to be done in every consuming project manually. Or you could do it automatically when the project targets |
Here's the odd thing though: Yes, there are unsafe accessors, but no they aren't required. This is what the source generator produces: [global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_TickerSymbol")]
private static extern void __SetAccessor_Security_TickerSymbol(global::Nerdbank.Cryptocurrencies.Security obj, string value);
[global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_Name")]
private static extern void __SetAccessor_Security_Name(global::Nerdbank.Cryptocurrencies.Security obj, string value);
[global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_Precision")]
private static extern void __SetAccessor_Security_Precision(global::Nerdbank.Cryptocurrencies.Security obj, int value);
[global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_IsTestNet")]
private static extern void __SetAccessor_Security_IsTestNet(global::Nerdbank.Cryptocurrencies.Security obj, bool value); But these unsafe accessors are not called. And in fact there is no need for them to be, because the members they provide access to are settable through a primary constructor public record Security(string TickerSymbol, string? Name = null, int Precision = 8, bool IsTestNet = false) So there doesn't appear to be any way for me to remove the unsafe accessors from being generated, and it seems a bug that the source generator is producing them in the first place. The constructor parameter is detected and source generated for: new global::PolyType.SourceGenModel.SourceGenConstructorParameterShape<(string, string, int, bool), bool>
{
Position = 3,
Name = "IsTestNet",
ParameterType = Boolean,
Kind = global::PolyType.Abstractions.ConstructorParameterKind.ConstructorParameter,
IsRequired = false,
IsNonNullable = true,
IsPublic = true,
HasDefaultValue = true,
DefaultValue = false,
Setter = static (ref (string, string, int, bool) state, bool value) => state.Item4 = value,
AttributeProviderFunc = static () => typeof(global::Nerdbank.Cryptocurrencies.Security).GetConstructor(__BindingFlags_Instance_All, new[] { typeof(string), typeof(string), typeof(int), typeof(bool) })?.GetParameters()[3],
}, And of course the property getter is accessible via this source-generated shape: new global::PolyType.SourceGenModel.SourceGenPropertyShape<global::Nerdbank.Cryptocurrencies.Security, bool>
{
Name = "IsTestNet",
DeclaringType = (global::PolyType.Abstractions.IObjectTypeShape<global::Nerdbank.Cryptocurrencies.Security>)Security,
PropertyType = Boolean,
Getter = static (ref global::Nerdbank.Cryptocurrencies.Security obj) => obj.IsTestNet,
AttributeProviderFunc = static () => typeof(global::Nerdbank.Cryptocurrencies.Security).GetProperty("IsTestNet", __BindingFlags_Instance_All, null, typeof(bool), [], null),
IsField = false,
IsGetterPublic = true,
IsSetterPublic = false,
IsGetterNonNullable = true,
IsSetterNonNullable = false,
}, |
What does the source generated parameterized constructor look like for the type? |
You mean this? private global::PolyType.Abstractions.IConstructorShape __CreateConstructor_Security()
{
return new global::PolyType.SourceGenModel.SourceGenConstructorShape<global::Nerdbank.Cryptocurrencies.Security, (string, string, int, bool)>
{
DeclaringType = (global::PolyType.Abstractions.IObjectTypeShape<global::Nerdbank.Cryptocurrencies.Security>)Security,
ParameterCount = 4,
GetParametersFunc = __CreateConstructorParameters_Security,
ArgumentStateConstructorFunc = static () => (default!, null!, 8, false),
ParameterizedConstructorFunc = static (ref (string, string, int, bool) state) => new global::Nerdbank.Cryptocurrencies.Security(state.Item1, state.Item2!, state.Item3, state.Item4),
AttributeProviderFunc = static () => typeof(global::Nerdbank.Cryptocurrencies.Security).GetConstructor(__BindingFlags_Instance_All, new[] { typeof(string), typeof(string), typeof(int), typeof(bool) }),
IsPublic = true,
};
} |
Yup, just needed to make sure the ctor delegate isn't setting the property itself. Can you share a minimal repro for the type? |
It's as simple as this: [GenerateShape]
public partial record Security(string TickerSymbol); That alone leads to construction of the unsafe accessor. |
Oh wow. I'll take a look. |
What about the last one?
Why is that being generated? That method is defined in .NET. |
I'm also still seeing these UnsafeAccessor members being generated for setters on properties like this: public required ZcashAddress ToAddress { get; init; } |
It doesn't look like a method generated by PolyType, it's a local method in BCL. How is the method being rooted? |
I just tried to consume Nerdbank.MessagePack from an iOS app, and the (mono) AOT compiler failed with the following:
The text was updated successfully, but these errors were encountered: