What Different Between `::std::` and `std::`

I saw some usage in macro:

#[inline]
fn default() -> CommandBuilder {
    CommandBuilder {
        executable: ::core::default::Default::default(),
        args: ::core::default::Default::default(),
        env: ::core::default::Default::default(),
        current_dir: ::core::default::Default::default(),
    }
}

What's the meaning of the :: prefix?

::std unambiguously refers to the crate std. Without the leading ::, it could also refer to local mod or use statements (at the macro call site) that shadow the name std.

3 Likes

What if I have a custom crate named std?

I’m not entirely sure, but I suspect it’ll resolve to whichever crate is called std in the extern prelude.

OK, the std is very special.

So ::foo means: unambiguously refers to the crate foo. Right?

Yes, in Rust 2018, ::foo unambiguously refers to the external crate foo. However, the ::foo syntax is no longer commonly used, because foo alone is usually sufficient. (Macros are one case where disambiguating is still often useful.)

You'll find this syntax more often in old code. In Rust 2015, ::foo was used to refer to items (including external crates) that were defined or imported in the root module. This was replaced by crate::foo in Rust 2018. See the edition guide for more details.

5 Likes

FWIW, I'd like to bring an unconventional opinion on this matter: I personally have found that codebases that defaulted to prefixing extern crate names with the leading :: diambiguator (Edition 2018 ofc.) reduced the cognitive burden / overhead and thus lead to more readable code.

For instance, when you have:

use some_crate::prelude::*; // typical Rust idiom

and then later see something like oid::foo(), you can't know (without checking extra files), whether oid is some module brought by the prelude scope of some_crate or if it is an external crate in and on its own. By defaulting to using the leading :: disambiguator for the later case (with maybe an exception for the built-in crates, such as core, alloc and std), you no longer have this disadvantage :slightly_smiling_face:

  • and for those who may occasionally write (procedural1) macros, it prevents forgetting to use robust paths :wink:

1 Non-procedural macros should always be using $crate-qualified paths, reexporting (through #[doc(hidden)] pub use ::crate_name)-, if needed, things such as std, to feature macros that are 100% call-site context agnostic, and thus as robust as a function.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.