fsprojects / FSharp.TypeProviders.SDK

The SDK for creating F# type providers
https://fsprojects.github.io/FSharp.TypeProviders.SDK/
MIT License
298 stars 94 forks source link

Error with two instantiations of a generative provider with a root constructor #280

Closed Tarmil closed 5 years ago

Tarmil commented 5 years ago

Description

Compilation fails when trying to instantiate the same generative provider with different static parameters, when this provider has a constructor on the root generated type.

Repro steps

  1. Clone https://github.com/Tarmil/GenerativeTPCtorBug

  2. dotnet build

Expected behavior

The project compiles.

Actual behavior

The project fails with:

FSC : error FS2014: A problem occurred writing the binary 'C:\my\tpbug\User\obj\Debug\netstandard2.0\User.dll': Error in pass3 for type User.Say, error: Error in GetMethodRefAsMethodDefIdx for mref =(".ctor", "User.Bug2"), error: Exception of type 'Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter+MethodDefNotFound' was thrown. [C:\my\tpbug\User\User.fsproj]

The error disappears when commenting out one of the ctor calls in User/Library.fs.

Known workarounds

None.

Related information

kevmal commented 5 years ago

Looks like maybe you want to do (note both let asm bindings)


[<TypeProvider>]
type MyProvider (cfg: TypeProviderConfig) as this =
    inherit TypeProviderForNamespaces(cfg)

    let asm = Assembly.GetExecutingAssembly()

    let rootNamespace = "TpBug"

    do
        let templateTy = ProvidedTypeDefinition(asm, rootNamespace, "TpBugProvider", None, isErased = false)
        templateTy.DefineStaticParameters([ProvidedStaticParameter("param", typeof<string>)], fun typename pars ->
            let asm = ProvidedAssembly()
            let n = pars.[0] :?> string
            let ty = ProvidedTypeDefinition(asm, rootNamespace, typename, Some typeof<obj>, isErased = false)
            ProvidedConstructor([], fun _ -> <@@ () @@>) |> ty.AddMember
            asm.AddTypes([ty])
            ty
        )
        this.AddNamespace(rootNamespace, [templateTy])

[<assembly:TypeProviderAssembly>]
do ()
sergey-tihon commented 5 years ago

Thank you for sample @kevmal @Tarmil if you take a look at TP template, created by Don, it also create ProvidedAssembly inside t.DefineStaticParameters (for each call/usage of TP) https://github.com/fsprojects/FSharp.TypeProviders.SDK/blob/master/templates/content/basic/src/MyProvider.DesignTime/MyProvider.DesignTime.fs#L75

Tarmil commented 5 years ago

Thanks guys! That was indeed the problem.