From 742eb134e529323ba2a67d3ed01b85895abe4dfb Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 6 Jun 2024 05:27:44 +0000 Subject: [PATCH] lowering: Recognize argument destructuring inside macro hygiene Fixes #54701 --- src/macroexpand.scm | 22 +++++++++------------- test/syntax.jl | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 74d47aec45479..f67145317dc7a 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -229,30 +229,26 @@ lst))) ;; get the name from a function formal argument expression, allowing `(escape x)` -(define (try-arg-name v) - (cond ((symbol? v) (list v)) +(define (try-arg-name v (escaped #f)) + (cond ((symbol? v) (if escaped '() (list v))) ((atom? v) '()) (else (case (car v) - ((|::|) (if (length= v 2) '() (try-arg-name (cadr v)))) - ((... kw =) (try-arg-name (cadr v))) - ((escape) (list v)) - ((hygienic-scope) (try-arg-name (cadr v))) + ((|::|) (if (length= v 2) '() (try-arg-name (cadr v) escaped))) + ((... kw =) (try-arg-name (cadr v) escaped)) + ((escape) (if escaped (list (cadr v)) '())) + ((hygienic-scope) (try-arg-name (cadr v) escaped)) + ((tuple) (apply nconc (map (lambda (e) (try-arg-name e escaped)) (cdr v)))) ((meta) ;; allow certain per-argument annotations (if (nospecialize-meta? v #t) - (try-arg-name (caddr v)) + (try-arg-name (caddr v) escaped) '())) (else '()))))) ;; get names from a formal argument list, specifying whether to include escaped ones (define (safe-arg-names lst (escaped #f)) (apply nconc - (map (lambda (v) - (let ((vv (try-arg-name v))) - (if (eq? escaped (and (pair? vv) (pair? (car vv)) (eq? (caar vv) 'escape))) - (if escaped (list (cadar vv)) vv) - '()))) - lst))) + (map (lambda (v) (try-arg-name v escaped)) lst))) ;; arg names, looking only at positional args (define (safe-llist-positional-args lst (escaped #f)) diff --git a/test/syntax.jl b/test/syntax.jl index bfe47abffe6ff..7f049fa5a9500 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -3683,3 +3683,19 @@ end # Issue #53729 - Lowering recursion into Expr(:toplevel) @test eval(Expr(:let, Expr(:block), Expr(:block, Expr(:toplevel, :(f53729(x) = x)), :(x=1)))) == 1 @test f53729(2) == 2 + +# Issue #54701 - Macro hygiene of argument destructuring +macro makef54701() + quote + call(f) = f((1, 2)) + function $(esc(:f54701))() + call() do (a54701, b54701) + return a54701+b54701 + end + end + end +end +@makef54701 +@test f54701() == 3 +@test !@isdefined(a54701) +@test !@isdefined(b54701)