<p dir="auto">MWE:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="struct Foo
   a::Vector{Any}
end

xs = Vector{Union{Nothing, T} where T}([2, 3])
Foo(xs)"><pre class="notranslate"><span class="pl-k">struct</span> Foo
   a<span class="pl-k">::</span><span class="pl-c1">Vector{Any}</span>
<span class="pl-k">end</span>

xs <span class="pl-k">=</span> <span class="pl-c1">Vector</span><span class="pl-c1">{Union{Nothing, T} where T}</span>([<span class="pl-c1">2</span>, <span class="pl-c1">3</span>])
<span class="pl-c1">Foo</span>(xs)</pre></div>
<p dir="auto">this leads to "illegal hardware instruction" on both Julia 1.5.2 and julia 1.6.0-DEV.1184</p>
<p dir="auto">The lowered code and typed code seems fine, but <code class="notranslate">code_llvm</code> gives</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia&gt; @code_llvm Foo(xs)
;  @ REPL[1]:2 within `Foo'
define [1 x {}*] @julia_Foo_491({}* nonnull align 16 dereferenceable(40) %0) {
top:
  call void @llvm.trap()
  unreachable
}"><pre class="notranslate"><code class="notranslate">julia&gt; @code_llvm Foo(xs)
;  @ REPL[1]:2 within `Foo'
define [1 x {}*] @julia_Foo_491({}* nonnull align 16 dereferenceable(40) %0) {
top:
  call void @llvm.trap()
  unreachable
}
</code></pre></div>
<p dir="auto">also I find that the result of <code class="notranslate">convert</code> and <code class="notranslate">Vector{Any}(x)</code> does not match, though <code class="notranslate">convert</code> actually (should) calls <code class="notranslate">Vector{Any}</code> to convert <code class="notranslate">xs</code> to <code class="notranslate">Vector{Any}</code> (<a href="https://github.com/JuliaLang/julia/blob/master/base/array.jl#L554">https://github.com/JuliaLang/julia/blob/master/base/array.jl#L554</a>), e.g</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia&gt; convert(Vector{Any}, xs)
2-element Vector{Union{Nothing, T} where T}:
 2
 3

julia&gt; Vector{Any}(xs)
2-element Vector{Any}:
 2
 3"><pre lang="julia-repl" class="notranslate"><code class="notranslate">julia&gt; convert(Vector{Any}, xs)
2-element Vector{Union{Nothing, T} where T}:
 2
 3

julia&gt; Vector{Any}(xs)
2-element Vector{Any}:
 2
 3
</code></pre></div>
<p dir="auto">This is because Julia thinks <code class="notranslate">xs</code> of type <code class="notranslate">Vector{Union{Nothing, T} where T}</code> is a <code class="notranslate">Vector{Any}</code>, so <code class="notranslate">convert</code> returns <code class="notranslate">xs</code> directly but I'm not sure if this is actually true...</p>
<h3 dir="auto">LOAD_PATH</h3>
<p dir="auto">In <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="286696869" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/25455" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/25455/hovercard" href="https://github.com/JuliaLang/julia/pull/25455">#25455</a>, I tried to keep things as compatible as possible, leaving the contents of <code class="notranslate">LOAD_PATH</code> as a superset of what was in it previously. The current default contents is:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[ [ Base.CurrentEnv(),
    Base.NamedEnv(&quot;v0.7.0&quot;),
    Base.NamedEnv(&quot;v0.7&quot;),
    Base.NamedEnv(&quot;v0&quot;),
    Base.NamedEnv(&quot;default&quot;),
    Base.NamedEnv(&quot;v0.7&quot;, create=true) ],
  Base.Pkg.dir,
  &quot;/Users/stefan/projects/julia/usr/local/share/julia/site/v0.7&quot;,
  &quot;/Users/stefan/projects/julia/usr/share/julia/site/v0.7&quot; ]"><pre class="notranslate">[ [ Base<span class="pl-k">.</span><span class="pl-c1">CurrentEnv</span>(),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7.0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>default<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>, create<span class="pl-k">=</span><span class="pl-c1">true</span>) ],
  Base<span class="pl-k">.</span>Pkg<span class="pl-k">.</span>dir,
  <span class="pl-s"><span class="pl-pds">"</span>/Users/stefan/projects/julia/usr/local/share/julia/site/v0.7<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>/Users/stefan/projects/julia/usr/share/julia/site/v0.7<span class="pl-pds">"</span></span> ]</pre></div>
