< Summary - FSharp.Interop.Dlr

Information
Class: FSharp.Interop.Dlr.Discover
Assembly: FSharp.Interop.Dlr
File(s): /home/runner/work/FSharp.Interop.Dlr/FSharp.Interop.Dlr/FSharp.Interop.Dlr/Discover.fs
Line coverage
93%
Covered lines: 161
Uncovered lines: 11
Coverable lines: 172
Total lines: 341
Line coverage: 93.6%
Branch coverage
85%
Covered branches: 147
Total branches: 172
Branch coverage: 85.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
tryReflected(...)100%11100%
unreadableAssembly(...)100%2290%
reflected(...)100%11100%
failuresIn(...)100%44100%
runsAt(...)100%3838100%
instantiate(...)87.5%88100%
Invoke(...)100%22100%
resolve@120(...)100%22100%
Invoke(...)83.33%66100%
build@119(...)78.57%1414100%
Invoke(...)100%22100%
var@140(...)100%22100%
canonical(...)100%11100%
Invoke(...)100%66100%
go@146(...)100%66100%
oneOf(...)66.66%121290%
Invoke(...)75%44100%
Invoke(...)27.77%1991817.64%
agree@191(...)77.77%191888.23%
unreadableError(...)100%11100%
findBody(...)80.76%554689.83%
Invoke(...)100%11100%
search@241(...)100%11100%

File(s)

/home/runner/work/FSharp.Interop.Dlr/FSharp.Interop.Dlr/FSharp.Interop.Dlr/Discover.fs

