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

Special-case raising an exception with byrefs

Open cartermp opened this issue 5 years ago • 3 comments

Tracking as per here: https://github.com/dotnet/fsharp/issues/5776

We should allow raising exceptions in byref-returning functions and methods, like this:


type Ii<'T> =
    abstract GetSpan : int -> ReadOnlySpan<'T>

[<Struct>]
type X(value : int) =
    interface Ii<int> with
        member _.GetSpan n = ReadOnlySpan()

[<Struct>]
type Y(value : int) =
    interface Ii<int> with
        member _.GetSpan n = failwith "Nope"

The existing way of approaching this problem in F# is to insert a dummy return value to satisfy the F# compiler:

[<Struct>]
type Y(value : int) =
    interface Ii<int> with
        member _.GetSpan n = failwith "Nope"; ReadOnlySpan()

The reason why this doesn't work is that the way you raise exceptions in F# is through the raise function, which returns a generic value. Same goes for the other helpers:

  • failwith
  • invalidArg
  • nullArg
  • invalidOp
  • reraise
  • rethrow
  • failwithf

~~Note that @dsyme is not in favor of special casing anything other than raise. I personally think all other than failwithf should be allowed, though that may be worth considering.~~

Pros and Cons

The advantages of making this adjustment to F# are:

  • Allowing a fairly common pattern, since exceptions are normal in .NET

The disadvantages of making this adjustment to F# are:

  • More special rules for byref and byref-like types

Extra information

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

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

cartermp avatar May 26 '20 18:05 cartermp

Marking approved. I guess I don't really mind how many of those are special-cased.

dsyme avatar May 28 '20 23:05 dsyme

Would this be extended to inline functions that raise an error unconditionally? It would make it possible to define custom error functions such as the following:

let inline notPositive name = raise (ArgumentOutOfRangeException(name, name + " must be greater than zero!"))

Naharie avatar May 04 '21 20:05 Naharie

Never mind. I just realized #688 already addresses the issue.

Naharie avatar May 04 '21 20:05 Naharie