-
Notifications
You must be signed in to change notification settings - Fork 803
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
Can't pass byref return along until 15.7.20180719.1 #5366
Comments
@lostmsu Sorry, I think I'm a bit confused by the report. Are you looking to consume a byref return or produce one? Producing a byref return is not supported in F# 4.1 (as specified in the RFC). If you are attempting to use F# 4.5 which expands support in this space, the compiler you get from the nightly feed may not contain all of what you need. I suggest waiting until VS 15.8 Preview 5, where a fully-assembled F# 4.5 will be shipped. However, based on the error message, it seems like you're attempting to return a value from its own frame. Byrefs cannot escape the scope in which they are declared (this is also true in C#). |
@lostmsu You can return byrefs as type IPool<'T when 'T: struct> =
abstract member GetReference : byref<'T> -> unit let mutable r = Unchecked.defaultof<'T>
pool.GetReference(&r) Alternatively if you want to pass pointers around why not pass native pointers |
@cartermp The code, that I am trying to compile is right there in the report. I want to make a F#-style wrapper for an ordinary array/span-like interface (the @zpodlovics Defining and implementing the interface is not the problem, the problem appears in the definition of |
@lostmsu This could get tricky. Any ByRefLike type (such as Span) is extremely restrictive in its use. You cannot store them in anything other than an additional ByRefLike struct, for example. That is, something like this: type C(s: ReadOnlySpan<string>) =
member this.SpanFoo : ReadOnlySpan<string>= s Is disallowed because it would violate rules in the runtime. Your wrapper type must also be a struct that is decorated with |
@cartermp but I don't have an explicitly declared wrapper type 🤔 |
Small repro: This definition will work: type IPool<'T> =
abstract member GetReference: int -> byref<'T>
let Ref (pool: IPool<_>) = pool.GetReference 0 This definition will not work: type IPool<'T> =
abstract member GetReference: int -> byref<'T>
let Ref<'T,'TPool when 'TPool :> IPool<'T>>(pool: 'TPool) = pool.GetReference 0
It produces the same error when 'T constrained to reference types: type IPool<'T when 'T: not struct> =
abstract member GetReference: int -> byref<'T> |
@zpodlovics , thanks, that solves my immediate problem. |
These definition will also works: type IPool<'T when 'T: unmanaged> =
abstract member GetPtr : int -> nativeptr<'T>
let Ref (pool: #IPool<_>) = pool.GetPtr 0
let Ref< 'T,'TPool when 'TPool :> IPool< 'T>>(pool: 'TPool) = pool.GetPtr 0 These definition will also fails: type IPool<'T> =
abstract member GetReference: int -> byref<'T>
let Ref (pool: #IPool<_>) = pool.GetReference 0 Somehow the generic specialization will fail when combined with byref return types. |
@lostmsu , based on your example, it should work in preview 5; I just tested this myself. type IPool<'P, 'T when 'T: struct> =
abstract member GetReference: unit -> byref<int>
let GetRef<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) =
&pool.GetReference()
let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) = pool.GetReference However, your example here: let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) = pool.GetReference may have found some interesting things in regards to partial application on member methods for byrefs. They create different signatures than if they were let-bound functions. For the example above, the signature is: Now, we don't support calling a partially applied function that takes a byref, but it might be something we could allow in the future. |
Closing as fixed. |
This seems to be a regression. It was supported at some point, because this code exists, that no longer compiles in VS |
Ah OK, it's because of the forward pipe #5286 (comment) |
I get
error FS3209: The address of the variable 'copyOfStruct' cannot be used at this point. A method or function may not return the address of this local value.
when trying to wrap a function, that returns a byref on the latest preview build. In fact, the error is the same as in the release.Repro steps
Here's the code sample, that produces the error:
Also, can't define
Ref
asdue to a different
byref
errorExpected behavior
can pass byref return up
Actual behavior
can't pass byref return due to the error above
Known workarounds
Reducing generalization helps, as discovered below
Related information
Visual F# preview build 15.7.20180719.1 from https://dotnet.myget.org/F/fsharp/vsix
But also reproduces on the latest retail build (the one shipping with VS 15.7.5).
Scenario
See StackOverflow post https://stackoverflow.com/questions/51033055/byref-return-in-f-4-5
The text was updated successfully, but these errors were encountered: