Skip to content

Allow using LongPackageName as LPN and change export conventions. #52821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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])

Expand Down
4 changes: 2 additions & 2 deletions deps/JuliaSyntax.version
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4f01f6c6538d08265522707574fd7c1d
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
48db105250b0686e8d0834ba7af45656173d040438357e5569514b22dedd6e0dea742359153f16a07346fe3d34a81f75e7de1beacd9e0bf6ffa81dfa69e72167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aeb5efda5cdf4e6e7d7741108d776fe1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8f36b304d5e963c3ee649bafd1b06b26673a24c66be3aa3c8335ed941544140ba10878d00ff7a80aab288d57e69268bf4363e131ee852bebae726609a5b79686

This file was deleted.

This file was deleted.

5 changes: 3 additions & 2 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
32 changes: 21 additions & 11 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Pkg.version
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion test/ordering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
38 changes: 37 additions & 1 deletion test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
8 changes: 4 additions & 4 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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:\"")

Expand Down Expand Up @@ -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)
Expand Down
Loading