<p dir="auto">This has the effect of looking in the following places:</p>
<ol dir="auto">
<li>The first of the following which succeeds:
<ol dir="auto">
<li>parent directories of the current working directory with a <code class="notranslate">Project.toml</code> file, if any</li>
<li><code class="notranslate">joinpath(DEPOT_PATH[1], "environments", "v0.7.0")</code> if it exists</li>
<li><code class="notranslate">joinpath(DEPOT_PATH[1], "environments", "v0.7")</code> if it exists</li>
<li><code class="notranslate">joinpath(DEPOT_PATH[1], "environments", "v0")</code> if it exists</li>
<li><code class="notranslate">joinpath(DEPOT_PATH[1], "environments", "default")</code> if it exists</li>
<li><code class="notranslate">joinpath(DEPOT_PATH[1], "environments", "v0.7")</code> even if it doesn't exist</li>
</ol>
</li>
<li>The Pkg2 package directory indicated by <code class="notranslate">JULIA_PKGDIR</code></li>
<li>The local site package directory (architecture-specific) – currently not created by default</li>
<li>The site package directory (architecture-independent) – this is where stdlib packages live</li>
</ol>
<p dir="auto">The first entry can be replaced and number of items by setting the <code class="notranslate">JULIA_LOAD_PATH</code> environment variable. The other three <code class="notranslate">LOAD_PATH</code> entries are added no matter what you do, which is not ideal since we would like for users to be able to control their load path entirely. However, that does mean that if the user does not include the stdlib environment in their load path, they will <em>not</em> be able to use stdlib packages.</p>
<p dir="auto">The second entry is a legacy thing that allows us to continue loading Pkg2-installed packages. We should deprecate this whenever we replace Pkg2 with Pkg3: at that point, we can have a <code class="notranslate">DeprecatedEnv</code> loader that allows this to continue working but prints a warning message if the target directory actually exists. That way people can keep using Pkg2-installed packages during the 0.7 transition, but they'll get a warning that they should reinstall packages using Pkg3.</p>
<h3 dir="auto">DEPOT_PATH</h3>
<p dir="auto">The new code loading system separates how to resolve what package names mean from where to look for installed versions of packages. The <code class="notranslate">LOAD_PATH</code> is involved in deciding what <code class="notranslate">import Foo</code> means in various contexts. A package name can mean one thing in your code while meaning a different thing to each of your dependencies; this is essential in Pkg3 since there is no longer a single global namespace of package names: METADATA is replaced with a federated system of package registries, which can be public or private.</p>
<p dir="auto">Once the <em>identity</em> and <em>version</em> of <code class="notranslate">Foo</code> is resolved by looking in the <code class="notranslate">LOAD_PATH</code>, finding the code for that version of the package is a separate step, which involves looking through the <code class="notranslate">DEPOT_PATH</code> in the <code class="notranslate">packages</code> directory of each until an installed copy of the package is found (or isn't). Currently, the <code class="notranslate">DEPOT_PATH</code> defaults to only containing <code class="notranslate">joinpath(homedir(), ".julia")</code> – i.e. your "home depot" (I did not anticipate this pun when choosing the name "depot" but there it is). However, we'll want to support looking for installed packages in multiple different places, most likely including:</p>
<ol dir="auto">
<li>You home depot, typically <code class="notranslate">~/.julia</code></li>
<li>A platform-specific shared system directory, e.g. <code class="notranslate">/usr/local/share/julia/site/</code></li>
<li>A platform-independent shared system directory, e.g. <code class="notranslate">/usr/share/julia/site/</code></li>
<li>The standard library for the Julia binary you're using, maybe <code class="notranslate">/usr/share/julia/stdlib</code>?</li>
</ol>
<p dir="auto">I'm decreasingly sure what these paths should be so input and thoughts would be helpful here.</p>
<h3 dir="auto">LOAD_PATH defaults</h3>
<p dir="auto">Since "what" is now addressed by <code class="notranslate">LOAD_PATH</code> while "where" is addressed by <code class="notranslate">DEPOT_PATH</code>, we generally want far fewer things in <code class="notranslate">LOAD_PATH</code>. In fact, when testing a project, you generally <em>only</em> want that project's environment – and maybe a a "test environment" – in the <code class="notranslate">LOAD_PATH</code> so that if you try to load anything that isn't recorded and identified in the project's <code class="notranslate">Project.toml</code> file, you'll get a failure. However, it's handy when developing to be able to augment the project environment with tools like debuggers, profilers, <code class="notranslate">Revise.jl</code>, etc.</p>
<p dir="auto">What should be in the default load path in 1.0? Maybe just this:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[ [ Base.CurrentEnv(),
    Base.NamedEnv(&quot;v0.7.0&quot;),
    Base.NamedEnv(&quot;v0.7&quot;),
    Base.NamedEnv(&quot;v0&quot;),
    Base.NamedEnv(&quot;default&quot;),
    Base.NamedEnv(&quot;v0.7&quot;, create=true) ],
  &quot;/usr/share/julia/stdlib&quot; ]"><pre class="notranslate">[ [ Base<span class="pl-k">.</span><span class="pl-c1">CurrentEnv</span>(),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7.0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>default<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>, create<span class="pl-k">=</span><span class="pl-c1">true</span>) ],
  <span class="pl-s"><span class="pl-pds">"</span>/usr/share/julia/stdlib<span class="pl-pds">"</span></span> ]</pre></div>
