Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error FS3039: A direct reference to the generated type 'MyType' is not permitted

The following type provider was intended to create GeneratedNamespace.MyType which accepts a static parameter of type string and contains only an empty constructor

namespace TypeProviderTest

open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
open System

[<TypeProvider>]
type MyTypeProvider(config:TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces()
    let namespaceName="GeneratedNamespace"
    let assembly = Assembly.LoadFrom(config.RuntimeAssembly)

    //Provides definition, based on type parameters
    let instantiationFunction typeName (typeParams:obj[]) =
        match typeParams with
                | [|:? string as param|] -> 
                    //Creates an empty non-erased type
                    let definition = ProvidedTypeDefinition(
                                        assembly,
                                        namespaceName,
                                        typeName,
                                        Some typedefof<Object>,
                                        IsErased = false
                                        )

                    //Creates an empty constructor
                    let emptyCtor = ProvidedConstructor (parameters = [])
                    //Provides a call to base constructor 
                    //(https://stackoverflow.com/questions/22520352/)
                    //Doesn't seem to help
                    let objCtor = typedefof<Object>.GetType().GetConstructor([||])
                    emptyCtor.BaseConstructorCall <- (fun _ -> objCtor,[])
                    emptyCtor.AddXmlDoc("Empty constructor test")

                    definition.AddMember(emptyCtor)
                    definition
                | _ -> failwith "That was not supported"

    let  staticParams = [ProvidedStaticParameter("value",typedefof<string>)] 
    let t = ProvidedTypeDefinition(assembly,namespaceName,"MyType",Some typedefof<Object>)
    do t.DefineStaticParameters(staticParams,instantiationFunction)


    do this.AddNamespace(namespaceName,[t])
[<assembly:TypeProviderAssembly>]
do ()

When I try to use it like this

open System
open GeneratedNamespace
type X = MyType<"Abacaba">
[<EntryPoint>]
let main argv = 
    printfn "%A %A" typedefof<X> (new X())
    Console.ReadLine() |> ignore
    0 

The line type X = MyType<"Abacaba"> produces the error

Error FS3039: A direct reference to the generated type 'MyType' is not permitted.

I added a base constructor call, but it didn't help

The type provider is made generative intentionally

Is there an error in my type provider?

like image 690
user2136963 Avatar asked Apr 22 '16 12:04

user2136963


1 Answers

I'm not sure how to make it fully work, but I think the reason why you're getting the error is that the parameterised type is an erased type (while the type that you return once static parameters are provided is not an erased type).

Adding IsErased = false to t makes the error go away:

let  staticParams = [ProvidedStaticParameter("value",typedefof<string>)] 
let t = 
  ProvidedTypeDefinition
    (assembly,namespaceName,"MyType",Some typedefof<Object>,IsErased = false)
do t.DefineStaticParameters(staticParams,instantiationFunction)

With this, the code can be compiled, but trying to create an instance using new X() gives:

error FS0192: internal error: null: GetTRefType

So, there is probably something else that I'm missing too. Perhaps it can point you into the right direction though!

like image 54
Tomas Petricek Avatar answered Oct 20 '22 16:10

Tomas Petricek