Module system changes are going into FCP!


Ooh, I like this suggestion.

On that note, another vote for anchored_use_paths. The explicitness feels like a definite boon, and typing self:: has become much rarer with the introduction of nested use statements.


I like the uniform path variant much more. The additional “crate” in Anchored paths seems like a step backwards.

To be honest I dislike the new macro import.
It’s easier for sure, but I liked that macros were separate things, as they’re (to me) not the same as real functions & structs.


I like uniform variant. But if it’s a huge issue - it’s not so critical if it will be anchored paths.


Another variant which I would like is a synthesis between anchored_use_paths and unified_paths variants.

  • As a basis we take a uniform_paths.
  • When referring to a crate as a first path separator we use ::: instead of ::.
  • When referring to current crate we use crate::: instead of leading ::.

Some fragments of code:

use futures:::Future;

fn my_poll() -> futures:::Poll { ... }

mod foo {
    fn func() {
        println!("foo::func is called");
        super::func();     // Calls a function from top level
    pub mod bar {
        fn func() {
            println!("bar::func is called");
            super::func(); // Calls a function from previous module
        crate fn summary() {
            func();        // Calls a function from current module
            super::func(); // Calls a function from previous module
            crate::func(); // Calls a function from top level
            outer:::func();// Calls a function from external crate 

    pub struct Baz;

use foo::Baz;
use atty:::Stream;
use structopt:::StructOpt;
use std:::{

enum SomeEnum {

pub fn func() {
    println!("crate:::func is called");
    let five = std:::sync::Arc::new(5);
    use SomeEnum::*;
    match ... {
        V1(i) => { ... }
        V2(s) => { ... }

fn main() {
    use notify:::{
    let (tx, rx) = std:::sync::mpsc::channel();
    let mut watcher = notify:::raw_watcher(tx)?;
    let file_dir = file_path.parent().expect("invalid file path");, RecursiveMode::NonRecursive)?;

It, however, was instantly downvoted on github, so there might be some issues with that syntax


I’d say that I like the general idea of it, but :: vs ::: really doesn’t really feel distinct enough without whitespace around them.


But is this distinction that interested for us to be more explicit? I think it’s more important for compiler to disambiguate namespaces and for external tools like code highlighters to be more flexible, but for humans it’s rather irrelevant in most of cases.

Current uniform_paths proposal even don’t has it.


If :: and ::: can cause different results then it’s important for them to be visually distinct.
If :: and ::: cannot cause different results then there is no reason to introduce :::.


There’s precedent for this factoring into syntax choices, too - the choice to make inclusive ranges use ..= instead of ... was based on the fact that the latter was harder to distiguish from an exclusive range (..) at a glance.


In fact :: and ::: cannot cause different results because code won’t compile if you choose a wrong separator. That will be not true only for a case when an external crate name and a name of local module matches plus they contain the same content which we access.
But there’s a very little chances for that to occur.
And we can easily catch such mistakes with proper syntax highlighting.
Finally, some clippy lint might be introduced to completely ensure that this situations never occurs.

That precedent is completely different, even if it looks similar:

  1. Wrong range syntax always compiles, so we can notice mistake only in runtime
  2. Inclusive and exclusive range syntaxes can’t be highlighted differently
  3. There’s no way to provide any clippy lint for wrong range
  4. Difference between inclusive and exclusive ranges really matters