fsharp icon indicating copy to clipboard operation
fsharp copied to clipboard

Compiler does not infer string type for nameof pattern

Open niesmo opened this issue 3 years ago • 4 comments

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

niesmo avatar Jun 24 '22 13:06 niesmo

@dsyme this is indeed producing invalid IL, hit it today as well.

NinoFloris avatar Jul 04 '22 13:07 NinoFloris

Thanks, should be a simple fix

dsyme avatar Jul 04 '22 15:07 dsyme

@vzarytovskii this is a good first issue, happy to guide the fix

dsyme avatar Jul 08 '22 13:07 dsyme

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

edgarfgp avatar Jul 19 '22 20:07 edgarfgp

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?

ntovas avatar Oct 09 '22 15:10 ntovas

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?

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!

vzarytovskii avatar Oct 09 '22 23:10 vzarytovskii

@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

T-Gro avatar Oct 10 '22 11:10 T-Gro

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.

vzarytovskii avatar Oct 10 '22 11:10 vzarytovskii

Hey @T-Gro , Maybe you can check the linked PR?

ntovas avatar Oct 11 '22 17:10 ntovas

On it :)

T-Gro avatar Oct 11 '22 19:10 T-Gro