-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
UnmanagedCallersOnly functions with ref parameters should be an error #57025
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
@333fred Is it expected that Roslyn allows this? https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/function-pointers.md#systemruntimeinteropservicesunmanagedcallersonlyattribute says that only unmanaged types should be allowed on UnmanagedCallersOnly. |
This works just fine in .NET: class App {
public unsafe static void Main ()
{
delegate* unmanaged<ref int, void> i = &I;
Console.WriteLine ((object) (IntPtr) (void*) i);
}
[UnmanagedCallersOnly]
static void I (ref int fileRegion)
{
}
}
|
It does not work. The UnmanagedCallersOnly signatures are validated lazily by the runtime, once the method is called. Try this:
It fails with |
I would say that since I didn't know |
I think we should just take a bug fix here and make the scenario an error. Anyone depending on this is depending on broken / dangerous behavior. The only case where it can be seemingly used without error is just to print out the address. |
…allersOnly method Fixes dotnet#57025.
I depended on |
Did it work for you at runtime? The runtime should have been failing for this case. |
It is working as expected with NativeAOT. // native code invokes it with a pointer to `struct MyValueType`
[UnmanagedCallersOnly(EntryPoint = "Test")]
static void Test(in MyValueType value)
{
var copiedValue = value;
// copiedValue is exactly what is expected
} In the new version, I have to use unsafe pointer. [UnmanagedCallersOnly(EntryPoint = "Test")]
static unsafe void Test(MyValueType* value)
{
var copiedValue = *value;
}
|
It is a bug / TODO in NativeAOT. |
@wegylexy The design of |
What about |
The pinning that |
Hey, We are discovering this problem at Unity as some of our unit tests are now failing compiling by updating Roslyn. That could be quite a breaking change on our side. Could someone explain exactly why having a ref arg is not considered as blittable as it is considered from the native side as a pure pointer and from managed side, it is still a pointer in a register? Behind the scene for the pure codegen part, I don't see how the code could be different. So if it is not a codegen problem, what is it? GC tracking ref? Or differently, what is the difference with doing: [System.Runtime.InteropServices.UnmanagedCallersOnly]
static unsafe void ScheduledAudioFileRegionCallback (int* fileRegion)
{
ActualScheduledAudioFileRegionCallback(ref *fileRegion);
}
static void ActualScheduledAudioFileRegionCallback (ref int fileRegion)
{
// ...
} |
@xoofx The issue is one of correctness not necessarily code-gen. The guarantees around |
An exception to the correctness is the return reference of |
That's not really an exception. The use of anything in the |
Thank you, I understand. On our side, the native code is actually C# code that we native compile with our Burst compiler, so it is explicit for the user that if it's declared with a ref, it means that it's not null. But we should be able to workaround if with an IL postprocessing step (we have many others) that will rewrite it to what I described above, so at least we have a workaround, just a bit unfortunate that we have to do that, but I hope it will work on our side. 🙂 |
Description
Test case:
Results in:
Complete test project: blittable-unmanagedattribute-6a124aa.zip
Repro: download & extract & execute
dotnet build
Binlog: msbuild.binlog.zip
I'm guessing it's hitting this:
https://github.com/dotnet/runtime/blob/36229d9d3a5abcf161fbee3a8917dcbdd3070946/src/mono/mono/metadata/marshal.c#L3694-L3697
Note that the C# code is valid, because otherwise the C# compiler should've have compiled it successfully.
Configuration
The text was updated successfully, but these errors were encountered: