# Good line numbers in macro expansions

**URL:** <https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425>\
**Category:** General Usage\
**Created:** [December 11, 2023, 10:30am UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425 "2023-12-11T10:30:46Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [December 11, 2023, 10:30am UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/1 "2023-12-11T10:30:46Z")

</div>

My macros often have poor line numbers. For instance, given this simple macro,

```julia
macro add_hi(def)
       @capture(def, function f_(args__) body__ end)
       esc(:(function $f($(args...)) println(hi); $body end))
end

```

at the REPL:

```julia
julia> @add_hi function g() 2+2 end
g (generic function with 1 method)

julia> methods(g)
# 1 method for generic function "g" from Main:
 [1] g()
     @ ~/Utils/src/Utils.jl:1559

```

Clearly, the function was defined at the REPL, not in Utils.jl. The culprit is the usage of code quotation, that peppered line numbers from Utils.jl all over the place.

```julia
julia> @macroexpand @add_hi function g() 2+2 end
:(function g()
      #= /Utils/src/Utils.jl:1559 =#
      #= /Utils/src/Utils.jl:1559 =#
      println(hi)
      #= /Utils/src/Utils.jl:1559 =#
      Any[:(2 + 2)]
  end)

```

I kinda wish it didn’t do that? I’ve had some limited success using `MacroTools.@q` and ` __source__ `, but sometimes it just doesn’t work. In particular, for a macro like

```julia
macro add_noinline(def)
    esc(:(@noinline $def))
end

```

the macroexpansion becomes

```julia
julia> @macroexpand1 @add_hi2 f(x) = 3
:(#= Utils.jl:1565 =# @noinline f(x) = begin
              #= REPL[16]:1 =#
              3
          end)

```

so the ` __source__ ` passed to `@noinline` is again not what I want; I’d like it to be the REPL of course. And I can’t seem to be able to get it to be REPL without painfully building the `Expr(:macrocall, ...)` expression.

Incidentally, looking at macro code from Base, like `@noinline`, I see that Base doesn’t use code quoting! Is code quoting basically broken for line numbering? How do people deal with these issues?

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [December 24, 2023, 9:56pm UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/2 "2023-12-24T21:56:07Z")

</div>

I found a solution, proposed in this PR: [Define @qq by cstjean · Pull Request #200 · FluxML/MacroTools.jl · GitHub](https://github.com/FluxML/MacroTools.jl/pull/200). Reviews welcome.

Incidentally, I also found `Meta.replace_sourceloc!`, but A) it doesn’t preserve the line numbers of interpolated expressions, and B) it doesn’t seem to work.

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [December 24, 2023, 10:13pm UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/3 "2023-12-24T22:13:48Z")

</div>

Your example uses `@capture`. Where is this macro defined?

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [December 24, 2023, 10:45pm UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/4 "2023-12-24T22:45:31Z")

</div>

It comes from MacroTools.jl:

> **[Pattern Matching · MacroTools](http://fluxml.ai/MacroTools.jl/dev/pattern-matching/)**
>
> Documentation for MacroTools.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 25, 2023, 12:02am UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/5 "2023-12-25T00:02:08Z")

</div>

The link is dead so I can’t tell if `add_hi` is defined in a `Utils.jl` file, but if it is, then a line number at the macro site would make some sense in the general case because the `add_hi` macro is what pieces together the evaluated method expression. In an extreme case of a macro with 0 arguments that returns a fixed method expression, the call site gives no information about the method. It’s just that in this case, you pass in a nearly identical method expression that would be more informative. Maybe it would be better to report call sites generally because we could at least search for the macro afterward, which is not possible the other way around.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [December 25, 2023, 1:37am UTC](https://discourse.julialang.org/t/good-line-numbers-in-macro-expansions/107425/6 "2023-12-25T01:37:24Z")

</div>

> [@Benny](#):
>
> then a line number at the macro site would make some sense in the general case because the `add_hi` macro is what pieces together the evaluated method expression.

Yeah, I don’t deny that pointing to the macro expansion code makes sense in some cases. In the case of a macro invocation inside of a function definition, then the call stack usually provides the surrounding function call, so it’s fine for the macro expansion to point to the macro definition. But for top-level definitions like `@defequation ...` , `@kwdef ...` or `@with_parameters ...` etc defining a method like `equation_value(...) = ...` or a type, having `equation_value(::...)` in the stacktrace pointing at the `macro def_equation()` code is rarely helpful.

> [@Benny](#):
>
> Maybe it would be better to report call sites generally because we could at least search for the macro afterward, which is not possible the other way around.

Yes, exactly.

I get why `quote` behaves the way it does. It’s already magical enough as it is, so changing it to implicitly use ` __source__ ` like the proposed `@qq` does, that might be too much.
