Compiler does not infer string type for nameof pattern
When using nameof in a pattern match, I'd expect the compiler to infer the argument type as string since nameof returns a string. However, the argument is treated as generic and generates invalid IL.
Repro steps
// Expected:
// FS0001: This expression was expected to have type 'int' but here has type 'string'
// Actual:
// No compile error; InvalidProgramException at runtime.
match 3 with
| nameof int -> true
| _ -> false
// Expected inferred type:
// val f : x:string -> bool
// Actual inferred type:
// val f : x:'a -> bool
let f x = match x with nameof x -> true | _ -> false
According to the RFC for the nameof pattern feature, the nameof expr should be "equivalent to a literal string pattern" which is not being respected.
Expected behavior
Expect the compiler to infer argument type as string when nameof is used in a pattern match.
Actual behavior
Compiler infers argument type as generic argument when nameof is used in a pattern match.
Known workarounds
Explicit type annotation.
let f (x:string) = match x with nameof x -> true | _ -> false
@dsyme this is indeed producing invalid IL, hit it today as well.
Thanks, should be a simple fix
@vzarytovskii this is a good first issue, happy to guide the fix
I have also hit this . Happy to help fixing this with a little bit of guidance as I’m still new to the compiler . cc @dsyme
I looked a bit into this and to me it seems that the issue to be in match than in nameof implementation.
I would like some guidance to make a fix for this, @vzarytovskii can you help?
I looked a bit into this and to me it seems that the issue to be in
matchthan innameofimplementation. I would like some guidance to make a fix for this, @vzarytovskii can you help?
Hey, @ntovas, I'm on vacation currently, without acces to my laptop unfortunately :(
Perhaps someone from the team can chime in, and help you looking into it? @dotnet/fsharp-team-msft ping!
@ntovas :
This is the approach I would take: Add a failing test into the Component.Tests suite, into \tests\FSharp.Compiler.ComponentTests\Language*NameofTests*.fs .
Before starting it, sprinkle breakpoints around code in the TypeChecking state, so that you can step the execution and investigate the available parameters.
One of the places that seems to be related is \src\Compiler*Checking**CheckPatterns*.fs . I would try to put a few breakpoints into that and trace it - e.g. to verify that the nameof is infered to be a constant expression, and also explicitely marked as constant expression of string type.
All nameof-related functionality is a behind a feature flag, which can also give you an idea at which places the compiler interacts with this feature:
g.langVersion.SupportsFeature LanguageFeature.NameOf
I would also add that nameof is not a typical function, and has a special treatment in the compiler. That's why it behaves differently to all other functions.
Hey @T-Gro , Maybe you can check the linked PR?
On it :)