#LineLine coverage
 1namespace FSharp.Interop.Dlr
 2
 3open System
 4open System.Collections.Concurrent
 5open System.Reflection
 6open FSharp.Quotations
 7open FSharp.Quotations.Patterns
 8open FSharp.Quotations.ExprShape
 9
 10/// Finds the quoted body of a `dlr { }` block from the type of its state machine (Release) or its
 11/// Delay closure (Debug on the 10.0 compiler, and the one shape Release leaves to the closure), using the
 12/// `[<ReflectedDefinition>]` of the enclosing member.
 13module internal Discover =
 14
 15    let private all =
 16        BindingFlags.Static ||| BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlag
 17
 18    /// Members with a reflected definition on `t` and every type nested in it (closures of a
 19    /// class member are nested in the enclosing module, not the class). Decoding a reflected
 20    /// definition costs microseconds and a module has one per member, so the result is kept
 21    /// per type: later blocks in the same type find their body without decoding again.
 22    let private reflectedCache = ConcurrentDictionary<Type, (MethodBase * Expr) list>()
 23
 24    /// Members whose stored quotation FSharp.Core could not decode, per type: some
 25    /// compiler-generated members have one (a [<CLIEvent>] accessor), and so can a member of the
 26    /// user's whose body FSharp.Core refuses (`typeof<System.Void>` in it). Neither is fatal here
 27    /// — the block may be elsewhere — but when no body is found, the failure is the likely reason.
 28    let private undecodable = ConcurrentDictionary<Type, (MethodBase * exn) list>()
 29
 30    let private tryReflected (m: MethodBase) =
 36423631        try Choice1Of2(Expr.TryGetReflectedDefinition m) with e -> Choice2Of2 e
 32
 33    /// Assemblies whose reflected definitions FSharp.Core cannot read at all, with its error. It
 34    /// reads them together and caches nothing when that fails, so every lookup reads them all again
 35    /// (#284): known, a block fails after one read, not one per member of the assembly.
 36    let private unreadable = ConcurrentDictionary<Reflection.Assembly, exn>()
 37    let private probing = ConcurrentDictionary<Reflection.Assembly, obj>()
 38
 39    /// Whether the assembly of a block's container cannot be read at all. The container never has a
 40    /// reflected definition, so decoding one of its methods throws only then: FSharp.Core reads an
 41    /// assembly's definitions together, and one it cannot bind (a function a signature hides,
 42    /// erased by Release inlining, #213; a `[<Literal>]` in a reflected module, #284) fails every
 43    /// method of every type. A body it refuses (`typeof<System.Void>`) fails only its own member.
 44    /// Told apart by this, not by FSharp.Core's (localized) message, which for Void names no member.
 45    let private unreadableAssembly (closureType: Type) : exn option =
 1352946        let assembly = closureType.Assembly
 1352947        match unreadable.TryGetValue assembly with
 1248        | true, e -> Some e
 49        | _ ->
 50            // One probe at a time per assembly: blocks first called together would each read a
 51            // failing table again. A readable one FSharp.Core keeps, so its probe costs nothing after
 52            // the first, and is not cached here.
 1354153            lock (probing.GetOrAdd(assembly, fun _ -> obj ())) (fun () ->
 1351754                match unreadable.TryGetValue assembly with
 055                | true, e -> Some e
 1351756                | _ ->
 8956757                    match closureType.GetMethods all |> Seq.tryPick (fun m -> match tryReflected m with Choice2Of2 e -> 
 958                    | Some e -> Some(unreadable.GetOrAdd(assembly, e))
 2702559                    | None -> None)
 60
 61    let rec private reflected (t: Type) : (MethodBase * Expr) list =
 8075062        reflectedCache.GetOrAdd(t, fun t ->
 5176663            let failures = ResizeArray()
 5176664            let found =
 40510065                [ for m in Seq.append (t.GetMethods all |> Seq.cast<MethodBase>) (t.GetConstructors all |> Seq.cast<Meth
 30140466                      match tryReflected m with
 1006767                      | Choice1Of2(Some q) -> yield m, q
 8873968                      | Choice1Of2 None -> ()
 3069                      | Choice2Of2 e -> failures.Add((m, e))
 20585670                  for n in t.GetNestedTypes all do
 10232471                      yield! reflected n ]
 5179072            if failures.Count > 0 then undecodable.[t] <- List.ofSeq failures
 13251673            found)
 74
 75    /// The decode failures recorded for `types` and their nested types, for the not-found message.
 76    let rec private failuresIn (types: seq<Type>) : (MethodBase * exn) list =
 249049577        [ for t in types do
 124509078              match undecodable.TryGetValue t with
 41179              | true, fs -> yield! fs
 62238680              | _ -> ()
 124519581              yield! failuresIn (t.GetNestedTypes all) ]
 82
 83    /// Every `builder.Run(builder.Delay((fun () -> body), file, line))` in `e` at this file and line.
 84    let rec private runsAt (builderType: Type) (file: string) (line: int) (e: Expr) : Expr list =
 57576171885        match e with
 86        | Call(Some receiver, mi, [ Call(_, delay, [ Lambda(_, body); Value(f, _); Value(l, _) ]) ])
 2439876087            when receiver.Type = builderType && mi.Name = "Run" && delay.Name = "Delay"
 814723488                 && unbox<int> l = line && unbox<string> f = file ->
 89            // Blocks nested inside this one compile with it (see Translate), so do not list them.
 1377890            [ body ]
 14141557191        | ShapeVar _ -> []
 12698271392        | ShapeLambda(_, body) -> runsAt builderType file line body
 46112821293        | ShapeCombination(_, args) -> args |> List.collect (runsAt builderType file line)
 94
 95    /// What a block needs from its enclosing member's reflected definition.
 96    type Found =
 97        { /// Type declaring the enclosing member: the binder's accessibility context, as in C#.
 98          Context: Type
 99          /// The whole reflected body of the enclosing member, for resolving let-bound values
 100          /// the optimizer inlined instead of capturing.
 101          MemberBody: Expr
 102          /// The block's body (the Delay lambda's body).
 103          Body: Expr }
 104
 105    /// For a block inside a generic member, the closure class carries the member's type parameters
 106    /// (and its type's) that it uses, under the same names, instantiated. Rebuild the member with
 107    /// those arguments so its reflected definition comes back with concrete types. A parameter the
 108    /// closure does not carry is unused by the block, so any instantiation will do: `obj`, or,
 109    /// where a constraint rejects `obj` (#222), the parameter itself, left open.
 110    let private instantiate (closureType: Type) (m: MethodBase) : MethodBase =
 53156111        if not (m.IsGenericMethodDefinition || m.DeclaringType.IsGenericTypeDefinition) then m
 112        else
 113            let concrete =
 132114                if closureType.IsGenericType then
 108115                    Array.zip (closureType.GetGenericTypeDefinition().GetGenericArguments()) (closureType.GetGenericArgu
 174116                    |> Array.map (fun (p, a) -> p.Name, a)
 108117                    |> dict
 24118                else dict []
 119            let build (unused: Type -> Type) =
 456120                let resolve (p: Type) = match concrete.TryGetValue p.Name with | true, t -> t | _ -> unused p
 121                let onType =
 180122                    if m.DeclaringType.IsGenericTypeDefinition then
 192123                        let constructed = m.DeclaringType.MakeGenericType(m.DeclaringType.GetGenericArguments() |> Array
 72124                        MethodBase.GetMethodFromHandle(m.MethodHandle, constructed.TypeHandle)
 84125                    else m
 156126                match onType with
 156127                | :? MethodInfo as mi when mi.IsGenericMethodDefinition ->
 216128                    mi.MakeGenericMethod(mi.GetGenericArguments() |> Array.map resolve) :> MethodBase
 48129                | other -> other
 312130            try build (fun _ -> typeof<obj>)
 144131            with :? ArgumentException -> build id
 132
 133    /// A body with its variables renamed canonically, so two trees compare equal exactly when they
 134    /// are the same up to their variables: each binder by its position, each free variable by its
 135    /// name, type and mutability. `shared` gives both trees the same `Var` for the same name, as
 136    /// `Expr` compares variables by reference. Two free variables of one name in one tree would
 137    /// become one; the reflected definition is the unoptimized source, where a block cannot see
 138    /// two variables of one name (the inner one shadows the outer), so that does not arise.
 139    let private canonical (shared: System.Collections.Generic.Dictionary<string, Var>) (e: Expr) : Expr =
 140        let var (key: string) (t: Type) (isMutable: bool) =
 2154141            let key = sprintf "%s:%O:%b" key t isMutable
 2154142            match shared.TryGetValue key with
 1143143            | true, v -> v
 3033144            | _ -> let v = Var(key, t, isMutable) in shared.[key] <- v; v
 672145        let mutable binders = 0
 146        let rec go (bound: Map<Var, Var>) (e: Expr) =
 5610147            match e with
 148            | ShapeVar v ->
 2112149                match bound.TryFind v with
 210150                | Some c -> Expr.Var c
 1902151                | None -> Expr.Var(var ("free " + v.Name) v.Type v.IsMutable)
 152            | ShapeLambda(v, body) ->
 252153                binders <- binders + 1
 252154                let c = var (sprintf "bound %d" binders) v.Type v.IsMutable
 252155                Expr.Lambda(c, go (bound.Add(v, c)) body)
 3246156            | _ -> Quotation.rebuild (go bound) e
 672157        go Map.empty e
 158
 159    /// The one block `bodies` are, when they are several copies of it. The quotation holds a match
 160    /// arm whose or-pattern binds a variable once per alternative, each copy over its own `Var`s,
 161    /// so the block is found once per alternative at its line (#263). Copies are taken as one block
 162    /// only when it cannot matter which is used: the same up to their variables, and every variable
 163    /// the block reads either a field of its own container (as the translator sees them), read by
 164    /// name where the translator reads it so (not an alias it substitutes), or one whose recovered definition is the sa
 165    /// reaches only such variables in turn (#271): the translator recovers it from the first copy,
 166    /// and the copy that ran would give the same. A variable whose definitions differ (an inlined
 167    /// pattern variable, `Choice1Of2`'s field in one copy and `Choice2Of2`'s in another; another
 168    /// block's look-alike on the same line) keeps the copies refused. The builder is never
 169    /// captured (the translator drops it by type, as here). `Error` names the variables that kept
 170    /// copies from being taken as one, or is empty when the runs are not copies at all.
 171    let private oneOf (builderType: Type) (closureType: Type) (memberBody: Expr) (bodies: Expr list) : Result<Expr, stri
 354172        match bodies with
 84173        | [ body ] -> Ok body
 174        | first :: rest ->
 270175            let shared = System.Collections.Generic.Dictionary<string, Var>()
 270176            let shape = canonical shared first
 864177            if not (rest |> List.forall (fun b -> canonical shared b = shape)) then Error []
 178            else
 179                // The translator's own view of the container's fields: a machine's `Data` and
 180                // `ResumptionPoint` are not captures, though a variable may be named either.
 258181                let fields = TranslateBlock.Captures.fields closureType
 182                // Per tree, its free variables by name: None when two share one (not the unoptimized
 183                // source's, where the inner shadows the outer).
 184                let byName (e: Expr) =
 876185                    let vs = e.GetFreeVars() |> List.ofSeq
 2574186                    let names = vs |> List.map (fun v -> v.Name)
 5724187                    if List.length (List.distinct names) = names.Length then Some(dict [ for v in vs -> v.Name, v ]) els
 188                // Per copy, its own free variables, which the translator never takes for aliases.
 1224189                let owns = bodies |> List.map (fun b -> b.GetFreeVars() |> Set.ofSeq)
 190                // Whether it cannot matter which copy's variable this is (`vars`, one per copy, of one name).
 191                let rec agree (vars: Var list) =
 831192                    let v = List.head vars
 831193                    v.Type = builderType
 194                    // Read from its field, as the translator reads it: not an alias it substitutes,
 195                    // which a field of its name may sit beside, holding another variable (#272 review).
 2133196                    || (fields.ContainsKey v.Name && not (List.exists2 (fun own w -> TranslateBlock.Captures.isAlias own
 197                    // Bound outside the copies: one variable, one definition.
 189198                    || vars |> List.forall (fun w -> w = v)
 180199                    || (let defs = vars |> List.map (fun w -> TranslatePatterns.letDefinition w memberBody |> Option.orE
 60200                        match List.choose id defs with
 60201                        | first :: rest when rest.Length = defs.Length - 1 ->
 60202                            let shared = System.Collections.Generic.Dictionary<string, Var>()
 60203                            let shape = canonical shared first
 120204                            rest |> List.forall (fun d -> canonical shared d = shape)
 27205                            && (match List.choose byName (first :: rest) with
 27206                                | reached :: others when others.Length = rest.Length ->
 27207                                    reached.Keys |> Seq.forall (fun n ->
 54208                                        others |> List.forall (fun o -> o.ContainsKey n)
 135209                                        && agree (reached.[n] :: [ for o in others -> o.[n] ]))
 0210                                | _ -> false)
 0211                        | _ -> false)
 258212                match List.choose byName bodies with
 258213                | copies when copies.Length = bodies.Length ->
 258214                    let firstVars = List.head copies
 215                    let uncaptured =
 258216                        firstVars.Keys
 258217                        |> Seq.filter (fun n ->
 7344218                            let vars = [ for c in copies -> match c.TryGetValue n with | true, v -> Some v | _ -> None ]
 2556219                            not (List.forall Option.isSome vars && agree (List.choose id vars)))
 258220                        |> List.ofSeq
 258221                    match uncaptured with
 225222                    | [] -> Ok first
 33223                    | uncaptured -> Error uncaptured
 224                // Two free variables of one name in a body: not seen in a reflected one (an inner
 225                // binding shadows), kept so that it would be refused, not guessed.
 0226                | _ -> Error [ for v in first.GetFreeVars() -> v.Name ]
 0227        | [] -> Error []
 228
 229    /// The error for a block whose assembly's reflected definitions cannot be read (`unreadableAssembly`).
 230    let private unreadableError (file: string) (line: int) (holder: Type) (closureType: Type) (e: exn) =
 21231        DlrTranslationException(
 21232            sprintf "dlr { } at %s:%d cannot find its body: FSharp.Core could not decode any of %s's reflected definitio
 21233                file line (holder.Assembly.GetName().Name) e.Message closureType.Name holder.FullName)
 234
 235    /// The block whose Delay closure has type `closureType`, at `file:line`.
 236    let findBody (builderType: Type) (closureType: Type) (file: string) (line: int) : Found =
 26938237        let holder = if isNull closureType.DeclaringType then closureType else closureType.DeclaringType
 13469238        match unreadableAssembly closureType with
 21239        | Some e -> raise (unreadableError file line holder closureType e)
 13448240        | None -> ()
 241        let search (types: seq<Type>) =
 13532242            types
 13532243            |> Seq.collect reflected
 10172473244            |> Seq.collect (fun (m, q) -> runsAt builderType file line q |> List.map (fun b -> m, q, b))
 13532245            |> List.ofSeq
 13448246        let searched = ResizeArray<Type>()
 247        let matches =
 13448248            searched.Add holder
 13448249            match search [ holder ] with
 250            | [] ->
 251                // A member of a type declared in a namespace gets its closures nested in the file's
 252                // <StartupCode$…> class, not in the type: fall back to the whole assembly.
 724346253                let all = closureType.Assembly.GetTypes() |> Seq.filter (fun t -> not t.IsNested) |> List.ofSeq
 84254                searched.AddRange all
 84255                search all
 13364256            | found -> found
 257        // Copies of one block in one member (an or-pattern's arm) are that block, not several.
 258        let matches =
 13448259            match matches with
 7335260            | (m, memberBody, _) :: rest when not rest.IsEmpty && rest |> List.forall (fun (m', _, _) -> m' = m) ->
 1026261                match oneOf builderType closureType memberBody (matches |> List.map (fun (_, _, b) -> b)) with
 201262                | Ok body -> [ m, memberBody, body ]
 12263                | Error [] -> matches
 264                | Error uncaptured ->
 33265                    raise (DlrTranslationException(
 33266                            sprintf "dlr { } at %s:%d is held %d times in its member's reflected definition (an or-patte
 33267                                file line matches.Length (uncaptured |> List.map (sprintf "'%s'") |> String.concat ", ")
 33268                                (String.Join(", ", (TranslateBlock.Captures.fields closureType).Keys))))
 13202269            | _ -> matches
 13415270        match matches with
 271        | [ m, memberBody, body ] ->
 272            let m, memberBody, body =
 13343273                match instantiate closureType m with
 26578274                | inst when obj.ReferenceEquals(inst, m) -> m, memberBody, body
 275                | inst ->
 108276                    match tryReflected inst with
 277                    | Choice1Of2(Some q) ->
 108278                        match oneOf builderType closureType q (runsAt builderType file line q) with
 108279                        | Ok b -> inst, q, b
 0280                        | Error _ -> m, memberBody, body
 0281                    | _ -> m, memberBody, body
 13343282            { Context = m.DeclaringType; MemberBody = memberBody; Body = body }
 283        | [] ->
 284            // Checked before the search too; a table may also fail between (another thread's block).
 60285            let assemblyWide = unreadableAssembly closureType
 286            // A member with the attribute whose quotation would not decode is the other reason a
 287            // body is not found — when it is the member the closure belongs to: the compiler
 288            // names a block's closure `<member>@<line>`. A name alone also matches a same-named
 289            // member of another type (#248), so this is stated only for a member declared in the
 290            // type holding the closure. A class's closures are nested in its module, which its
 291            // sibling classes share, so a class member is left to the hint below, whose wording
 292            // allows for a wrong guess, like any other match.
 453293            let own = failuresIn searched |> List.tryFind (fun (m, _) -> closureType.Name.StartsWith(m.Name + "@") && m.
 60294            match assemblyWide, own with
 0295            | Some e, _ -> raise (unreadableError file line holder closureType e)
 296            | None, Some(m, e) ->
 15297                raise (DlrTranslationException(
 15298                        sprintf "dlr { } at %s:%d is in %s.%s, whose reflected definition FSharp.Core could not decode (
 15299                            file line m.DeclaringType.Name m.Name e.Message closureType.Name holder.FullName))
 300            | None, None ->
 301                // A block in a local function has a closure named after the local, not the member
 302                // (Debug; Release names the machine after the member), so the member is unknown
 303                // here (#245). Members that failed to decode in the closure's type and the types
 304                // nested in it (a class in the module) are then the likely place. A type declared in
 305                // a namespace has its closures in the file's <StartupCode$…> class, which nothing
 306                // ties to the types the file declares: there, the assembly's. The attribute may still
 307                // be missing, so they are a hint after the missing-attribute message, not a
 308                // replacement for it.
 309                let candidates =
 171310                    if not (isNull holder.Namespace) && holder.Namespace.StartsWith "<StartupCode$" then failuresIn sear
 57311                    else failuresIn [ holder ]
 21312                    // `searched` holds the closure's type twice when the assembly-wide fallback ran,
 21313                    // and a nested type comes once more through its parent.
 45314                    |> List.distinctBy fst
 315                let hint =
 45316                    match candidates with
 317                    | [] ->
 318                        // A trimmed publish keeps the stored definitions but not what FSharp.Core
 319                        // matches them by, so the block is not found although the attribute is
 320                        // there: say so where the assembly holds reflected definitions at all.
 45321                        if holder.Assembly.GetManifestResourceNames() |> Array.exists (fun n -> n.StartsWith "ReflectedD
 18322                            " If the attribute is there and the app is published trimmed (PublishTrimmed), trimming is t
 0323                        else ""
 324                    | [ m, e ] ->
 0325                        sprintf " If the block is in %s.%s (in a local function there, say), the attribute is there, but
 0326                            m.DeclaringType.Name m.Name e.Message
 327                    | several ->
 328                        // One error per distinct message, with the members it was raised for.
 329                        let named =
 27330                            several
 135331                            |> List.groupBy (fun (_, e) -> e.Message)
 207332                            |> List.map (fun (message, ms) -> sprintf "%s (%s)" (ms |> List.map (fun (m, _) -> m.Declari
 27333                            |> String.concat "; "
 27334                        sprintf " If the block is in one of %s (in a local function there, say), the attribute is there,
 27335                            named
 45336                raise (DlrTranslationException(
 45337                        sprintf "dlr { } at %s:%d needs [<ReflectedDefinition>] on the function or member that contains 
 45338                            file line closureType.Name holder.FullName hint))
 339        | many ->
 12340            raise (DlrTranslationException(
 12341                    sprintf "%d dlr { } blocks share %s:%d; put each dlr { } on its own line." many.Length file line))

Methods/Properties

tryReflected(System.Reflection.MethodBase)
unreadableAssembly(System.Type)
reflected(System.Type)
failuresIn(System.Collections.Generic.IEnumerable`1<System.Type>)
runsAt(System.Type,System.String,System.Int32,Microsoft.FSharp.Quotations.FSharpExpr)
instantiate(System.Type,System.Reflection.MethodBase)
Invoke(System.Type)
resolve@120(System.Collections.Generic.IDictionary`2<System.String,System.Type>,Microsoft.FSharp.Core.FSharpFunc`2<System.Type,System.Type>,System.Type)
Invoke(Microsoft.FSharp.Core.FSharpFunc`2<System.Type,System.Type>)
build@119(System.Reflection.MethodBase,System.Collections.Generic.IDictionary`2<System.String,System.Type>,Microsoft.FSharp.Core.FSharpFunc`2<System.Type,System.Type>)
Invoke(System.String,System.Type,System.Boolean)
var@140(System.Collections.Generic.Dictionary`2<System.String,Microsoft.FSharp.Quotations.FSharpVar>,System.String,System.Type,System.Boolean)
canonical(System.Collections.Generic.Dictionary`2<System.String,Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Collections.FSharpMap`2<Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
go@146(System.Collections.Generic.Dictionary`2<System.String,Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Core.FSharpRef`1<System.Int32>,Microsoft.FSharp.Collections.FSharpMap`2<Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
oneOf(System.Type,System.Type,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Quotations.FSharpExpr>)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Quotations.FSharpVar>)
agree@191(System.Type,Microsoft.FSharp.Quotations.FSharpExpr,System.Collections.Generic.IDictionary`2<System.String,System.Reflection.FieldInfo>,Microsoft.FSharp.Core.FSharpFunc`2<Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Core.FSharpOption`1<System.Collections.Generic.IDictionary`2<System.String,Microsoft.FSharp.Quotations.FSharpVar>>>,Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>>,Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Quotations.FSharpVar>)
unreadableError(System.String,System.Int32,System.Type,System.Type,System.Exception)
findBody(System.Type,System.Type,System.String,System.Int32)
Invoke(System.Collections.Generic.IEnumerable`1<System.Type>)
search@241(System.Type,System.String,System.Int32,System.Collections.Generic.IEnumerable`1<System.Type>)