# Revisiting modules, take 3

**URL:** <https://internals.rust-lang.org/t/revisiting-modules-take-3/5715>\
**Category:** language design\
**Created:** [August 4, 2017, 9:06pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715 "2017-08-04T21:06:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 4, 2017, 9:06pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/1 "2017-08-04T21:06:02Z")

</div>

This is a third module proposal, very similar to the second one but iterating a bit more. It clarifies a few things from the previous proposal and introduces one additional significant change.

### The trouble with “everything is an item”

First, a digression.

In Rust, everything is an item except for let statements and expressions. Every module is just a collection of items (and modules are items), and you can access any item in the crate by naming its path. This means an `extern crate`, a `use`, a `mod` are all actually just _items_, which create new names in the present path context which alias names defined elsewhere.

This sounds very simple, and from one angle it is. But I would contend its the source of a significant amount of confusion around the module system:

1. Users often don’t expect `extern crate rand;` to bring `rand` into scope, and are confused about why `rand::random` works in the crate root, but nowhere else.
2. Users often report confusion about when to use `mod` and when to use `use`; they often feel that mod is a “weird `use` statement” because from their perspective, they’re _using_ `foo` by declaring `mod` (not adding it to their build, and then it happens to be in scope because a mod is an item just like a `use` is).
3. `use` being an item is also not the behavior people expect, usually. They thing of use as bringing names into this scope, but not as “mounting” those names to be visible in other scopes. Here’s an example of the surprising behavior that this creates:

```rust
use std::io::{self, Read, Write};

fn foo() -> io::Result<()> {
    ...
}

mod bar {
    use io::{Read, Write}; // NOTE: No `std::`
}

```

As an advanced Rust user, you might appreciate the real brilliance of having these conceptual unifications, and see a certain aesthetical appeal in the way that `use io` arises out of these orthogonal rules. I certainly do. But as a user trying to figure out why I have to `use std::io;` in the crate root, and I can just `use io;` everywhere else (because I’ve stumbled upon that discovery by mistake), this is not a good UX.

I also know there are some users who don’t just appreciate this unification, but consider it _extremely important_. I’d be happy to hear this position more fully articulated - I haven’t received a clear impression of why this would be so important. But I’d also encourage users to keep an open mind to a system in which:

- `use` is not an item; it brings a name into scope, but does not _mount_ it in the module hierarchy at this location. It does not have a visibility attribute (no `pub use`)
- A new keyword, `export`, is an item, and does take a visibility attribute.

That’s the biggest new idea of the proposal, but now into the full details of this proposal.

* * *

* * *

## The proposal

### Absolute path hierarchy

The absolute root of the path graph, from which paths beginning `::` traverse, is not the module of `main.rs` or `lib.rs`, but a module which contains these symbols:

- One module for each crate passed by `--extern`, which contain that crate’s module tree underneath it (that is `::std`, `::serde`, etc)
- A special `crate` module, which contains _this_ crate (from the previous `root` module).

That is, absolute paths are written `::std::iter::Iterator;` to get something from another crate, and `::crate::module::Item;` to get something from _this_ crate.

### Use statements

`use` statements are no longer items, and do not mount names, they only import them. That is, items imported with `use` cannot be accessed from other modules.

`use` statements take absolute paths beginning at the `::crate::` module, not the true root. So you have:

```rust
use module::Item; // an item defined in src/module.rs
use ::std::iter::Iterator; // an item defined in another crate
use self::child::Item; // an item defined in a child module
use super::sibling::Item; // an item defined in a sibling module

```

Only thing that’s changed in this syntax is `::` on crate imports (and some sugar will make that better soon).

Because `use` statements are not items, they do not have their own visibility. Instead, we have a new kind of statement called export statements.

### Export statements

`export` statements work a lot like `use` statements do today - they both mount and import names, impacting the resolution of relative paths in this module and absolute paths in other modules. There are a few key differences from use statements, designed to improve user experience.

First (and most importantly), the path they take is relative to the current module, not the crate. So you are replacing:

```rust
pub use self::child::Item;
// replaced with
pub export child::Item;

```

However, they can still take absolue paths with `::`, just like use statements can (and again, the next section has syntactic sugar to make this nicer).

```rust
pub export ::crate::module::Item;
pub export ::std::iter::Iterator;
pub export super::sibling::Item;
pub export self::child::Item; // equivalent to not having self::

```

The last big difference is that `export` is `pub(crate)` by default. However, export can take any visibility scope, including `pub(self)` if you really only want to make this item visible in submodules.

### The from syntactic sugar

To avoid having to write `::` in use and export statements, we also add the `from` syntax. `from` takes a single ident, which is any of these:

- The name of one of the `--extern` crates, including `std`.
- The speical symbols `crate`, `self`, and `super`.

Both `use` and `export` statements can be prefixed with `from`, which desugars them to taking the appropriate absolute path:

```rust
from std use iter::Iterator; 

from super use sibling::Item;

from tokio export Service;

from crate pub export module::Item;

```

We could also possibly support a more complex syntactic sugar that takes multiple paths, but I haven’t worked through it fully:

```rust
from std use {
    cmp::{min, max},
    collections::HashMap,
    iter::once,
    thread,
}

```

### Modules

Mod statements would no longer be necessary to pick up a file a new file in the crate. Instead, rustc would walk the files it knows to walk (see next section for more info), and mount a module tree from that, possibly before parsing any Rust code.

Files mounted this way would have a `pub(crate)` visibility, if you wish to change that publicity, add an export statement to their parent.

```rust
pub export submodule1;
pub(self) export submodule2; // if you are very concerned about using something
                             // from this submodule elsewhere in the crate

```

Though the names of modules are mounted automatically, they are not imported into their parent, and so they are not visible to relative paths from their parent unless they are imported with `use` or `export`. That is, you cannot use the name of a submodule without somhow bringing it into scope through use or export statements.

Modules of the form `mod foo { /* code */ }` would still exist, with no change to their semantics.

### File lists

rustc will only automatically load modules that are listed through two command line arguments it receives: `--load-files` and `--ignore-files`. The files that it loads are all the files matching load-files, subtracting those which match ignore-files. Both take a list of filenames, supporting basic standard glob expansions.

- When building a `lib.rs` or `main.rs`, cargo tells rustc to load any files matching `src/ **/*.rs` and to ignore any matching `src/bin/** /*.rs` (that is, all `.rs` files in the `src` directory, except those in the `bin` directory).
- When building a binary in the root of the `bin` directory, cargo tells rustc to load every file in the `bin` directory.
- When building a binary in a subdirectory of `bin`, cargo tells rustc to load every file in that directory.

This introduces a firmer convention around multi-crate packages. In my survey, most multi-crate packages already conformed to this, though a sizable minority did not (mainly by having both `main.rs` and `lib.rs` in the same directory):

- For packages with 1 binary and 1 library, the bin should be in `src/bin` while the library is in `src/lib.rs`. `src/main.rs` is only used by packages without a library.
- For packages with multiple binaries, they should each sit in their own subdirectory of `bin`, none should sit in the `bin` directory directly.

However, some users will probably want to opt out of these defaults for multiple reasons:

- They do not want rustc using glob imports to import all of the files in their `src` directory.
- They do not want to structure their multi-crate packages in the same way.

For this reason, `cargo` will expose a way to control these arguments to rustc directly, probably through the `Cargo.toml`. My hope is that most users won’t do this, though, and it will result in a more consistent package structure across the ecosystem.

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 4, 2017, 10:06pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/3 "2017-08-04T22:06:26Z")

