When a macro call appears inside an expression, the statements for the enclosing calls on that line — the ones the user wrote, not the macro's expansion — get no source node. Shape from ApproxFunBase's _default_Fun:
struct Coefs; coefficients::Vector{Float64}; end
function macroline(cf::Coefs, bs::Int)
m = maximum(abs, cf.coefficients)
maximum(abs, @view cf.coefficients[bs:end]) < 10m
end
Repro (TypedSyntax 1.5.4, Julia 1.13.0):
using TypedSyntax, JuliaSyntax
using JuliaSyntax: kind, sourcetext
macroline(Coefs(rand(3)), 1)
mi = only(Base.method_instances(macroline, (Coefs, Int), Base.get_world_counter()))
src, rt = TypedSyntax.code_typed1_tsn(mi)
tsn, mappings = TypedSyntax.tsn_and_mappings(mi, src, rt)
for (i, nodes) in enumerate(mappings)
st = src.code[i]
(st isa Core.ReturnNode || st isa Core.GotoIfNot || st isa Core.GotoNode) && continue
println(i, " ", st, " -> ", isempty(nodes) ? "(nothing)" : [string(kind(n), " `", sourcetext(n), "`") for n in nodes])
end
Output:
1 Main.maximum -> Identifier `maximum`
2 Main.abs -> Identifier `abs`
3 Base.getproperty(_2, :coefficients) -> . `cf.coefficients`
4 _5 = (%1)(%2, %3) -> call `maximum(abs, cf.coefficients)`
5 Main.:< -> Identifier `<`
6 Main.maximum -> Identifier `maximum`
7 Main.abs -> Identifier `abs`
8 _4 = Base.getproperty(_2, :coefficients) -> . `cf.coefficients`
9 _4 -> (nothing)
10 Main.:(:) -> (nothing)
11 _4 -> (nothing)
12 (lastindex)(%11) -> (nothing)
13 (%10)(_3, %12) -> (nothing)
14 (view)(%9, %13) -> (nothing)
15 (%6)(%7, %14) -> (nothing)
16 Main.:* -> (nothing)
17 _5 -> (nothing)
18 (%16)(10, %17) -> (nothing)
19 (%5)(%15, %18) -> (nothing)
The first line maps completely. On the second line only the leaf identifiers and cf.coefficients map; the @view expansion (lastindex, :, view) is understandably unmapped, but so are the calls around it that the source spells verbatim — maximum(abs, ...), <, 10m — so the whole expression comes back untyped and none of those callsites can be located in the source.
In the original (maximum(abs, @view cf.coefficients[bs:end]) < 10tol*maxabsc in ApproxFunBase, seen through Cthulhu) the outcome was slightly different: the maximum statement was attributed to the macrocall node itself rather than dropped, so the maximum callsite was located at the @view node. I could not reduce that variant to a standalone repro; the drop above is the reproducible form of the same thing.
Related: #710 (a macro call in argument position sends the enclosing call to the assignment target).
🤖 Filed using Claude Code. The reproduction was run locally on the stated versions and the output is quoted verbatim.
When a macro call appears inside an expression, the statements for the enclosing calls on that line — the ones the user wrote, not the macro's expansion — get no source node. Shape from ApproxFunBase's
_default_Fun:Repro (TypedSyntax 1.5.4, Julia 1.13.0):
Output:
The first line maps completely. On the second line only the leaf identifiers and
cf.coefficientsmap; the@viewexpansion (lastindex,:,view) is understandably unmapped, but so are the calls around it that the source spells verbatim —maximum(abs, ...),<,10m— so the whole expression comes back untyped and none of those callsites can be located in the source.In the original (
maximum(abs, @view cf.coefficients[bs:end]) < 10tol*maxabscin ApproxFunBase, seen through Cthulhu) the outcome was slightly different: themaximumstatement was attributed to themacrocallnode itself rather than dropped, so themaximumcallsite was located at the@viewnode. I could not reduce that variant to a standalone repro; the drop above is the reproducible form of the same thing.Related: #710 (a macro call in argument position sends the enclosing call to the assignment target).
🤖 Filed using Claude Code. The reproduction was run locally on the stated versions and the output is quoted verbatim.