JuliaDebug / JuliaDebug/Cthulhu.jl

TypedSyntax: `val = f(@inbounds A[j])` maps the call to the assignment target `val`

Open
#710 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
709
Forks
46
Avg merge
1d 13h
Merged PRs (30d)
2

Description

In map_ssas_to_source, the statement for a call whose result is assigned to a variable is attributed to the variable's identifier rather than to the call node, when the call's argument is a macro call. The shape is Base.map!:

function mapsize!(f::F, dest, A) where F
    for j in eachindex(A)
        val = f(@inbounds A[j])
        @inbounds dest[j] = val
    end
    dest
end

Repro (TypedSyntax 1.5.4, Julia 1.13.0):

using TypedSyntax, JuliaSyntax
using JuliaSyntax: kind, sourcetext
A = [rand(2,2) for _ in 1:2, _ in 1:2]; dest = Matrix{Tuple{Int,Int}}(undef, 2, 2)
mapsize!(size, dest, A)
mi = only(Base.method_instances(mapsize!, (typeof(size), typeof(dest), typeof(A)), 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)
    isempty(nodes) && continue
    println(i, "  ", src.code[i], " -> ", [string(kind(n), " `", sourcetext(n), "`") for n in nodes])
end

Output (excerpt):

 13  _7 = Base.getindex(_4, %12)   -> ["ref `A[j]`"]
 15  _7                            -> ["Identifier `val`"]
 16  _9 = (_2)(%15)                -> ["Identifier `val`"]      # the call `f(@inbounds A[j])`
 18  _9                            -> ["Identifier `val`"]

Statement 16 is the call f(@inbounds A[j]); it is mapped to the Identifier val (the assignment's LHS) and the call node gets nothing. The A[j] read maps correctly to the ref.

Consequence in Cthulhu: find_callsites(…, true) returns each callsite's source node from this mapping, so the size callsite is located at val rather than at the call, and the source view annotates val with the call's type while the call itself carries none. Seen in Base.map!; without @inbounds in argument position the call maps to the call node, so the macro call appears to be the trigger.


🤖 Filed using Claude Code. The reproduction was run locally on the stated versions and the output is quoted verbatim.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with map_ssas_to_source and reproduce the mapping using the Julia code in the issue, focusing on the f(@inbounds A[j]) case. Trace how find_callsites(…, true) consumes the mappings and compare it with the case without @inbounds. Done means the call maps to the call node rather than the assignment target val, while the A[j] mapping remains correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
66/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.