Open mvikto opened 3 years ago
I don't think this has to do with the conversion, but to do with the pretty-printing call with printfn
. Same happens if it's %O
for ToString(). Note that if you swap out for Console.WriteLine, you'll see a more helpful message:
Unhandled exception. System.InvalidOperationException: The given type cannot be boxed.
Which makes sense to me, since this is just some unverifiable pointer floating in the program at this point.
Was there a different usage that led to the same runtime exception?
At some point in my code I decided to alias toVoidPtr
with let
like this:
#nowarn "9"
let toVoid = NativeInterop.NativePtr.toVoidPtr
[<EntryPoint>]
let main argv =
let numbers = [| 1..10 |]
use v = fixed numbers
let v' = toVoid v
0
If you call toVoid
you'll get the same cryptic message, but if you do:
#nowarn "9"
let toVoid x = NativeInterop.NativePtr.toVoidPtr x
[<EntryPoint>]
let main argv =
let numbers = [| 1..10 |]
use v = fixed numbers
let v' = toVoid v
0
Then it works. Why is it like that?
So this is ultimately by design, even if it's a little tricky. You can notice the difference in these two decompilations:
The first example needs to box a void pointer, which is a 💥 because that can't get boxed. So I think there's some missing compiler analysis here, since the first example should not compile. It's similar to our analysis for byref<'T>
, where you cannot box it.
@TIHan what are your thoughts?
In regards to the error on this example:
#nowarn "9"
let toVoid = NativeInterop.NativePtr.toVoidPtr
[<EntryPoint>]
let main argv =
let numbers = [| 1..10 |]
use v = fixed numbers
let v' = toVoid v
0
This is by-design and should stay as is. You are partially applying the function which is not allowed if it contains byref or nativeptrs as part of the signature. I don't think it is worth it to add more heuristics to allow partial application with those types of parameters.
Agreed, closing as by-design. Please consider re-opening at fslang-suggestions
Note that I think this should stay open and not be at all a language suggestion. I labeled this as a compile enhancement so that we enhance the analysis, not that we allow this pattern. We currently throw an exception at runtime when we ought to not compile @TIHan @dsyme
Possibly related: https://github.com/dotnet/fsharp/issues/9994 (where, after some back and forth with myself, I found that generics and void*
weren't exactly friends).
Re-opening as this is not about allowing the coding pattern, but about ensuring we have the compiler analysis in place to disallow it
Repro steps
Provide the steps required to reproduce the problem:
open FSharp.NativeInterop
[]
let main argv =
let numbers = [| 1..10 |]
use v = fixed numbers
let v' = NativePtr.toVoidPtr v
printfn "void = %A" v'
0
Unhandled exception. System.TypeLoadException: The generic type 'Microsoft.FSharp.Core.FSharpFunc`2' was used with an invalid instantiation in assembly 'FSharp.Core, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.