`definition(String, m)` returns `nothing` for a closure when the enclosing function has arguments

未關閉
#162 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

評估

難度
3/5
預估耗時
1-2 天
新手友好度
75/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
julia
領域
devtools

研究方向

Start in src/utils.jl at is_func_expr(ex, meth::Method), then run repro.jl with include on the stated Julia and CodeTracking versions to reproduce the parameterized-closure failures. Trace the backward scan, gensym name matching, and argument comparison. Done means definition(String, m) finds the source for all arrow and do-block closures, including those inside functions with parameters.

由索引模型根據 Issue 內容生成。

描述

definition(String, m) for a closure's method (a do block or a -> inside a call) returns nothing whenever the function it is written inside has parameters. With no parameters it works. The distinction is the enclosing function's argument list, not the closure form or whether the enclosing function is short- or long-form.

Repro (repro.jl, run with include; Julia 1.13.0, CodeTracking 3.0.2, no Revise needed):

using CodeTracking
returnit(f) = f
# short form, enclosing has no args / has args; arrow / do
s_noargs_arrow()  = returnit(y -> y + 1)
s_args_arrow(x)   = returnit(y -> y + x)
s_noargs_do()     = returnit() do y
    y + 1
end
s_args_do(x)      = returnit() do y
    y + x
end
# long form
function l_noargs_arrow()
    return returnit(y -> y + 1)
end
function l_args_arrow(x)
    return returnit(y -> y + x)
end
function l_noargs_do()
    return returnit() do y
        y + 1
    end
end
function l_args_do(x)
    return returnit() do y
        y + x
    end
end
for (make, args) in ((s_noargs_arrow, ()), (s_args_arrow, (1,)), (s_noargs_do, ()), (s_args_do, (1,)),
                     (l_noargs_arrow, ()), (l_args_arrow, (1,)), (l_noargs_do, ()), (l_args_do, (1,)))
    m = only(methods(make(args...)))
    d = CodeTracking.definition(String, m)
    println(rpad(string(make), 16), " closure at line ", lpad(m.line, 2), "  -> ", d === nothing ? "nothing" : "found (starts at line $(d[2]))")
end

Output:

s_noargs_arrow   closure at line  4  -> found (starts at line 4)
s_args_arrow     closure at line  5  -> nothing
s_noargs_do      closure at line  7  -> found (starts at line 5)
s_args_do        closure at line 10  -> nothing
l_noargs_arrow   closure at line 14  -> found (starts at line 12)
l_args_arrow     closure at line 17  -> nothing
l_noargs_do      closure at line 21  -> found (starts at line 18)
l_args_do        closure at line 26  -> nothing

Where it happens — is_func_expr(ex, meth::Method) in src/utils.jl:

  • The backward scan from the closure's line reaches the enclosing definition, and the name check accepts it on purpose: fname === strip_gensym(meth.name) maps #l_args_do##0 to l_args_do. So far so good — the enclosing definition is the text that contains the closure.
  • It then "matches the argnames": exargs are the enclosing definition's parameters (x), zipped against Base.method_argnames(meth)[2:end], which are the closure's (y). x !== y → return false. When the enclosing function has no parameters the zip is empty and the check passes, which is why the noargs rows succeed.

So for a gensym-named method the argument check is comparing two different functions' parameter lists. A closure whose parameter names happen to coincide positionally with the enclosing function's would pass by accident.

Suggested fix: when meth.name is a gensym and the expression matched via strip_gensym, skip the argname comparison (the enclosing definition is the right answer, and the caller has meth.line to find the lambda inside it), or locate the ->/do node within ex and compare its parameters instead.

Downstream effect: TypedSyntax calls definition(String, m) first, so Cthulhu's source view cannot show any closure written inside a function with parameters — e.g. stable_hash_helper(x::Tuple, hash_state, context, ::StructTypes.ArrayType) in StableHashTraits, whose do nested_hash_state block reports couldn't retrieve source of (::var"#stable_hash_helper##4#…")(nested_hash_state). Related earlier reports: #102 (added -> matching), #132 (closed; a lambda returned as data, which is a different case — here the file and line are known and correct).


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

主要語言
Julia
星號
150
分支
12
PR 合併指標
30 天內沒有已合併 PR

環境準備

這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

JuliaDebug/CodeTracking.jl 的其他 Issue

查看 JuliaDebug/CodeTracking.jl 的全部 Issue

相似的 Issue

更多 Julia Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。