<p dir="auto">If you start Julia in a project directory the, you'll only be able to load the project's dependencies and standard libraries – which, incidentally should probably also be recorded as project dependencies. Or maybe we want something more like this:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[ Base.CurrentEnv(),
  &quot;/usr/share/julia/stdlib&quot;,
  [ Base.NamedEnv(&quot;v0.7.0&quot;),
    Base.NamedEnv(&quot;v0.7&quot;),
    Base.NamedEnv(&quot;v0&quot;),
    Base.NamedEnv(&quot;default&quot;),
    Base.NamedEnv(&quot;v0.7&quot;, create=true) ] ]"><pre class="notranslate">[ Base<span class="pl-k">.</span><span class="pl-c1">CurrentEnv</span>(),
  <span class="pl-s"><span class="pl-pds">"</span>/usr/share/julia/stdlib<span class="pl-pds">"</span></span>,
  [ Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7.0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>default<span class="pl-pds">"</span></span>),
    Base<span class="pl-k">.</span><span class="pl-c1">NamedEnv</span>(<span class="pl-s"><span class="pl-pds">"</span>v0.7<span class="pl-pds">"</span></span>, create<span class="pl-k">=</span><span class="pl-c1">true</span>) ] ]</pre></div>
<p dir="auto">That would mean that you can load whatever's in the current project if it exists, the standard library, and whatever's in your default named environment, which would presumably include all your dev tools and other favorite packages.</p>
<h3 dir="auto">Controlling the LOAD_PATH</h3>
<p dir="auto">We'll want some convenient ways to manipulate the <code class="notranslate">LOAD_PATH</code>, e.g. to run with only the current environment visible. Design ideas are welcomed here, but my thought was that we'd have some command-line options to control this such as:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia --env=@ # just the current environment
julia --env=@devtools # just the named &quot;devtools&quot; environment
julia --env+@devtools # add the named &quot;devtools&quot; environment to the load path"><pre class="notranslate"><code class="notranslate">julia --env=@ # just the current environment
julia --env=@devtools # just the named "devtools" environment
julia --env+@devtools # add the named "devtools" environment to the load path
</code></pre></div>
<p dir="auto">It's a little weird to call this option <code class="notranslate">--env</code> when it manipulates the <code class="notranslate">LOAD_PATH</code> but maybe that's ok. We could also write it <code class="notranslate">julia --load-path=...</code> but I still like <code class="notranslate">--env</code> as a name for this since the <code class="notranslate">LOAD_PATH</code> is a list of environments to look in for dependencies.</p>