-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
F# typeof comparison suboptimal codegen #82394
Comments
@vzarytovskii can F# here emit
instead of
? Or otherwise we need to do special handling for |
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue DetailsThe following F# snippet: let test() = typeof<float> = typeof<bool> Emits this IL: ldtoken !!a
call class [netstandard]System.Type [netstandard]System.Type::GetTypeFromHandle(valuetype [netstandard]System.RuntimeTypeHandle)
ldtoken [System.Runtime]System.Boolean
call class [netstandard]System.Type [netstandard]System.Type::GetTypeFromHandle(valuetype [netstandard]System.RuntimeTypeHandle)
tail.
call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/HashCompare::GenericEqualityIntrinsic<class [System.Runtime]System.Type>(!!0, !!0)
ret and this codegen: _.test()
L0000: push rsi
L0001: sub rsp, 0x20
L0005: mov rcx, 0x7ff9f93c77a8
L000f: call 0x00007ffa58e77670
L0014: mov rsi, rax
L0017: mov rcx, 0x7ff9f934b3c0
L0021: call 0x00007ffa58e77670
L0026: mov r8, rax
L0029: mov rdx, rsi
L002c: mov rcx, 0x7ff9febc1e88
L0036: mov rax, 0x7ff9feb43be8
L0040: add rsp, 0x20
L0044: pop rsi
L0045: jmp qword ptr [rax] expected codegen: _.test()
L0000: xor eax, eax
L0002: ret
|
dotnet/fsharp#526 |
By default F# Some relevant discussions (it's a known problem): |
I guess we can generate op_Equality for System.Type (and other known types like DateTime, TimeSpan, UtcDateTime, Range, Guid, etc). |
@vzarytovskii afaik @TIHan mentioned at some point this is not sound due to |
Yeah, and I think we do it in Type Providers ourselves, and yeah, I meant that we can limit it to the |
Type testing at runtime is not needed in F#. |
Is this still the case when (non-collectible) |
Codegen for 8.0 RC 2: ; Program+Program.f()
; typeof<int> = typeof<float>
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^
mov rcx,offset MD_Microsoft.FSharp.Core.LanguagePrimitives+HashCompare.GenericEqualityIntrinsic[[System.Type, System.Private.CoreLib]](System.Type, System.Type)
mov rdx,19080205140
mov r8,19080205898
jmp qword ptr [7FFA6643F9F0]; Microsoft.FSharp.Core.LanguagePrimitives+HashCompare.GenericEqualityIntrinsic[[System.__Canon, System.Private.CoreLib]](System.__Canon, System.__Canon)
; Total bytes of code 36 GenericEqualityIntrinsic is still not inlined. |
Is there any workaround or better way to do this if you have to compare many types? let test myType =
if myType = typeof<bool> then ...
elif myType = typeof<float> then ...
elif myType = typeof<ValueOption<decimal>> then ...
elif ... |
If you open the built-in NonStructuralComparison module, it will locally override the meaning of equals and produce the desired codegen: open NonStructuralComparison
let test() = typeof<float> = typeof<bool> |
I'd introduce an inline function for this, something along the lines of [<AbstractClass; Sealed; AutoOpen>]
type TypeTestsImpl() =
static member inline typetest<'T>(type': Type) =
Type.(=) (type', typeof<'T>)
static member inline typetest<'T, 'U>() =
Type.(=) (typeof<'T>, typeof<'U>) I guess I will add this to my own collection of extensions I never use :D |
The following F# snippet:
Emits this IL:
and this codegen:
expected codegen:
The text was updated successfully, but these errors were encountered: