diff --git a/NEWS.md b/NEWS.md index 9c6e35a6c8127..af331402770ec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ Julia v1.13 Release Notes New language features --------------------- +* The syntax `using LongPackageName as LPN` is now supported ([#52821]). - New `Base.@acquire` macro for a non-closure version of `Base.acquire(f, s::Base.Semaphore)`, like `@lock`. ([#56845]) diff --git a/deps/JuliaSyntax.version b/deps/JuliaSyntax.version index 9487754d8a617..aa5a12127e418 100644 --- a/deps/JuliaSyntax.version +++ b/deps/JuliaSyntax.version @@ -1,4 +1,4 @@ -JULIASYNTAX_BRANCH = main -JULIASYNTAX_SHA1 = 46723f071d5b2efcb21ca6757788028afb91cc13 +JULIASYNTAX_BRANCH = lh/using-as +JULIASYNTAX_SHA1 = d3cc52a1f8f27d145517484db80e6ff20619aa00 JULIASYNTAX_GIT_URL := https://github.com/JuliaLang/JuliaSyntax.jl.git JULIASYNTAX_TAR_URL = https://api.github.com/repos/JuliaLang/JuliaSyntax.jl/tarball/$1 diff --git a/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/md5 b/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/md5 new file mode 100644 index 0000000000000..8f020683aa4b9 --- /dev/null +++ b/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/md5 @@ -0,0 +1 @@ +4f01f6c6538d08265522707574fd7c1d diff --git a/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/sha512 b/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/sha512 new file mode 100644 index 0000000000000..8fd1b19b52bce --- /dev/null +++ b/deps/checksums/JuliaSyntax-d3cc52a1f8f27d145517484db80e6ff20619aa00.tar.gz/sha512 @@ -0,0 +1 @@ +48db105250b0686e8d0834ba7af45656173d040438357e5569514b22dedd6e0dea742359153f16a07346fe3d34a81f75e7de1beacd9e0bf6ffa81dfa69e72167 diff --git a/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/md5 b/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/md5 new file mode 100644 index 0000000000000..dff679f66233b --- /dev/null +++ b/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/md5 @@ -0,0 +1 @@ +aeb5efda5cdf4e6e7d7741108d776fe1 diff --git a/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/sha512 b/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/sha512 new file mode 100644 index 0000000000000..8cea6087e3251 --- /dev/null +++ b/deps/checksums/Pkg-4c9b08431bb4d0cf875c517e65b9193906211746.tar.gz/sha512 @@ -0,0 +1 @@ +8f36b304d5e963c3ee649bafd1b06b26673a24c66be3aa3c8335ed941544140ba10878d00ff7a80aab288d57e69268bf4363e131ee852bebae726609a5b79686 diff --git a/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/md5 b/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/md5 deleted file mode 100644 index bcaf046283425..0000000000000 --- a/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e097e71eea7524a17bda8ba14569a983 diff --git a/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/sha512 b/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/sha512 deleted file mode 100644 index 1c659df733de4..0000000000000 --- a/deps/checksums/Pkg-5432fdd30f06707ee227237224b0b72168c2c2f5.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -56f6baeda00597ab8a9d9827e6a07aa41662e7914c6ba6fe8c6c21c2008a6552db9778ad95dbaad8d0309e6caa25995916adafcd0243b0f26e1e5217ae608a01 diff --git a/src/module.c b/src/module.c index 4c685ca574523..0a38543b9b301 100644 --- a/src/module.c +++ b/src/module.c @@ -513,8 +513,9 @@ static void jl_add_default_names(jl_module_t *m, uint8_t default_using_core, uin jl_module_initial_using(m, jl_core_module); } if (self_name) { - // export own name, so "using Foo" makes "Foo" itself visible - jl_set_initial_const(m, m->name, (jl_value_t*)m, 1); + // Do not export or publicize own name, "using Foo" already makes "Foo" itself + // visible and "using Foo as Bar" should not make the name "Foo" visible. + jl_set_initial_const(m, m->name, (jl_value_t*)m, 0); } } } diff --git a/src/toplevel.c b/src/toplevel.c index f1fff694926ba..ce5ba56442003 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -36,12 +36,15 @@ jl_mutex_t jl_modules_mutex; // During incremental compilation, the following gets set jl_module_t *jl_precompile_toplevel_module = NULL; // the toplevel module currently being defined +static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import, jl_sym_t *asname); + jl_module_t *jl_add_standard_imports(jl_module_t *m) { jl_module_t *base_module = jl_base_relative_to(m); assert(base_module != NULL); // using Base jl_module_initial_using(m, base_module); + import_module(m, base_module, NULL); return base_module; } @@ -845,26 +848,33 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_val jl_symbol_name(name)); // `using A` and `using A.B` syntax jl_module_using(m, u); - if (m == jl_main_module && name == NULL) { - // TODO: for now, `using A` in Main also creates an explicit binding for `A` - // This will possibly be extended to all modules. - import_module(ct, m, u, NULL); - } + import_module(ct, m, u, name); } continue; } - else if (from && jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_as_sym && jl_expr_nargs(a) == 2 && + else if (jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_as_sym && jl_expr_nargs(a) == 2 && jl_is_expr(jl_exprarg(a, 0)) && ((jl_expr_t*)jl_exprarg(a, 0))->head == jl_dot_sym) { jl_sym_t *asname = (jl_sym_t*)jl_exprarg(a, 1); if (jl_is_symbol(asname)) { jl_expr_t *path = (jl_expr_t*)jl_exprarg(a, 0); name = NULL; jl_module_t *import = eval_import_path(ct, m, from, ((jl_expr_t*)path)->args, &name, "using"); - assert(name); - check_macro_rename(name, asname, "using"); - // `using A: B as C` syntax - jl_module_use_as(ct, m, import, name, asname); - continue; + if (from) { + // `using A: B as C` and `using A: B.C as D` syntax + assert(name); + check_macro_rename(name, asname, "using"); + jl_module_use_as(ct, m, import, name, asname); + continue; + } + else { + // `using A as B` and `using A.B as C syntax + if (name != NULL) + import = (jl_module_t*)jl_eval_global_var(import, name); + check_macro_rename(import->name, asname, "using"); + jl_module_using(m, import); + import_module(ct, m, import, asname); + continue; + } } } jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 8d13ca7f3e8dc..326b4f5aabb6a 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 5432fdd30f06707ee227237224b0b72168c2c2f5 +PKG_SHA1 = 4c9b08431bb4d0cf875c517e65b9193906211746 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 diff --git a/test/core.jl b/test/core.jl index 4f27c4896da9d..ecedc50508748 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1213,7 +1213,7 @@ let A = [1] end # Module() constructor -@test names(Module(:anonymous), all = true, imported = true) == [:anonymous] +@test names(Module(:anonymous), all = true, imported = true) == [:Base, :anonymous] @test names(Module(:anonymous, false), all = true, imported = true) == [:anonymous] @test invokelatest(getfield, Module(:anonymous, false, true), :Core) == Core @test_throws UndefVarError invokelatest(getfield, Module(:anonymous, false, false), :Core) diff --git a/test/ordering.jl b/test/ordering.jl index 3b5385b99be68..3a55ecd89ac41 100644 --- a/test/ordering.jl +++ b/test/ordering.jl @@ -55,5 +55,5 @@ struct SomeOtherOrder <: Base.Order.Ordering end @testset "Base.Order docstrings" begin undoc = Docs.undocumented_names(Base.Order) @test_broken isempty(undoc) - @test undoc == [:DirectOrdering, :ForwardOrdering, :Order, :ordtype] + @test undoc == [:DirectOrdering, :ForwardOrdering, :ordtype] end diff --git a/test/reflection.jl b/test/reflection.jl index b9d1eaa1c86f9..2420c72a28f7f 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -312,6 +312,7 @@ public this_is_public @test isexported(@__MODULE__, :this_is_not_defined) @test !isexported(@__MODULE__, :this_is_not_exported) @test !isexported(@__MODULE__, :this_is_public) +@test !isexported(@__MODULE__, :TestingExported) const a_value = 1 @test which(@__MODULE__, :a_value) === @__MODULE__ @test_throws ErrorException("\"a_value\" is not defined in module Main") which(Main, :a_value) @@ -321,6 +322,7 @@ const a_value = 1 @test Base.ispublic(@__MODULE__, :this_is_not_defined) @test Base.ispublic(@__MODULE__, :this_is_public) @test !Base.ispublic(@__MODULE__, :this_is_not_exported) +@test !Base.ispublic(@__MODULE__, :TestingExported) end # PR 13825 @@ -1224,7 +1226,7 @@ private() = 1 end -@test names(TestNames) == [:TestNames, :exported, :publicized] +@test names(TestNames) == [:exported, :publicized] # reflections for generated function with abstract input types @@ -1318,3 +1320,37 @@ end using .X1ConstConflict, .X2ConstConflict @test_throws ErrorException which(@__MODULE__, :xconstconflict) + +# `using Mod as M` +module Mod52821 + +using Test + +module M1 + module M2 + export f52821 + f52821() = 7 + g52821() = 8 + end +end + +@test_throws UndefVarError f52821() +using .M1.M2 as Mod +@test f52821() === 7 # Export mechanism works +@test_throws UndefVarError g52821() # Unexported things don't get loaded +@test !isdefined(@__MODULE__, :M2) # Does not load the name M2 into Main +@test Mod === M1.M2 === Mod.M2 # Does load M2 under the aliased name +const M2 = 4 # We can still use the name M2 +@test M2 == 4 + +@test_throws UndefVarError mean([0]) +using Statistics as Stats +@test mean([0]) == 0 +@test Stats.mean === mean +@test Stats === Stats.Statistics +@test_throws UndefVarError Statistics.mean([0]) + +# combined "as" and "non-as" +using Base, Statistics as Stats, Test, .M1.M2 as Mod, M1 + +end diff --git a/test/syntax.jl b/test/syntax.jl index ec6c2ffb00635..45132a614b6f9 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1744,7 +1744,7 @@ eval(Expr(:toplevel, Expr(:block, Expr(:export, :Inner), Expr(:abstract, :Inner))))) -@test names(Mod28991) == Symbol[:Inner, :Mod28991] +@test names(Mod28991) == Symbol[:Inner] # issue #28593 macro a28593() @@ -2655,9 +2655,6 @@ end @test B37890(1.0, 2.0f0) isa B37890{Int, Int8} # import ... as -@test_parseerror("using A as B", "invalid syntax \"using A as ...\"") -@test_parseerror("using A.b as B", "invalid syntax \"using A.b as ...\"") -@test_parseerror("using X, A.b as B", "invalid syntax \"using A.b as ...\"") @test_parseerror("import A as B: c", "invalid syntax \"import A as B:\"") @test_parseerror("import A.b as B: c", "invalid syntax \"import A.b as B:\"") @@ -2732,6 +2729,9 @@ import .Mod.@mac as @m @test_throws ErrorException eval(:(using .Mod: @mac as notmacro)) @test_throws ErrorException eval(:(using .Mod: func as @notmacro)) +@test_throws ErrorException eval(:(using .Mod as @M)) +@test_throws UndefVarError eval(:(using .Mod.Mod2 as @M)) + import .Mod2.x_from_mod @test @isdefined(x_from_mod)