</div>

> Files mounted this way would have a pub(crate) visibility

I think there's one question that should be answered, which isn't obvious: Is it actually important for modules to have non-public visibility? Or, does it really only matter that (non-submodule) items within modules have visibility controls?

If visibility on modules is actually important, then I think the default used everywhere else (private) should be the default on modules too. Conversely, if it isn't important (or can be made to be not important, by changing our conventions to be more item-specific) then there's no reason to have explicit visibility controls on modules.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 4, 2017, 10:10pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/4 "2017-08-04T22:10:24Z")

</div>

> [@briansmith](#):
>
> I think there’s one question that should be answered, which isn’t obvious: Is it actually important for modules to have non-public visibility? Or, does it really only matter that (non-submodule) items within modules have visibility controls?

The reason we prefer `pub(crate)` is that even if a module exports no items, another crate could do something awful like:

```rust
from your_crate use module::with::no::items::*;

```

And now if you delete `src/module/with/no/items.rs`, that's a breaking change.

However, _inside_ your crate, this is not a breaking change - you just delete that line that wasn't doing anything. I don't understand the reason to make modules less than pub(crate) - the benefit of it is that for the purpose of your own crate, items now say exactly what their visibility is - if they are `pub(crate)`, they can be seen anywhere in the crate for sure.

Some users see this as a downside, but I don't see why you would mark an item `pub(crate)` that isn't supposed to be `pub(crate)`. I think this is a bit of a holdover from previous patterns where you mark items `pub` and then make the module private to mean `pub(super)`, but we _have_ `pub(super)` now.

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 4, 2017, 10:19pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/5 "2017-08-04T22:19:51Z")

