From 38afa5d8039edf45114df00e8fc7a7a9b8147e34 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 16 Oct 2020 14:11:42 -0400 Subject: [PATCH] fix #37540, interpolation in quoted exprs returned from macros (#37573) --- NEWS.md | 3 +++ base/essentials.jl | 4 ++-- src/ast.c | 6 ------ stdlib/Distributed/src/macros.jl | 2 +- test/syntax.jl | 9 +++++++++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index b3da572b13bf4..c37415f0206e3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,9 @@ New language features Language changes ---------------- +* Macros that return `:quote` expressions (e.g. via `Expr(:quote, ...)`) were previously + able to work without escaping (`esc(...)`) their output when needed. This has been + corrected, and now `esc` must be used in these macros as it is in other macros ([#37540]). * The `-->` operator now lowers to a `:call` expression, so it can be defined as a function like other operators. The dotted version `.-->` is now parsed as well. For backwards compatibility, `-->` still parses using its own expression head diff --git a/base/essentials.jl b/base/essentials.jl index 1158fa7483d73..31c746bab5d28 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -216,10 +216,10 @@ Evaluate an expression with values interpolated into it using `eval`. If two arguments are provided, the first is the module to evaluate in. """ macro eval(ex) - :(Core.eval($__module__, $(Expr(:quote,ex)))) + return Expr(:escape, Expr(:call, GlobalRef(Core, :eval), __module__, Expr(:quote, ex))) end macro eval(mod, ex) - :(Core.eval($(esc(mod)), $(Expr(:quote,ex)))) + return Expr(:escape, Expr(:call, GlobalRef(Core, :eval), mod, Expr(:quote, ex))) end argtail(x, rest...) = rest diff --git a/src/ast.c b/src/ast.c index f3ae26ebee125..9f4ac6f934d9d 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1028,12 +1028,6 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str if (e->head == quote_sym && jl_expr_nargs(e) == 1) { expr = jl_call_scm_on_ast("julia-bq-macro", jl_exprarg(e, 0), inmodule); JL_GC_PUSH1(&expr); - if (macroctx) { - // in a macro, `quote` also implies `escape` - jl_expr_t *e2 = jl_exprn(escape_sym, 1); - jl_array_ptr_set(e2->args, 0, expr); - expr = (jl_value_t*)e2; - } expr = jl_expand_macros(expr, inmodule, macroctx, onelevel, world); JL_GC_POP(); return expr; diff --git a/stdlib/Distributed/src/macros.jl b/stdlib/Distributed/src/macros.jl index 7e988bc173a91..b53890017d4de 100644 --- a/stdlib/Distributed/src/macros.jl +++ b/stdlib/Distributed/src/macros.jl @@ -202,7 +202,7 @@ macro everywhere(procs, ex) imps = extract_imports(ex) return quote $(isempty(imps) ? nothing : Expr(:toplevel, imps...)) # run imports locally first - let ex = Expr(:toplevel, :(task_local_storage()[:SOURCE_PATH] = $(get(task_local_storage(), :SOURCE_PATH, nothing))), $(Expr(:quote, ex))), + let ex = Expr(:toplevel, :(task_local_storage()[:SOURCE_PATH] = $(get(task_local_storage(), :SOURCE_PATH, nothing))), $(esc(Expr(:quote, ex)))), procs = $(esc(procs)) remotecall_eval(Main, procs, ex) end diff --git a/test/syntax.jl b/test/syntax.jl index 6af0b139026d0..1abe8fa72dbfe 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2365,6 +2365,15 @@ end # issue #37656 @test :(if true 'a' else 1 end) == Expr(:if, true, quote 'a' end, quote 1 end) +# issue #37540 +macro m37540() + quote + x = 1 + :($x) + end +end +@test @m37540() == 1 + # issue #37890 struct A37890{A, B} a