fable-compiler / repl

Fable online REPL
http://fable.io/repl
MIT License
61 stars 34 forks source link

Fable typeof seems to be broken in versions > 3.7 #152

Closed zelenij closed 2 years ago

zelenij commented 2 years ago

This code

open System
open Fable.Core
open Fable.Core.JsInterop

[<Emit("window.alert($0)")>]
let alert (message: string): unit = jsNative

type Test = {
    Name: string
}

type R = 
    | A of int
    | B of string

type Service<'a> = {
    GetRecord: int -> int64 -> Async<'a>
}
with
    static member inline RouteBuilder _ m =
        let name = typeof<'a>.Name
        sprintf "/api/%s/%s" name m

let a = R.A 72
let oa = a.GetType().Name
let a1 = Service<R>.RouteBuilder "" "Add"
alert(a1)

when run in the online tool with fable 3.7.9 produces

/api/String/Add

Expected:

/api/R/Add

And with version 3.7.0 it does that.

alfonsogarciacaro commented 2 years ago

This is a tricky thing, maybe we should report it to the F# compiler. The problem is that the F# compiler assigns the same name to the generic automatically inferred for the unused argument and this confuses Fable. If you explicitly type the generic argument the problem is solved.

static member inline RouteBuilder (_: 'b) m =

Unfortunately I'm afraid I cannot easily fix this in Fable but I will add a warning to the next version so users can fix the issue in their code. Thanks for reporting!

image

zelenij commented 2 years ago

I see, interesting...

Any idea why it actually works in Fable 3.7.0 and below?

inosik commented 2 years ago

This might be a regression in F#. In VS 2019 the signature of RouteBuilder is 'a0 -> string ->string when hovering over it.

inosik commented 2 years ago

But it doesn't look like we updated FCS after 3.7.0, so probably not?

alfonsogarciacaro commented 2 years ago

Yes, unfortunately we don't keep real control of the FCS version, because we just make custom builds of ncave's fork whenever is rebased with dotnet/fsharp 😅

alfonsogarciacaro commented 2 years ago

Actually I found a work-around, see last part of this comment. If you upgrade to Fable 3.7.11 it should work without the explicit annotations.

zelenij commented 2 years ago

Nice one! 👍

ncave commented 1 year ago

@alfonsogarciacaro Do we want to revert this work-around, now that dotnet/fsharp#13062 is supposedly fixed?

alfonsogarciacaro commented 1 year ago

@ncave Unfortunately this still seems to be a problem. With latest Fable version (which should contain latest FCS bits) in this code:

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

    static member Stringify v = string v

The Stringify method gets compiled in Dart as follows, which causes an error because the name of the generics is the same:

String MyRecord$1_Stringify_2B595<$a, $a>($a v) => v.toString();
ncave commented 1 year ago

@alfonsogarciacaro That's ok, for Rust it is the other way (generating an unnecessary type param), so I removed the work-around for Rust only.