Skip to content

Commit e5762fd

Browse files
krauthaufenKevinRansom
authored andcommitted
typeof in quotations.fs now respects ByRef types (#3450)
* typeof in quotations.fs now respects ByRef types * [Test] added tests for AddressOf quotations - AddressOf now has a proper type (byref<'a>) - AddressOf can be used in Expr.Call (was an error) - calls containing AddressOf can be rebuilt using RebuildShapeCombination
1 parent 0095fde commit e5762fd

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

src/fsharp/FSharp.Core/quotations.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,8 @@ module Patterns =
643643
| WhileLoopOp,_
644644
| VarSetOp,_
645645
| AddressSetOp,_ -> typeof<Unit>
646-
| AddressOfOp,_ -> raise <| System.InvalidOperationException (SR.GetString(SR.QcannotTakeAddress))
647-
| (QuoteOp _ | SequentialOp | TryWithOp | TryFinallyOp | IfThenElseOp | AppOp),_ -> failwith "unreachable"
646+
| AddressOfOp,[expr]-> (typeOf expr).MakeByRefType()
647+
| (AddressOfOp | QuoteOp _ | SequentialOp | TryWithOp | TryFinallyOp | IfThenElseOp | AppOp),_ -> failwith "unreachable"
648648

649649

650650
//--------------------------------------------------------------------------

tests/fsharp/core/quotes/test.fsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,28 @@ module TypedTest = begin
439439
test "check Mutate 1" (<@ let mutable x = 0 in x <- 1 @> |> (function Let(v,Int32 0, VarSet(v2,Int32 1)) when v = v2 -> true | _ -> false))
440440

441441
let q = <@ let mutable x = 0 in x <- 1 @>
442+
443+
let rec getMethod (e : Expr) =
444+
match e with
445+
| Call(None, mi, _) -> mi
446+
| Let(_,_,m) -> getMethod m
447+
| Lambdas(_, e) -> getMethod e
448+
| _ -> failwithf "not a lambda: %A" e
449+
450+
let increment (r : byref<int>) = r <- r + 1
451+
let incrementMeth = getMethod <@ let mutable a = 10 in increment(&a) @>
452+
453+
let rec rebuild (e : Expr) =
454+
match e with
455+
| ExprShape.ShapeLambda(v,b) -> Expr.Lambda(v, rebuild b)
456+
| ExprShape.ShapeVar(v) -> Expr.Var v
457+
| ExprShape.ShapeCombination(o, args) -> ExprShape.RebuildShapeCombination(o, args |> List.map rebuild)
458+
459+
test "check AddressOf in call" (try let v = Var("a", typeof<int>, true) in Expr.Let(v, Expr.Value 10, Expr.Call(incrementMeth, [Expr.AddressOf(Expr.Var v)])) |> ignore; true with _ -> false)
460+
test "check AddressOf rebuild" (try rebuild <@ let mutable a = 10 in increment(&a) @> |> ignore; true with _ -> false)
461+
test "check AddressOf argument" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_)])) -> true | _ -> false)
462+
test "check AddressOf type" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_) as e])) -> (try e.Type = typeof<int>.MakeByRefType() with _ -> false) | _ -> false)
463+
442464

443465
// Test basic expression splicing
444466
let f8383 (x:int) (y:string) = 0

0 commit comments

Comments
 (0)