From 7289e665ebc8b89da9b9bafff76cddcd08d0bba4 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 27 Jun 2024 12:59:56 +0000 Subject: [PATCH] Fix accidental early evaluation of imported `using` binding In `using A.B`, we need to evaluate `A.B` to add the module to the using list. However, in `using A: B`, we do not care about the value of `A.B`, we only operate at the binding level. These two operations share a code path and the evaluation of `A.B` happens early and is unused on the `using A: B` path. I believe this was an unintentional oversight when the latter syntax was added. Fixes #54954. --- src/toplevel.c | 6 +++--- test/syntax.jl | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/toplevel.c b/src/toplevel.c index 3f9c6ba5e71ca..85d922016a4f8 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -821,14 +821,14 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_val if (jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_dot_sym) { name = NULL; jl_module_t *import = eval_import_path(m, from, ((jl_expr_t*)a)->args, &name, "using"); - jl_module_t *u = import; - if (name != NULL) - u = (jl_module_t*)jl_eval_global_var(import, name); if (from) { // `using A: B` and `using A: B.c` syntax jl_module_use(m, import, name); } else { + jl_module_t *u = import; + if (name != NULL) + u = (jl_module_t*)jl_eval_global_var(import, name); if (!jl_is_module(u)) jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, "invalid using path: \"%s\" does not name a module", diff --git a/test/syntax.jl b/test/syntax.jl index 3acf5864b2614..2553056fc00b9 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -3858,3 +3858,10 @@ end @test isa(expr.args[1], Union{GlobalRef, Symbol}) end end + +# Test that globals can be `using`'d even if they are not yet defined +module UndefGlobal54954 + global theglobal54954::Int +end +using .UndefGlobal54954: theglobal54954 +@test Core.get_binding_type(@__MODULE__, :theglobal54954) === Int