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

Lift byref generics restrictions for inline functions #688

Open
NinoFloris opened this Issue Aug 30, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@NinoFloris

NinoFloris commented Aug 30, 2018

Lift byref generics restrictions for inline functions

I propose to lift byref generics restrictions for inline functions.

Since all the new byref things have landed in 4.5 I've been playing quite a bit with Span. It's awesome it all works so well already and correctly prevents you from going off the rails.
It is definitely restrictive and it complicates generic programming a lot. It might especially shock people where they normally don't realize this applies, like piping |> or functions like id. The reason for this is purely a limitation of the CLR and its implementation of generics, it cannot accept a byref type argument, however F# could.

F# already has ways to deal with other generics limitations by marking functions as inline. This effectively removes this function from the runtime's view which allows the language to relax restrictions around generic constraints or limitations.

For instance lifting restrictions on byref for generic functions should allow the following contrived example to pass compilation:

Span<int>.Empty |> id

Both |> and id are generic, but both are also already marked inline today.

Making this change is neatly in line ;) with previous choices for inline to lift generics limitations and it greatly increases ergonomics working with byreflike types and byref arguments.

@TIHan has also quickly checked the feasibility of this and found a place to implement this inside PostInferenceChecks.fs where it can be, in theory, implemented in a way to guarantee correctness.

Pros and Cons

The advantages of making this adjustment to F# are increased language ergonomics and consistency as not being able to use byref in generics is purely a CLR restriction. This is opens up a lot of possibilities to add some sugar on interactions with Span and friends. And it might also help in performance scenarios where passing structs byref is preferred but where generic code is important too or used a lot. In the face of F# dissuading people from doing method overloading it is a good option to have.

The disadvantages of making this adjustment to F# are extra complexity in the compiler. A function marked as inline should, for byref call sites, not contain any calls to other generic functions that aren't marked inline as well.

Extra information

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

Related suggestions: (put links to related suggestions here)

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • 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:

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

This comment has been minimized.

Show comment
Hide comment
@cartermp

cartermp Aug 30, 2018

Member

The advantages of making this adjustment to F# are increased language ergonomics and consistency as not being able to use byref in generics is purely a CLR restriction.

Agreed on this. It's so commonplace to pipe data into another function that it's a guaranteed surprise to first-time users of Span and other byref-like types that they cannot use |>.

Another thing worth calling out is that an error message when applying a byref-like type to a generic function that isn't inline needs to have a descriptive error message (tracked by Microsoft/visualfsharp#5351). Otherwise, people will definitely be confused about why some functions "work" and others don't.

Member

cartermp commented Aug 30, 2018

The advantages of making this adjustment to F# are increased language ergonomics and consistency as not being able to use byref in generics is purely a CLR restriction.

Agreed on this. It's so commonplace to pipe data into another function that it's a guaranteed surprise to first-time users of Span and other byref-like types that they cannot use |>.

Another thing worth calling out is that an error message when applying a byref-like type to a generic function that isn't inline needs to have a descriptive error message (tracked by Microsoft/visualfsharp#5351). Otherwise, people will definitely be confused about why some functions "work" and others don't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment