Namedtuple destructuring in macro fails roughly due to macro hygiene (since gensym goes eagerly)

Here is the situation

f(x) = (; a=2x, b=x*x)

macro ma(x)
    quote
        f($x)
    end
end

macro mb(x)
    quote
        nt = f($x)
        (; nt.a, nt.b)
    end
end

macro mc(x)
    quote
        (; a,b) = f($x)
    end
end

while ma and mb behaves kindly IMO

using Test
@test (@ma 1) == (; a=2, b=1) # ok
@test (@mb 1) == (; a=2, b=1) # ok
@test (@mc 1) == (; a=2, b=1) # bug

mc errors immediately (at the lowerer ?)
There may be some unification issues in regard to non-escaped / re-gensymd a,b
but we should be able to destructure first IMO .
Comment advices welcome

macro md(x)
    nt = :((; a, b))
    quote
        $(esc(nt)) = f($x)
    end
end
julia> @macroexpand @mc 1
quote
    #= Untitled-1:67 =#
    (; a = Main.a, b = Main.b) = Main.f(1)
end

julia> @macroexpand @md 1
quote
    #= Untitled-1:74 =#
    (; a, b) = Main.f(1)
end

Yes this seems kind of buggy/ill-defined to me. If the symbols a and b are not escaped, I would expect the output to be something like (; var"#1#a", var"#2#b") = ... because the new variables should have gensymmed names. Instead these a = Main.a assignments are created, which of course cannot work.

But because gensymmed names would not access the correct variables from the destructured object, this also cannot work.

Interesting case because property access and variable creation are intertwined in this syntax, and while property symbols are not subject to macro hygiene, variable creation is, so that is kind of incompatible.

IMO the issues come from the fact the lowerer does too few passes eg. 5 passes only, first one is ~ 2.5KLOC of femtolisp. It’s a monolithic (and archaic) code nowadays.
There should be many more passes (compare to go, rust, fsharp, no surprise, they all go this way).
This will be possible to stage those kinds of issues correctly
JuliaSyntax will be important at some point, (and countdown has begun a couple of years ago)