JuliaDebug / JuliaDebug/Cthulhu.jl
TypedSyntax: a macro call inside an expression leaves the enclosing calls unmapped
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 709
- Forks
- 46
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 2
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the standalone reproduction with TypedSyntax 1.5.4 and Julia 1.13.0, starting at TypedSyntax.tsn_and_mappings and the printed mappings. Compare the first and second expression and related issue #710; done means source-spelled enclosing calls such as maximum, <, and 10m receive source nodes while macro-expansion nodes may remain unmapped.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100