dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.9k stars 783 forks source link

Type inference assigns name to method generic args that conflict with type generic args #13062

Open alfonsogarciacaro opened 2 years ago

alfonsogarciacaro commented 2 years ago

This causes problems when resolving inlined expressions in Fable. For example, in the image below, FCS tells Fable there are two generic args for RouteBuilder, both named a and when inlining the code, Fable incorrectly assumes typeof<'a>.Name is "String" . See https://github.com/fable-compiler/repl/issues/152

image

Is this intended or cannot easily be fixed? It'd be very helpful to work on the assumption all generic arguments have unique names.

alfonsogarciacaro commented 2 years ago

This may be a regression, @inosik points here that there's no name conflict with the same code in VS2019 https://github.com/fable-compiler/repl/issues/152#issuecomment-1112103091

dsyme commented 2 years ago

I think this is only a bug in the inline type hints generation, since the actually compiler does the necessary name-avoidance:

type C<'a> =
    { R: Async<'a> }
    static member inline F x = x 

type C<'a> =
  { R: Async<'a> }
  static member inline F: x: 'a0 -> 'a0
alfonsogarciacaro commented 2 years ago

Thanks for the reply @dsyme. It's a bit strange, by debugging it looks like FCS indeed does solve the name conflict at some point, but when I inspect the name of the GenericArgument, I can only get the "unsolved" name. Please see the captured image. If I check the type of call_2 the string representation seems to be ^a * ^b -> 'b0 but when I check the generic arguments I get two duplicated b parameters.

image

However, I think I found a work-around. If I check the IsCompilerGenerated flag for the generic parameter, I can add a $ suffix and this solves the conflict with user-declared generics. Interestingly it seems I was using this work-around and I removed it at some point because I had the impression the issue was solved in FCS, but that seems not to be the case.

alfonsogarciacaro commented 1 year ago

Hi there!

This issue has been closed but the problem still seems to be there. Latest Fable uses latest code from FCS but when compiling the following code:

type MyRecord<'a> =
    { Value: 'a }
    // F# automatically still assigns 'a name to argument's generic type

    static member Stringify v = string v

The argument of Stringify method automatically gets assigned generic 'a type. This conflicts with the generic name of MyRecord<'a> and causes issues when compiling F# code to other languages with generics.

vzarytovskii commented 1 year ago

I don't think that should've been closed, since it's not exactly a codelens langservice related one

psfinaki commented 1 year ago

Hi @alfonsogarciacaro, sorry I closed this - I didn't read the description attentively enough and thought it was one of the CodeLens problems which are all irrelevant now since the whole thing is removed.

@vzarytovskii thanks for reopening, I added the triage label so that we properly go through this.

alfonsogarciacaro commented 1 year ago

@psfinaki No worries! The screenshot was indeed confusing :)