Skip to content

implicit module M wrapping #23619

@StefanKarpinski

Description

@StefanKarpinski

Problem

Currently, when you do using M and the code for M.jl is automatically loaded, the file is evaluated in Main and expected to define a module M. It can, however, evaluate arbitrary code in Main before or after the definition of M and can fail to define M entirely:

# M.jl
@show @__MODULE__ # => Main

module M # can not do this bit
    @show @__MODULE__ # => Main.M
end # module M

@show @__MODULE__ # => Main

With #23579 and the plan outlined in #4600 (comment), this becomes increasingly awkward. Modules will no longer live inside of Main so what module is code before and after the definition of M evaluated in?

Proposal

The simplest solution would be for the code in the file M.jl to be evaluated inside of M instead of defining M. In other words, the file M.jl would be reduced to this:

# M.jl
@show @__MODULE__ # => Main.M

When using M or import M ends up loading this file, it would implicitly wrap it in the equivalent of module M; include("M.jl"); end. This way the module M cannot help but be defined and the boilerplate module M and corresponding end # module at the beginning and end of most files is eliminated.

Transition

One fact makes this transition surprisingly straightforward: modules automatically have a constant, internal self-binding. Thus, module M; module M; end; end causes a warning to be printed: WARNING: replacing module M. Because of this, we can safely implement the above proposal and simply change the behavior of module M; module M; end; end – the inner module M; end would have no effect, simply continuing with the definition of the outer M. To encourage people to change their code and eliminate the boilerplate, we can emit a warning that the module M is no longer necessary and should be deleted.

The most common and official case of code evaluated in Main before module code is __precompile__ calls in packages, controlling/indicating whether a package is precompilable or not. This would no longer work as expected, so we need an alternative. Since precompilability is a package-level property, it would make sense for this bit to be recorded in the new Pkg3-style as a precompile = [true|false] entry in the Project.toml file. This metadata would automatically be propagated to the Pkg3 registry metadata for various versions of each package.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions