Skip to content

Commit d19bb47

Browse files
authored
Explicitly store a module's location (#55963)
Revise wants to know what file a module's `module` definition is in. Currently it does this by looking at the source location for the implicitly generated `eval` method. This is terrible for two reasons: 1. The method may not exist if the module is a baremodule (which is not particularly common, which is probably why we haven't seen it). 2. The fact that the implicitly generated `eval` method has this location information is an implementation detail that I'd like to get rid of (#55949). This PR adds explicit file/line info to `Module`, so that Revise doesn't have to use the hack anymore.
1 parent 5fc582b commit d19bb47

File tree

6 files changed

+31
-0
lines changed

6 files changed

+31
-0
lines changed

base/reflection.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ function fullname(m::Module)
7676
return (fullname(mp)..., mn)
7777
end
7878

79+
"""
80+
moduleloc(m::Module) -> LineNumberNode
81+
82+
Get the location of the `module` definition.
83+
"""
84+
function moduleloc(m::Module)
85+
line = Ref{Int32}(0)
86+
file = ccall(:jl_module_getloc, Ref{Symbol}, (Any, Ref{Int32}), m, line)
87+
return LineNumberNode(Int(line[]), file)
88+
end
89+
7990
"""
8091
names(x::Module; all::Bool=false, imported::Bool=false, usings::Bool=false) -> Vector{Symbol}
8192

src/jl_exported_funcs.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@
316316
XX(jl_module_name) \
317317
XX(jl_module_names) \
318318
XX(jl_module_parent) \
319+
XX(jl_module_getloc) \
319320
XX(jl_module_public) \
320321
XX(jl_module_public_p) \
321322
XX(jl_module_use) \

src/julia.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,8 @@ typedef struct _jl_module_t {
710710
struct _jl_module_t *parent;
711711
_Atomic(jl_svec_t*) bindings;
712712
_Atomic(jl_genericmemory_t*) bindingkeyset; // index lookup by name into bindings
713+
jl_sym_t *file;
714+
int32_t line;
713715
// hidden fields:
714716
arraylist_t usings; // modules with all bindings potentially imported
715717
jl_uuid_t build_id;

src/module.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ JL_DLLEXPORT jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, ui
5252
m->compile = -1;
5353
m->infer = -1;
5454
m->max_methods = -1;
55+
m->file = name; // Using the name as a placeholder is better than nothing
56+
m->line = 0;
5557
m->hash = parent == NULL ? bitmix(name->hash, jl_module_type->hash) :
5658
bitmix(name->hash, parent->hash);
5759
JL_MUTEX_INIT(&m->lock, "module->lock");
@@ -1179,6 +1181,14 @@ jl_module_t *jl_module_root(jl_module_t *m)
11791181
}
11801182
}
11811183

1184+
JL_DLLEXPORT jl_sym_t *jl_module_getloc(jl_module_t *m, int32_t *line)
1185+
{
1186+
if (line) {
1187+
*line = m->line;
1188+
}
1189+
return m->file;
1190+
}
1191+
11821192
JL_DLLEXPORT jl_uuid_t jl_module_build_id(jl_module_t *m) { return m->build_id; }
11831193
JL_DLLEXPORT jl_uuid_t jl_module_uuid(jl_module_t* m) { return m->uuid; }
11841194

src/staticdata.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,9 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t
12591259
jl_atomic_store_relaxed(&newm->bindingkeyset, NULL);
12601260
arraylist_push(&s->relocs_list, (void*)(reloc_offset + offsetof(jl_module_t, bindingkeyset)));
12611261
arraylist_push(&s->relocs_list, (void*)backref_id(s, jl_atomic_load_relaxed(&m->bindingkeyset), s->link_ids_relocs));
1262+
newm->file = NULL;
1263+
arraylist_push(&s->relocs_list, (void*)(reloc_offset + offsetof(jl_module_t, file)));
1264+
arraylist_push(&s->relocs_list, (void*)backref_id(s, m->file, s->link_ids_relocs));
12621265

12631266
// write out the usings list
12641267
memset(&newm->usings._space, 0, sizeof(newm->usings._space));

src/toplevel.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex
213213
form = NULL;
214214
}
215215

216+
newm->file = jl_symbol(filename);
217+
jl_gc_wb_knownold(newm, newm->file);
218+
newm->line = lineno;
219+
216220
for (int i = 0; i < jl_array_nrows(exprs); i++) {
217221
// process toplevel form
218222
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);

0 commit comments

Comments
 (0)