Skip to content

Commit

Permalink
macroexpand: handle const/atomic struct fields correctly (#51980)
Browse files Browse the repository at this point in the history
Fixes #51899
  • Loading branch information
Pangoraw authored Nov 2, 2023
1 parent 54996ca commit 924aac9
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
28 changes: 17 additions & 11 deletions src/macroexpand.scm
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,22 @@

(define (reescape ux x)
(if (and (pair? x) (eq? (car x) 'escape))
(reescape '(escape ,ux) (cadr x)))
ux)
(reescape `(escape ,ux) (cadr x))
ux))

;; type has special behavior: identifiers inside are
;; field names, not expressions.
(define (resolve-struct-field-expansion x env m parent-scope inarg)
(let ((ux (unescape x)))
(cond
((atom? ux) ux)
((and (pair? ux) (eq? (car ux) '|::|))
`(|::| ,(unescape (cadr ux))
,(resolve-expansion-vars- (reescape (caddr ux) x) env m parent-scope inarg)))
((and (pair? ux) (memq (car ux) '(const atomic)))
`(,(car ux) ,(resolve-struct-field-expansion (reescape (cadr ux) x) env m parent-scope inarg)))
(else
(resolve-expansion-vars-with-new-env x env m parent-scope inarg)))))

(define (resolve-expansion-vars- e env m parent-scope inarg)
(cond ((or (eq? e 'begin) (eq? e 'end) (eq? e 'ccall) (eq? e 'cglobal) (underscore-symbol? e))
Expand Down Expand Up @@ -377,16 +391,8 @@
((symbolicgoto) e)
((struct)
`(struct ,(cadr e) ,(resolve-expansion-vars- (caddr e) env m parent-scope inarg)
;; type has special behavior: identifiers inside are
;; field names, not expressions.
,(map (lambda (x)
(let ((ux (unescape x)))
(cond ((atom? ux) ux)
((and (pair? ux) (eq? (car ux) '|::|))
`(|::| ,(unescape (cadr ux))
,(resolve-expansion-vars- (reescape (caddr ux) x) env m parent-scope inarg)))
(else
(resolve-expansion-vars-with-new-env x env m parent-scope inarg)))))
(resolve-struct-field-expansion x env m parent-scope inarg))
(cadddr e))))

((parameters)
Expand Down
37 changes: 37 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,43 @@ end
@test B28593.var.name === :S
@test C28593.var.name === :S

# issue #51899
macro struct_macro_51899()
quote
mutable struct Struct51899
const const_field
const const_field_with_type::Int
$(esc(Expr(:const, :(escaped_const_field::MyType))))
@atomic atomic_field
@atomic atomic_field_with_type::Int
end
end
end

let ex = @macroexpand @struct_macro_51899()
const_field, const_field_with_type, escaped_const_field,
atomic_field, atomic_field_with_type = filter(x -> isa(x, Expr), ex.args[end].args[end].args)
@test Meta.isexpr(const_field, :const)
@test const_field.args[1] === :const_field

@test Meta.isexpr(const_field_with_type, :const)
@test Meta.isexpr(const_field_with_type.args[1], :(::))
@test const_field_with_type.args[1].args[1] === :const_field_with_type
@test const_field_with_type.args[1].args[2] == GlobalRef(@__MODULE__, :Int)

@test Meta.isexpr(escaped_const_field, :const)
@test Meta.isexpr(const_field_with_type.args[1], :(::))
@test escaped_const_field.args[1].args[1] === :escaped_const_field
@test escaped_const_field.args[1].args[2] === :MyType

@test Meta.isexpr(atomic_field, :atomic)
@test atomic_field.args[1] === :atomic_field

@test Meta.isexpr(atomic_field_with_type, :atomic)
@test atomic_field_with_type.args[1].args[1] === :atomic_field_with_type
@test atomic_field_with_type.args[1].args[2] == GlobalRef(@__MODULE__, :Int)
end

# issue #25955
macro noeffect25955(e)
return e
Expand Down

0 comments on commit 924aac9

Please sign in to comment.