fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Deprecate `outref` returns

Open jwosty opened this issue 2 years ago • 4 comments

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:

  • Helps prevent / fix up code that should never have been written in the first place

Cons:

  • Opens the door for a breaking change

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:

  • [x] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • [x] This is not a breaking change to the F# language design
  • [x] I or my company would be willing to help implement and/or test this

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.

jwosty avatar Jul 28 '23 16:07 jwosty

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

cartermp avatar Jul 29 '23 17:07 cartermp

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.

jwosty avatar Jul 29 '23 17:07 jwosty

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.

cartermp avatar Jul 29 '23 17:07 cartermp

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).

jwosty avatar Jul 31 '23 16:07 jwosty