Closed neon-sunset closed 1 month ago
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.
As a workaround you can use generic wrapper for the accessor (not sure what changed in .NET 9 to require that):
using System.Runtime.CompilerServices;
using Google.Protobuf.Collections;
var repeatedField = new RepeatedField<float> { 1.0f, 2.0f, 3.0f };
Console.WriteLine(MyAccessor<float>.ArrayRef(repeatedField).Length); // 8
public class MyAccessor<T>
{
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "array")]
public static extern ref T[] ArrayRef(RepeatedField<T> instance);
}
Thanks, this works the other way around - on 9 but not on 8 (which does not support unsafe accessor generics), so I'm kind of back to square one 😀
I have simplified the example - does not need Protobuf dependency to repro.
cc @AaronRobinsonMSFT
Tagging subscribers to this area: @dotnet/area-system-runtime-compilerservices See info in area-owners.md if you want to be subscribed.
Thanks, this works the other way around - on 9 but not on 8 (which does not support unsafe accessor generics), so I'm kind of back to square one 😀
I have simplified the example - does not need Protobuf dependency to repro.
@neon-sunset The solution here is to use an accessor class, as suggested in https://github.com/dotnet/runtime/issues/108046#issuecomment-2362520815. The UnsafeAccessorAttribute
wasn't supposed to support generics in .NET 8. Unfortunately it did and enabled users to perform actions that weren't expected or properly spec'd. This was filed as a break-change in .NET 9, eventhough using generics in .NET 8 wasn't supported. See https://github.com/dotnet/docs/issues/41769.
The documentation for UnsafeAccessorAttribute
has additional details that are also relevant.
Thanks. This is fair, the only question is the discrepancy with NativeAOT 9.0 where it does continue to work.
Thanks. This is fair, the only question is the discrepancy with NativeAOT 9.0 where it does continue to work.
Yes, sadly native AOT has a very different Type System API and in this case was written "properly" in .NET 8.0. Since native AOT must be computed at compile time it is much easier to reason about. The check at run-time in CoreCLR was a bit harder and took me longer to wrap my head around "how" to make it work. The lack of support in .NET 8.0 was simply me not having the knowledge to make it work in the timeframe.
I see, thank you for the explanation. In this case I ended up unintentionally relying on undocumented behavior where the unsafe accessor for RepeatedField<float>
works in .NET 8 but no longer does in .NET 9. Its use will be removed for 8 altogether, and a working solution for 9 will be provided in net9.0-specific package instead, but it's not ideal (well, protobuf abstractions are not exactly great in general, to the point of System.Text.Json being more performance-friendly, but that's another topic).
Description
It appears that
UnsafeAccessor
may not be working on .NET 9 as expected with JIT configuration, but continues to work with NativeAOT.Reproduction Steps
Given simple program created from a default console template:
Expected behavior
Actual behavior
Regression?
Yes
Known Workarounds
Using reflection 😢
Configuration
but did also reproduce with RC.1
Other information
No response