SwensenSoftware / unquote

Write F# unit test assertions as quoted expressions, get step-by-step failure messages for free
http://www.swensensoftware.com/unquote
Apache License 2.0
285 stars 26 forks source link

NotSupportedException in eval #139

Closed marklam closed 6 years ago

marklam commented 6 years ago

The following test throws a NotSupportedException

let inline sq x = 
    x * x

let inline fsq x =
    sq (float x)

[<Test>]
let ``fsq converts the argument to float and then squares it`` () =
    test <@ fsq 25uy = 625.0 @>

produces


TestMath.fsq 25uy = 625.0
System.NotSupportedException: Specified method is not supported.
   at TestMath.fsq[a](a x) 
   at Swensen.Unquote.Evaluation.eval(FSharpList`1 env, FSharpExpr expr)
   at Swensen.Unquote.Reduction.reduce(FSharpList`1 env, FSharpExpr expr)
   at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x)
   at Swensen.Unquote.Reduction.reduce(FSharpList`1 env, FSharpExpr expr)
   at Swensen.Unquote.Reduction.loop@126(FSharpList`1 env, FSharpExpr expr, FSharpList`1 acc)```
stephen-swensen commented 6 years ago

Thanks for reporting @marklam - I was able to reproduce and am digging deeper into it.

stephen-swensen commented 6 years ago

@marklam turns out this is a limitation of certain inline functions (with statically resolved type parameters) not being dynamically invokable (in this case the float function is the culprit). Since Unquote evaluation is based on reflection, I don't think it can be overcome. See https://stackoverflow.com/a/40853727/236255 for a little more insight.

You can, of course, avoid this issue by evaluating fsq 25uy outside of a quotation:

let actual = fsq 25uy
test <@ actual = 625.0 @>
marklam commented 6 years ago

Thanks for taking the time to look into it. I was particularly interested in evaluating inline functions in the quotation to get coverage tools to mark inlined functions' definitions as covered, but I guess that won't work for SRTP functions.