From eefb6618dfe8fc7ff8af643b8635c80b908aa674 Mon Sep 17 00:00:00 2001 From: Tor Erlend Fjelde Date: Sat, 31 Jul 2021 10:52:32 +0100 Subject: [PATCH 1/2] use gensym for lens in setmacro --- src/sugar.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sugar.jl b/src/sugar.jl index 11a812f..377fa06 100644 --- a/src/sugar.jl +++ b/src/sugar.jl @@ -174,19 +174,20 @@ function setmacro(lenstransform, ex::Expr; overwrite::Bool=false) @assert length(ex.args) == 2 ref, val = ex.args obj, lens = parse_obj_lens(ref) + lenssym = gensym(:lens) dst = overwrite ? obj : gensym("_") val = esc(val) ret = if ex.head == :(=) quote - lens = ($lenstransform)($lens) - $dst = $set($obj, lens, $val) + $lenssym = ($lenstransform)($lens) + $dst = $set($obj, $lenssym, $val) end else op = get_update_op(ex.head) f = :($_UpdateOp($op,$val)) quote - lens = ($lenstransform)($lens) - $dst = $modify($f, $obj, lens) + $lenssym = ($lenstransform)($lens) + $dst = $modify($f, $obj, $lenssym) end end ret From cb1d984ae3b39d1c3e52cf92beed40a26a1b04b0 Mon Sep 17 00:00:00 2001 From: Tor Erlend Fjelde Date: Sun, 1 Aug 2021 05:34:47 +0100 Subject: [PATCH 2/2] added test for type inference with multiple usage of setmacro within the same macro --- test/test_setmacro.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/test_setmacro.jl b/test/test_setmacro.jl index bc48fa3..77c9bb0 100644 --- a/test/test_setmacro.jl +++ b/test/test_setmacro.jl @@ -46,5 +46,31 @@ using StaticNumbers @test m3 === @SMatrix[1 0; 0 0] end +function test_all_inferrable(f, argtypes) + typed = first(code_typed(f, argtypes)) + code = typed.first + @test all(T -> !(T isa UnionAll || T === Any), code.slottypes) +end + +# Example of macro that caused inference issues before. +macro test_macro(expr) + quote + function f($(esc(:x))) + $(Setfield.setmacro(identity, expr, overwrite=true)) + $(Setfield.setmacro(identity, expr, overwrite=true)) + $(Setfield.setmacro(identity, expr, overwrite=true)) + $(Setfield.setmacro(identity, expr, overwrite=true)) + $(Setfield.setmacro(identity, expr, overwrite=true)) + return $(esc(:x)) + end + end +end + +@testset "setmacro multiple usage" begin + let f = @test_macro(x[end] = 1) + test_all_inferrable(f, (Vector{Float64}, )) + end +end + end#module