Closed abelbraaksma closed 2 years ago
I think in general we would like to avoid appending to the list of things you can only reasonably do in FSharp.Core. I'd like @dsyme's perspective on this, though.
you can only reasonably do in FSharp.Core
Just to make sure: I meant this feature to be added and stay within Core, I don't mean to make the compiler specific optimization syntax available outside it.
(and probably only if it's relatively trivial to add, so we can improve optimizations, otherwise it's likely not worth the effort)
@cartermp This may be worth doing in order to handle ambiguities of enums and int-types when doing static optimizations in FSharp.Core. @abelbraaksma and I just walked through his string
PR: https://github.com/dotnet/fsharp/pull/9549, that is getting rid of a lot of the boxing except for int-types because they need to be handled using IFormattable
.
Even though this is internal to FSharp.Core, this may warrant a RFC because any additional constraints added to static optimizations will have to be added to the TypedTreePickle. This means it is public and the compiler understands it; you just can't write one in your own library code.
Makes sense!
From a brief look at how static optimizations work, it should be fairly straight forward to add.
I've the intention to work on optimizations for some of the array functions. If we consider adding enum
here, we might want to consider when 'T: unmanaged
as well. There's currently no way to test for a struct that has no reference types, and recently the runtime added optimizations specifically for that case (optimizations that only work with blittable types). Without unmanaged
such optimizations are bound to be restricted to the integral types, plus bool, decimal, float and float32.
@TIHan I believe this would mostly require additions to the TypedTree format, which would rule out using them in FSHarp.Core
@dsyme, are we talking about the same things here? This is an additive suggestion for static optimization syntax, which currently is only allowed in FSharp.Core.
I'm ok to implement it if someone guides me where current version is implemented.
SR when syntax on interfaces would also enable perf gain in comparison operators which currently are slow with IComparable
@thinkbeforecoding great if you want to take a look at this! It's been a while that I looked at this, but this is related to a certain syntax for when
that gets statically compiled if and only if the thing being compiled is FSharp.Core
. In other words, this is syntax that allows making optimizations to functions in FSharp.Core that are otherwise impossible. When the compiler encounters such "static when" clauses (can be either when 'T
or when ^T
syntax iirc), it will compile that function as an inline
function for only that when-path (i.e. when the function is called from user code), which allows great optimizations.
I looked into this at the time and I don't think it was terribly hard, but I do recall it was buried pretty deep in the compiler optimization code. But @dsyme may be more suited in pointing you to the right direction ;).
@dsyme could you give me some pointers to files/functions that handle this?
I would start with WhenTyparIsStruct
and add WhenTyparIsEnum
and continue from there
https://github.com/dotnet/fsharp/blob/main/src/Compiler/SyntaxTree/SyntaxTree.fsi#L988
I'll actually close this issue however, as it needs a suggestion and RFC. Please add one?
To actually use this in FSharp.Core is tricky as old compilers must consume new FSHarp.Core. If we could somehow find a backwards compat way of accpeting the constructs then we could probably add this sort of thing. That would probably mean immediately adding a clause in TypedTreePickle.fs that ignores static optimization instructions it doesn't recognise, assuming they are from the future. That would set us up to be backwards compat eventually. Not sure there's any other way to do it that doesn't involve a lot of engineering
Is your feature request related to a problem? Please describe. By trying to remove boxing for the
string
function, I got blocked by the fact that I cannot special-case enums. In fact, the staticwhen
syntax is quite limited, and probably rightly so, but I would like to see if it is possible to extend this with support forenum<_>
, so that we can distinguish between enums and integral types.Describe the solution you'd like I'd like to allow syntax like:
Alternatively, we can use
enum
without type spec. But I figured, since normal generic type restrictions are possible withenum<'T>
where'T
is an integral type, this may be easier to add to the language.Like with the normal enum type restriction, after the equals-sign,
x
has type annotationrequires enum
.Describe alternatives you've considered I don't think there's an alternative that allows different code paths to be statically resolved for integral types (that are not enum) and enums (of an integral type).
Additional context This restriction was discussed at some length in https://github.com/dotnet/fsharp/pull/9549. If there's another workaround, I'll gladly take it ;). Since this is an "internal to the compiler only" request, I don't think it ought to go through the language-suggestions, but I've no problem to re-post there ;).
I looked around in the compiler code where this static
when
clause was resolved, but failed to find it (it's not easy to search for "when", it's omnipresent).I think the only "special" type allowed is
struct
. Others, that are allowed in generics and SRTP, likenot struct
,enum<_>
,delegate<_, _>
are not available in this context.Benefit of implementing this would be that we can write more targeted IL code for FSharp.Core functions. But whether it is worth the effort if the only case is to prevent boxing for
string
remains to be seen.