# Updating the location of a method definition

**URL:** <https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 24, 2021, 11:26pm UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247 "2021-07-24T23:26:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [July 24, 2021, 11:26pm UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/1 "2021-07-24T23:26:31Z")

</div>

Is there a good way to change where Julia thinks a method definition is located (file and line number)? I got halfway there with this:

```julia
m = first(methods(MyModule.mymethod))
m.file = Symbol("/path/to/real/file")
m.line = real_line

```

(I can find the correct method definition when `methods` returns more than one, in this example `first` is just a simplification.)

This works well enough for uses internally reliant on `methods` for file and line information, but does not work for displayed stack traces. Stack traces still show the old location of the method definition.

The following fails because `LineInfoNode` is an immutable struct:

```julia
m = first(methods(MyModule.mymethod))
Base.uncompressed_ast(m).linetable[1].file = Symbol("/path/to/real/file")

```

Is there any way to force Julia to see a different location for a redefined function?

Context: I wrote a [Julia IDE for Emacs](https://discourse.julialang.org/t/ann-julia-snail-an-emacs-development-environment-first-beta-release/35786). One of its features allows redefinition of a function without reloading an entire file. This messes up cross-referencing (which I figured out how to fix) and stack traces (which I have not). Exact bug: [https://github.com/gcv/julia-snail/issues/28](https://github.com/gcv/julia-snail/issues/28).

---

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [July 31, 2021, 11:47pm UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/2 "2021-07-31T23:47:31Z")

</div>

Pinging @tim.holy, @longemen3000, and @tkf who have helped me with questions about Julia internals in the past. 🙃

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [August 1, 2021, 12:45am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/3 "2021-08-01T00:45:21Z")

</div>

If you control how the code is evaluated, maybe you can just use `task_local_storage()[:SOURCE_PATH]`? For example, see how `Distributed.@everywhere` pass around “current file context”:

[https://github.com/JuliaLang/julia/blob/bdacfa21ef7d9657be0ff3220947ceca92a340a1/stdlib/Distributed/src/macros.jl#L205](https://github.com/JuliaLang/julia/blob/bdacfa21ef7d9657be0ff3220947ceca92a340a1/stdlib/Distributed/src/macros.jl#L205)

It’s not enough to make line positions correct, though. For this, I think it’s simpler to parse the code and change the `LineNumberNode` yourself before `eval`. Or, maybe even simpler solution to add empty lines in the temp file.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [August 1, 2021, 8:34am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/4 "2021-08-01T08:34:33Z")

</div>

Load CodeTracking and Revise and then use `whereis`.

---

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [August 3, 2021, 5:22am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/5 "2021-08-03T05:22:17Z")

</div>

Changing `LineNumberNode`s worked perfectly. Thank you.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [August 4, 2021, 11:36am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/6 "2021-08-04T11:36:09Z")

</div>

The problem here is imagine inserting a blank line at the top of a file with 1000 methods. Do you really want to re-`eval` all the methods just to update the line numbers? That’s going to force a lot of invalidation and recompilation.

Much better to use the CodeTracking + Revise strategy, which is completely free of recompilation.

---

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [August 4, 2021, 11:42pm UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/7 "2021-08-04T23:42:27Z")

</div>

@tim.holy: Indeed, but Snail does not attempt to update all affected line numbers. It only changes `LineNumberNode` instances for the code being directly evaluated (a top-level form or selected region) before calling `eval` on it. While this messes up line numbering for all surrounding code, this tends to happen with SLIME and CIDER equivalent commands also (or at least it used to). Re-evaluating the buffer with `julia-snail-send-buffer-file` will fix everything (albeit with invalidation). I consider this acceptable for this type of tool.

That said, it’s great that a Revise-oriented workflow won’t have any of these drawbacks. Snail users are welcome to use Revise, avoid `julia-snail-send-region` or `julia-snail-send-top-level-form`, and still enjoy Snail’s autocompletion and cross-referencing features. But, I just tested a Revise-oriented workflow, and ran into an interesting problem.

My test involved just making a simple Julia source file with a sample function `samplefun`. Then I called `Revise.includet` on the source file. Revise started working on that file, as expected. But, I found that calling `CodeTracking.whereis(@which samplefun())` gives me correct output _only_ when called from the REPL, and _not_ when called through Snail’s network interface. If I move `samplefun` around by adding blank lines, then `CodeTracking.whereis` returns stale locations when called through Snail’s network interface, but correct locations when called from the REPL.

Using `functionloc` on a method to determine its location exhibits the same behavior: correct from the REPL, wrong when invoked outside the REPL.

Do you know anything about this? Does Julia or Revise maintain some kind of internal source location cache which is invalidated only when these introspection functions are called from the REPL?

If you use Emacs, I can talk you through reproducing the behavior pretty easily. If you don’t use Emacs, it’ll take a bit more work, but I can write a handful of `netcat` commands that use Snail’s network backend to demonstrate the behavior.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [August 5, 2021, 11:53am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/8 "2021-08-05T11:53:37Z")

</div>

> [@gcv](#):
>
> I found that calling `CodeTracking.whereis(@which samplefun())` gives me correct output _only_ when called from the REPL, and _not_ when called through Snail’s network interface.

That’s because Revise modifies the REPL to call `revise()` before evaluating what the user types.

---

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [August 6, 2021, 6:28am UTC](https://discourse.julialang.org/t/updating-the-location-of-a-method-definition/65247/9 "2021-08-06T06:28:58Z")

</div>

Perfect. Thanks! I now have Revise compatibility working in Snail as expected.
