4

I have a type provider which gives me the error "Type mismatch when splicing expression into quotation literal".

I extracted the code below in order to reproduce the issue in a smaller context.

let f (s : string) : string = s //some dummy implementation

let t = ProvidedTypeDefinition(asm, ns, "Root", Some typeof<obj>)
let ctor = ProvidedConstructor(parameters = [],
                               InvokeCode = (fun args -> <@@ "root" :> obj @@>)) :> MemberInfo

let prop = ProvidedProperty(propertyName = "SomeProperty",
                            parameters = [],
                            propertyType = typeof<string>,
                            GetterCode = (fun args -> <@@ f %%(args.[0]) @@>)) :> MemberInfo

do  t.AddMembers [ctor; prop]
    t.SetBaseType typeof<obj>

...and when I use the type provider like

let root = Provided.Root()

let a = root.SomeProperty

I get the error:

Error: The type provider 'typeproviders.providerpoc+MyProvider' reported an error in the context of provided type 'typeproviders.providerpoc.Provided.Root', member 'get_Menu'.

The error: Type mismatch when splicing expression into quotation literal.

The type of the expression tree being inserted doesn't match the type expected by the splicing operation.

Expected 'System.Object', but received type 'System.String'.

Consider type-annotating with the expected expression type, e.g., (%% x : string) or (%x : string).. Parameter name: receivedType.

How can I write the quotation to be able to call a function inside the quotation?

Thanks!

vidi
  • 2,056
  • 16
  • 34
  • 1
    Have you tried type-annotating with expected type as the error message tells you? – Fyodor Soikin Feb 03 '17 at 15:14
  • @FyodorSoikin - the message is a bit misleading because the `string` part of it is just an example not related to the actual type mismatch, and represents the _expected_ type, not the _received_ type. So you actually would need to use `%%(args.[0] : obj)`, but that won't fix anything by itself since `f` expects a string. Tomas's answer shows the right way to fix this. – kvb Feb 03 '17 at 17:37

1 Answers1

6

What the error message is saying is that you are putting a quoted expression of type obj in a place where a quoted expression of type string is expected.

I suspect this is happening when creating the GetterCode in the provided property:

GetterCode = (fun args -> <@@ f %%(args.[0]) @@>)

Here, args is an array of quoted expressions where each expression is of type obj, but the function f expects a string and so the quotation filling the hole using %% should be of type string

Adding a type conversion that would turn the obj into string should do the trick:

GetterCode = (fun args -> <@@ f (unbox<string> (%%(args.[0]))) @@>)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553