</div>

> [@withoutboats](#):
>
> The reason we prefer pub(crate) is that even if a module exports no items, another crate could do something awful like:
> 
> ```rust
> from your_crate use module::with::no::items::*;
> 
> ```

If this is the only issue then I think we should just get rid of the idea of visibility for modules completely, because the problem of people referencing a module with nothing in it hardly seems like an important problem to solve. Then we could just say that visibility is a property of items. I think that would be easier to learn than having different defaults for modules than other items.

---

<div class="post-metadata">

**Author:** ![aturon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aturon/32/3272_2.png) [@aturon](https://internals.rust-lang.org/u/aturon)\
**Post date:** [August 4, 2017, 10:31pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/6 "2017-08-04T22:31:51Z")

</div>

Thank you, @withoutboats! I think this variant has a _lot_ of promise, and I'm feeling really optimistic that we're getting ever closer to a winner.

Here are some kneejerk thoughts:

- The `from` form seems under-motivated here. IMO, if we let you write `use ::std::blah` no one is going to use the more verbose `from` form.

- You don't spell out the rationale for not bringing submodules into scope automatically. I worry that this will be surprising and unergonomic. What's the upside?

- Did you consider making `export` not use relative paths per se, but rather based on what's in scope, i.e. working the same way as paths in non-`use` items? I suspect that would be more clear.

Finally, I want to say that I think @briansmith's point has merit:

> [@briansmith](#):
>
> If this is the only issue then I think we should just get rid of the idea of visibility for modules completely, because the problem of people referencing a module with nothing in it hardly seems like an important problem to solve.

As we've been going through this module system work, I increasingly feel that the visibility of module names is totally insignificant (as opposed to the items within them). Taking that to its conclusion, though, would in practice require writing more constrained uses of `pub` than today -- we often lazily write `pub` items in a private module, when we really should be saying `pub(crate)` or something even more narrow. I see this as a bit of a wart in Rust code today, but to fix it we'll need to make `pub(restricted)` more ergonomic IMO.

It's also worth noting that if we remove module visibility altogether, `export` may no longer be as motivated.

---

<div class="post-metadata">

**Author:** ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)\
**Post date:** [August 4, 2017, 10:34pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/7 "2017-08-04T22:34:37Z")

</div>

I have been wondering in the past (and maybe even read a suggestion about it somewhere) if it would be possible to reset item visibility with a bare `pub`. E.g.:

```
pub submodule::SomePublicItem;

```

which in the context of this proposal would make `submodule` fully public, but all items in it are only `pub(crate)` except the `SomePublicItem` with specific visibility. This could help avoid having to reexport for visibility reasons only.

Just bringing it up since the mount/import split might make this appear less magic. And now that I’m done writing and looking at the newest comments, it might also be relevant in the “visibility for modules” topic.

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [August 4, 2017, 10:48pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/8 "2017-08-04T22:48:31Z")

</div>

To echo a point that others have made in previous threads:

I really don’t think it’s necessary to auto-load all .rs files in the directory tree, given all the drawbacks (for users who prefer alternate directory layouts, sometimes have stray files lying around, etc.). It should be sufficient to lazy-load modules when they’re referenced through the absolute path hierarchy; this would cause some confusion with modules that only have impls and not items, but it’s not that bad (such modules aren’t too common and the compiler could have smart diagnostics), and I’d say it’s ultimately less trouble than the alternative.

(signed, someone who prefers alternate directory layouts)

No particular opinion on the rest of the proposal.

---

<div class="post-metadata">

**Author:** ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)\
**Post date:** [August 4, 2017, 11:01pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/9 "2017-08-04T23:01:50Z")

</div>

> [@withoutboats](#):
>
> I also know there are some users who don’t just appreciate this unification, but consider it extremely important. I’d be happy to hear this position more fully articulated - I haven’t received a clear impression of why this would be so important.

This - private `use` statements being accessible - is actually a fairly new feature introduced by @petrochenkov (`item_like_imports`). In Rust 1.0, `use` was like `use` with this proposal & `pub use` was like `export` (but with an absolute path).

It's actually a "feature" I don't like - it confuses me sometimes: e.g. `librustc/ty/mod.rs` contains a `use ty::substs::Substs;`, so you can use `use ty::Substs;` within any (of the many) submodules of the `ty` module but not outside of it.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [August 4, 2017, 11:07pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/10 "2017-08-04T23:07:53Z")

</div>

> [@withoutboats](#):
>
> This sounds very simple, and from one angle it is.

And from the other angle it's simple as well, because it's objectively simple, and documentation can describe the rules in a few lines. This proposal, on the other hand, immediately starts with introducing more complexity\* (in very backward incompatible way).  
The premise seems fundamentally wrong, it's oriented on people discovering the language purely by intuition and taking an invitation to read even basic docs as an insult. The language can't match every guess and expectation inherited from any other language, the new model won't match them as well.

(I won't proceed to the technical details, I didn't fully process even the "take 2" yet.)

\* To clarify, I'm not against introducing this separation in principle, I even suggested it myself in [https://github.com/rust-lang/rfcs/pull/1976#issuecomment-301903528](https://github.com/rust-lang/rfcs/pull/1976#issuecomment-301903528) (in backward compatible way), the "non-item" imports just shouldn't _look like items_.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [August 4, 2017, 11:10pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/11 "2017-08-04T23:10:22Z")

</div>

> [@arielb1](#):
>
> This - private use statements being accessible - is actually a fairly new feature introduced by @petrochenkov (item\_like\_imports).

The design was actually by @Kimundi (originally) and @nrc, and @jseyfried did the implementation, I mostly helped by staying nearby and being supportive.  
(Before it was implemented, people actually reported imports being non-items as confusing! (There's no escape from this hell.))

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [August 4, 2017, 11:24pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/12 "2017-08-04T23:24:33Z")

</div>

I like these `use` defaults. In particular: Removing private `use`s as items child modules see is a nice touch. Bringing back intra-crate absolute paths in `use` is also a win, and is another step closer to backwards compatibility.

I’m not convinced of the mechanism, though- removing `pub use` and adding yet another keyword (`export`) with yet another path default (relative) feels like a step back. Could we perhaps implement it as an even narrower level of visibility, only for `use` items? It might be odd for different item types to have different defaults, but then again submodules don’t tend to rely on private `use`s of their parents. One exception might be `mod tests { use super::*; }`- this could use some clarification. ( **edit re @arielb1** : apparently this is how it was until very recently!)

I would also prefer to preserve `rustc`'s ability to discover an entire crate’s source files, without `--load-files`. While they’d both be rarely done, explicitly `use`ing `impl`-only files seems much easier than managing globs. Further, globs still have the problem I mentioned in the last thread- deleting a file that’s not referenced anywhere else won’t trigger a rebuild in many build systems.

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [August 4, 2017, 11:56pm UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/13 "2017-08-04T23:56:07Z")

</div>

- The goal to remove `mod` is good.
- Creating a module tree from the file system _alone_ is not desirable, because it’s inflexible and stray files are included even if you didn’t ask for it.
  - Instead, it seems ideal to create the module tree by combining explicit `use` and the file system. A file is not part of the crate unless it is `use`d by the crate root directly or indirectly.
  - `use` determines if a file is included, directory structure determines what the path to the module is in the namespace.

- As much as I agree that it’s confusing that _non-pub_ `use` “mounts” items, maybe that can stay and help solve the other goals with few changes.

For example, `extern crate` can maybe be removed like this: Add path prefix `crate::` that simply resolves a path in an extern crate. (Alternative syntax: `extern::`). Intended use is through `use` statements.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 5, 2017, 12:12am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/14 "2017-08-05T00:12:47Z")

</div>

> [@aturon](#):
>
> Finally, I want to say that I think @briansmith’s point has merit:

Modules can't have no visibility of their own because of other constraints we have.

First, the `less than or equal to` rule of visibility: If you have an item that's marked `pub(crate)`, we guarantee that it is never re-exported at a greater visibility than `pub(crate)` (and similarly for any other visibility restriction).

Second, we want to support facading, so that items are visible in the public API, but not where they are defined (for example, the flattening in the `futures` crate discussed in a previous blog post).

The only way to support both of these is to have `pub` items in a `pub(crate)` module. So we cannot have modules be public always.

---

<div class="post-metadata">

**Author:** ![ahmedcharles](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ahmedcharles/32/4041_2.png) [@ahmedcharles](https://internals.rust-lang.org/u/ahmedcharles)\
**Post date:** [August 5, 2017, 12:34am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/15 "2017-08-05T00:34:35Z")

</div>

I sort of have the same feedback to this proposal that I did with part 2.

```rust
use std::io::{self, Read, Write};
mod bar {
    use io::{Read, Write}; // NOTE: No `std::`
}

```

I think the issue with this is that I expect `io` in `bar` to refer to `::bar::io` not `::io`. Hence why I prefer relative use statements and if this read `::io::{Read, Write};`, I don’t think it would be as confusing, because it would be obvious that it’s referring to the `io` in the crate root, which (if you search for `io`) is obviously added by the `use` statement. Like @petrochenkov says, having unusual syntax/semantics isn’t the problem, it’s having people learn them that’s the problem. This sort of stuff could be easily documented in the book, but the last time I checked, it wasn’t and I’m not sure why.

The book doesn’t seem to explain name lookup and it waits until after explaining `mod`, to explain `use` and it doesn’t have any example where `use` is not used at the crate root. So, given all of those things, why would Rust name lookup make sense, even to people who read the docs? Why are we trying to change things on the basis of learning Rust when the things we are changing are things that aren’t documented in an accessible way? If I missed the documentation somewhere, please feel free to point it out.

I like the `inline mod` proposal, because it’s a targeted fix for a targeted problem. I like the `from <crate> use <path>;` syntax because it removes the need to add external code as items into the root crate while preserving all of the consistency related to how normal `use` statements work. I suspect relative use statement would help with understanding what use statement refer to, but that’s not a guarantee and it doesn’t really add anything fundamental and it’s not backwards compatible, so I could take it or leave it.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 5, 2017, 12:35am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/16 "2017-08-05T00:35:00Z")

</div>

> [@aturon](#):
>
> - You don’t spell out the rationale for not bringing submodules into scope automatically. I worry that this will be surprising and unergonomic. What’s the upside?

Not convinced this is the right decision. The goal was to make the name appear somewhere at the top of the file if you're going to use it, but for many use cases this is not ideal (e.g. having a lot of `use self::` statements is not great).

> [@aturon](#):
>
> - Did you consider making export not use relative paths per se, but rather based on what’s in scope, i.e. working the same way as paths in non-use items? I suspect that would be more clear.

That only works if submodule are in scope by default (e.g. your previous point), but that sounds fine to me; the only difference then, as far as I can tell, would be that `export` would be able to see things that `use` had imported.

> [@aturon](#):
>
> The from form seems under-motivated here. IMO, if we let you write use ::std::blah no one is going to use the more verbose from form.

My belief is that the `from` form is more obvious and intuitive than the `::` form. Here's the imports from `src/ir/mod.rs` in chalk:

```rust
use cast::Cast;
use chalk_parse::ast;
use lalrpop_intern::InternedString;
use solve::infer::{TyInferenceVariable, LifetimeInferenceVariable};
use std::collections::{HashSet, HashMap, BTreeMap};
use std::sync::Arc;

// the items after this line are at the *bottom* of the file for some reason:

pub mod debug;
mod tls;

pub use self::tls::set_current_program;
pub use self::tls::with_current_program;

```

Not to pick on Niko or anyone else, but I personally strictly separate my std imports, my extern crate imports, and my imports from other files in the module. So I'm already pretty unhappy with how this is organized. But reorganized to be better sorted, here's how it is with the "unsugared" form:

```rust
use ::std::collections::{HashSet, HashMap, BTreeMap};
use ::std::sync::Arc;

use ::chalk_parse::ast;
use ::lalrpop_intern::InternedString;

use cast::Cast;
use solve::infer::{TyInferenceVariable, LifetimeInferenceVariable};

pub export debug;
pub export tls::{set_current_program, with_current_program};

```

I think this is already much clearer, but I don't think its _intuitive_ that `::` means "an external dependency." As a new user looking at this file, I don't feel like I would be able to figure out why the first four imports are different; I suspect I would get exactly the wrong impression - that `::` meant "from the crate root."

So I would prefer if the from sugar were the idiomatic way to import things from other crates:

```rust
from std use {
    collections::{HashSet, Hashmap, BTreeMap},
    sync::Arc,
}

from chalk_parse use ast;
from lalrpop_intern use InternedString;

use cast::Cast;
use solve::infer::{TyInferenceVariable, LifetimeInferenceVariable};

pub export debug;
pub export tls::{set_current_program, with_current_program};

```

To me, this seems very easy to interpret!

But several people have suggested out of band that everyone will just prefer the `::` form, because it is shorter. I'd really like this not to be the case, but I'm not sure how. In order to be a successful improvement, the `from` syntax needs widespread buyin. Here are some ideas of how to achieve that:

- Make the absolute paths `extern::` instead of `::`. Leading `::` would stop being a thing in this world. I actually kind of like this "aesthetically," because it makes extern/self/super/crate the four keywords that "begin non-relative paths," making them more consistent. Now its not less typing to not use `from`.
- Only support the multiple-path form of use with `from`, as a carrot to encourage `from`.
- Declare `from` idiomatic and have rustfmt use it.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 5, 2017, 12:53am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/17 "2017-08-05T00:53:21Z")

</div>

> [@withoutboats](#):
>
> Make the absolute paths extern:: instead of ::. Leading :: would stop being a thing in this world. I actually kind of like this “aesthetically,” because it makes extern/self/super/crate the four keywords that “begin non-relative paths,” making them more consistent. Now its not less typing to not use from.

New variation on the proposal, generated from talking to @scott in IRC:

### Changes to absolute paths

We drop the `::` form entirely. Instead, all absolute paths begin with one of these keywords:

- `self` and `super`, which mean what they do today
- `crate`, which means imported from the root of this crate.
- `extern`, which contains all of the external crate dependencies. So `extern::std::iter::Iterator` is the absolute path to Iterator.

### Changes to use and export

Use and export cannot take an absolute path. Instead, their fully desugared form always uses `from`.

```rust
// allowed
from std use iter::Iterator;
// not allowed:
use extern::std::iter::Iterator;

```

However, we _do_ have sugar, so that without `from` on use means `from crate` and on export means `from self`:

```rust
use module::Item;
// sugar for
from crate use module::Item;

export child::Item;
// sugar for
from self export child::Item;

```

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [August 5, 2017, 1:06am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/18 "2017-08-05T01:06:01Z")

</div>

> [@withoutboats](#):
>
> ```rust
> use std::io::{self, Read, Write};
> mod bar {
> use io::{Read, Write}; // NOTE: No `std::`
> }
> 
> ```

Wait, that's legal? I thought I always had to import items from the super-crate.

Oh wait, you assume this is at the crate root. (It just literally took me more than a minute to realize that this is the reason the example works.) So actually this is `use ::io::{Read, Write}` inside `bar`, which indeed makes perfect sense if you buy into this "everything is an item" thing. Which I will freely admit I like 🙂

* * *

As already expressed previously, I like having a grammar of paths that covers all paths, making e.g. types in other nameable for error messages or for usage without `use`.

However, I don't like the fact that in this proposal, `use module::Type` and `const x: module::Type = ...` do not use the same rules to resolve `module::Type`. That's a step backwards compared to take 2. This is exactly the "relative vs. absolute path" problem, which to me in the single most confusing part about the current module system. `use` and `export` and other places that paths occur should be uniform in how they interpret any given path.

I also do not buy the motivation for the `from` syntactic sugar. From a UI perspective, I would then certainly expect to also be able to write e.g. `from std::io use Read, Write;` (as indeed other languages do, e.g. Coq -- and also Python, I believe?). However, such sugar is entirely redundant: We already have `use std::io::{Read, Write}`. Curly braces are currently needless limited, but they can be made to scale much better than `from`. I think it is much more consistent to be able to write e.g.

```rust
use ::std::{
  io::{Read, Write},
  cmp::min,
};

```

or even (with the "four roots")

```rust
use extern::{
  std::io::{Read, Write},
  regex,
};

```

rather than using `from` here.

I personally do not think "`use` is an item" is particularly hard to learn, and indeed it is beautiful, but I am also not extremely attached to the idea. If it confuses people, I don't mind that being changed. I suppose the hope is that `export` sounds more like this item being also available elsewhere, which is plausible. However, writing `export foo:Foo` will not actually make this item available to other crates, which one might expect from a command named "export". Furthermore, I am concerned that people will think that `export` is _mandatory_ to export anything, i.e., that non-export things are in fact not exported.

Also, I find the role of `use` and `export` to be somewhat confusing -- from what I understand, export is (the new version of) use + being an item? IOW, export is like the current use (well, with changes to what paths are)? I expect the question "when do I `use`, when do I `export`, and what is even the difference between the two" will be a very common one.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [August 5, 2017, 1:14am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/19 "2017-08-05T01:14:53Z")

</div>

> [@withoutboats](#):
>
> Changes to absolute paths We drop the :: form entirely. Instead, all absolute paths begin with one of these keywords:
> 
> self and super, which mean what they do today
> 
> crate, which means imported from the root of this crate.
> 
> extern, which contains all of the external crate dependencies. So extern::std::iter::Iterator is the absolute path to Iterator.

Most of what I wrote in parallel to you posting this still applies, I just wanted to drop one more thing because `crate` as a keyword came up repeatedly here: I do not find it obvious at all that this means _current_ crate. I know that `pub(crate)` also does that, but that's a different context. Reading `crate::foo::bar`, my first inclination is to parse this as "the `bar` item in the `foo` crate" -- just like how in URLs, the first item is special for many protocols (think: `crate://foo/bar`). Maybe that's just my brain being weird, just wanted to warn about possible misunderstandings here.

Also, it would be great if it was possible to have a name for an item that works both in the crate it is defined in, and in other crates. For example, if this crate is called `foo`, then something like `extern::foo` could be allowed. That would provide a way to communicate names that are meaningful without knowing which crate they are interpreted in.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 5, 2017, 1:21am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/20 "2017-08-05T01:21:33Z")

</div>

> [@RalfJung](#):
>
> Also, it would be great if it was possible to have a name for an item that works both in the crate it is defined in, and in other crates. For example, if this crate is called foo, then something like extern::foo could be allowed. That would provide a way to communicate names that are meaningful without knowing which crate they are interpreted in.

This is appealing, but isn't it possible to depend on a crate with the same name as the crate under compilation? (And not uncommon, if you have both a bin and a lib form of a crate).

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [August 5, 2017, 1:38am UTC](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715/21 "2017-08-05T01:38:56Z")

</div>

Actually, thinking about your latest proposal again, I think this is moving in the right direction. You didn't say this explicitly, but I assume `use` would be relative to the current crate like paths everywhere else. I mostly like the path syntax, except for `crate` but I also agree that `::path` looks rather ugly. `crate` seems acceptable. Also, `self::foo` and `foo` should be equivalent in every context. (Your only mentioned absolute paths, not sure if you implied this.)

However, I think forbidding `use extern::std::iter::Iterator` is totally the wrong approach. That just destroys all uniformity of the way paths work. I do agree we need some sugar to avoid `use extern::std::io::{...}; use extern::std::fmt; ...`. If that ends up being `from` rather than curly braces, that seems suboptimal to me, but whatever. But nobody should be forced to use the sugar, that would be just wrong. Your argument above was "`::` is unintuitive", which no longer applies now that absolute paths always start with a keyword. So, I'd appreciate if you could give some motivation for why you want to enforce this as a _hard error_.

(I am not commenting on the other aspects, about file system control etc., as I care much less about them. I just hope in the end it will be possible to have files be anonymous modules or completely flat. 😉 )

> [@withoutboats](#):
>
> This is appealing, but isn’t it possible to depend on a crate with the same name as the crate under compilation? (And not uncommon, if you have both a bin and a lib form of a crate).

Oh, I forgot about this. Two crates with the same name in the same crate hierarchy. _ugh_ Can we deprecate that?^^

[Next page](https://internals.rust-lang.org/t/revisiting-modules-take-3/5715.md?page=2)
