Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with sequence of non-erased type #352

Closed
giacomociti opened this issue Nov 9, 2020 · 0 comments
Closed

Issue with sequence of non-erased type #352

giacomociti opened this issue Nov 9, 2020 · 0 comments

Comments

@giacomociti
Copy link
Contributor

Description

I'm struggling to create a non-erased type with a member returning a sequence of another (or even the same) non-erased type

Repro steps

[<TypeProvider>]
type BasicGenerativeProvider (config : TypeProviderConfig) as this =
	inherit TypeProviderForNamespaces (config, assemblyReplacementMap=[("LemonadeProvider.DesignTime", "LemonadeProvider.Runtime")])

	let ns = "LemonadeProvider"
	let asm = Assembly.GetExecutingAssembly()

	let createType typeName (count:int) =
		let asm = ProvidedAssembly()
		let myType = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>, isErased=false)

		let ctor = ProvidedConstructor([], invokeCode = fun _ -> <@@ () @@>)
		myType.AddMember(ctor)
		
		let resultType = ProvidedTypeBuilder.MakeGenericType(typedefof<seq<_>>, [myType])
		let lambda = Expr.Lambda(Var("_", typeof<int>), Expr.NewObject(ctor, []))
		let runtimeMethod = 
			let methodInfo = 
				match <@@ CommandRuntime.Map(id, []) @@> with
				| Patterns.Call(_, m, _) -> m
				| _ -> failwith "unexpected"
			ProvidedTypeBuilder.MakeGenericMethod(methodInfo.GetGenericMethodDefinition(), [myType])
		let integerSequence = <@@ Seq.init count id @@>
		let myProp = ProvidedProperty("foo", resultType, getterCode = function _ -> Expr.Call(runtimeMethod, [lambda ; integerSequence]))
			   
		myType.AddMember myProp
		asm.AddTypes [ myType ]
		myType

	let myParamType = 
		let t = ProvidedTypeDefinition(asm, ns, "GenerativeProvider", Some typeof<obj>, isErased=false)
		t.DefineStaticParameters( [ProvidedStaticParameter("Count", typeof<int>)], fun typeName args -> createType typeName (unbox<int> args.[0]))
		t
	do
		this.AddNamespace(ns, [myParamType])

where in the runtime project I have the following helper method:

type CommandRuntime =
    static member Map(f, items: seq<int>) = Seq.map f items

Expected behavior

I expected the above code to create a working type provider:

type Gimme5 = LemonadeProvider.GenerativeProvider<5>

[<Test>]
let ``Can list`` () =
    let x: Gimme5 list = Gimme5().foo |> Seq.toList
    Assert.AreEqual(5, x.Length)

Actual behavior

The error raised is 'unexpected erased target ProvidedTypeDefinition' (thrown in ProvidedTypes.fs)

Known workarounds

It works adding a guard at line 8982:

if ptd.BelongsToTargetModel then failwithf "unexpected erased target ProvidedTypeDefinition '%O'" ptd

if ptd.IsErased && ptd.BelongsToTargetModel then failwithf "unexpected erased target ProvidedTypeDefinition '%O'" ptd

and a similar one at line 9269

if x.BelongsToTargetModel then failwithf "unexpected target type definition '%O'" x

 if x.IsErased && x.BelongsToTargetModel then failwithf "unexpected target type definition '%O'" x

but I'm a bit reluctant to propose such changes because I have no idea about their possible impacts.

giacomociti added a commit to giacomociti/FSharp.TypeProviders.SDK that referenced this issue Nov 29, 2020
@giacomociti giacomociti mentioned this issue Nov 29, 2020
@dsyme dsyme closed this as completed in a09c88b Dec 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant