Should macros observe mutable global state, e.g. method tables?

My package Convertible.jl currently uses generated functions to enable multi-step type conversions at runtime. The problem is that I achieved this by calling methods within the generated function body, i.e. I am observing mutable global state which is considered harmful.

I am now in the process of rewriting the package and want to shift the generation of the missing intermediate convert methods to compile-time by using a macro. The question is now whether this actually solves the problem? Can macros safely observe method tables?

Anybody? :frowning:

I don’t know enough about he internals or your code to say how exactly it would fail, but since macros should just perform syntax transformations, you are probably better off just rewriting the code a different way.

Perhaps if you gave a bit of context, or an MWE that would illustrate the problem you are trying to solve, you could get an alternative solution.

Maybe, but it breaks my expectations as a user, and it will also break Revise.jl

Couldn’t you do essentially the same with an explicit declaration of convertible types?

@convertible A -> B -> D -> C -> A

or, if you want to avoid the redundancy, read the relationships from the convert statements.

@convertible begin
Base.convert(::Type{B}, a::A) = B(a.val+1)
Base.convert(::Type{D}, a::A) = D(a.val+1)
Base.convert(::Type{C}, b::B) = C(b.val+1)
Base.convert(::Type{A}, c::C) = A(c.val-2)
end

In both cases, you can get rid of the @convert macro.

What makes it complicated is that I want the user to be able to add new types to the graph at runtime. Maybe the whole thing is premature optimization. I must confess I have not checked whether looking up the intermediate conversion dynamically would actually perform much worse.