Skip to content

Test: add @test_hygienic macro for checking macro hygiene#61500

Draft
IanButterworth wants to merge 1 commit intoJuliaLang:masterfrom
IanButterworth:ib/test_hygienic
Draft

Test: add @test_hygienic macro for checking macro hygiene#61500
IanButterworth wants to merge 1 commit intoJuliaLang:masterfrom
IanButterworth:ib/test_hygienic

Conversation

@IanButterworth
Copy link
Copy Markdown
Member

@IanButterworth IanButterworth commented Apr 5, 2026

Draft claude-generated proposal (opening as a proof of concept), but it seems to work in the test cases, and it discovered three hygiene issues:

Passed:

  • @time, @elapsed, @allocated, @allocations, @timed, @assert, @show, @info, @warn, @error, @debug, @lock, @enum, @inline, @noinline, @boundscheck, @inbounds, @label, @goto, @static, @eval, @isdefined, @invoke, @invokelatest, @view, @views, @async, @sync, @atomic, @ccall, @kwdef, @deprecate, @task, @threadcall, @fastmath, @polly, @simd, @test, @test_throws, @test_broken, @test_skip, @test_warn, @test_nowarn, @test_logs, @testset, @logmsg, @sprintf

Failed:

i.e.

julia> onethread = "hello";

julia> Threads.@threads for i in 1:2
           println(onethread)
       end
false
false

julia> @test_hygienic Threads.@threads for i in 1:2
       i
       end
Test Failed at REPL[7]:1
  Expression: #= REPL[7]:1 =# Threads.@threads for i = 1:2
        #= REPL[7]:2 =#
        i
        #= REPL[7]:3 =#
    end
  Unhygienic names: onethread
ERROR: There was an error during testing

The implementation may be easier once JuliaLowering lands?

Developed with Claude:


Add a new macro @test_hygienic that verifies a macro expansion does not contain unhygienic names — either leaked bindings or captured variable references. After macroexpand, any plain Symbol (no gensym #) that appears outside hygienic-scope blocks and wasn't in the original user expression is flagged as unhygienic.

The implementation correctly handles compiler special forms (ccall, cglobal), qualified names (Expr(:.)), compiler directives (inbounds, boundscheck), keyword argument names, and QuoteNodes.

Supports broken and skip keyword arguments consistent with other Test macros.

Add a new macro `@test_hygienic` that verifies a macro expansion does not
contain unhygienic names — either leaked bindings or captured variable
references. After macroexpand, any plain Symbol (no gensym `#`) that appears
outside `hygienic-scope` blocks and wasn't in the original user expression
is flagged as unhygienic.

The implementation correctly handles compiler special forms (ccall, cglobal),
qualified names (Expr(:.)), compiler directives (inbounds, boundscheck),
keyword argument names, and QuoteNodes.

Supports `broken` and `skip` keyword arguments consistent with other Test
macros.

Co-Authored-By: Claude <claude@users.noreply.github.com>
@IanButterworth IanButterworth added testsystem The unit testing framework and Test stdlib macros @macros labels Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macros @macros testsystem The unit testing framework and Test stdlib

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant