fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
345 stars 21 forks source link

Deprecate `outref` returns #1296

Open jwosty opened 1 year ago

jwosty commented 1 year ago

Currently, it's possible to write a function which returns an outref<'a>. I propose we deprecate that construct, emitting a new warning whenever it is encountered.

For example:

type SomeType<'a>(value) =
    let mutable _value = value
    member this.GetValue () : outref<'a> = &_value

This is nonsensical and the compiler shouldn't have allowed stuff like this in the first place. I would argue that it's really a compiler bug, but I'm filing this as a language suggestion because removing it would technically be a breaking change. Deprecating it would be a step towards making it a compile error in the future.

It seems to compile the same as byref<'a>. I seriously doubt that's in a real codebase, but if it is, users just be able to use that instead: https://sharplab.io/#v2:DYLgZgzgNALiCWwoBMQGoA+BbA9sgrsAKYAEAsgIbwB2AsAFAMwCeADqQMo5ZEAqbRADwByCgD4AFADcKwfEQCUJALwMS6ksRgks+GBQBGxEgH0Zc0spLn5ajTywGiAJxIwAFvAgA6AELNnIjAAJSIYfGdqCSUQEgMAoJFxFRIAMjNZW3oNHSJHFzdPHwBJakCQsIiomJIacqSxFPSbIjt1BydXDy9vAHk9ctDwyOiSWJwBxNFGq2bM1vogA

It's also worth noting that there's also no C# equivalent.

Pros and Cons

Pros:

Cons:

Extra information

Estimated cost (XS, S, M, L, XL, XXL):

Related suggestions: (put links to related suggestions here)

Affidavit (please submit!)

Please tick this by placing a cross in the box:

Please tick all that apply:

For Readers

If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

cartermp commented 1 year ago

This may have be considered by design. Semantically, outrefs are no different from byrefs, and you can do byref returns.

jwosty commented 1 year ago

This is true, but I couldn't find anything on outref returns in the docs nor the relevant RFCs (see here especially - the RFC doesn't say you can return outrefs - https://github.com/fsharp/fslang-design/blob/main/FSharp-4.5/FS-1053-span.md)

I could see how this may have happened - when byref returns were originally added (https://github.com/fsharp/fslang-design/blob/main/FSharp-4.1/FS-1020-byref-returns.md), there was no inref and outref. When those were added (to enable Span support) (https://github.com/fsharp/fslang-design/blob/main/FSharp-4.5/FS-1053-span.md), they were implemented as if they are subtypes of byref. I can definitely see how this corner case could have gotten missed.

cartermp commented 1 year ago

Right, but by being semantically equivalent to a byref, they're supported as returns. I think this is something that can be reconsidered, but I don't think this was an oversight.

jwosty commented 1 year ago

Right, but by being semantically equivalent to a byref, they're supported as returns. I think this is something that can be reconsidered, but I don't think this was an oversight.

This makes me curious actually - what's the rational behind having both, if F# doesn't really treat them differently? I understand why for C# (which does enforce additional out rules).