What does :: (double colon) mean before an identifier? - rust

This line is from Rust libc crate. What is the use of double colon here? I thought its bringing c_uint in the scope from the crate root but I can't find where its defined in the crate root.
pub type speed_t = ::c_uint;

https://doc.rust-lang.org/reference/paths.html#path-qualifiers
Paths can be denoted with various leading qualifiers to change the meaning of how it is resolved.
::
Paths starting with :: are considered to be global paths where the segments of the path start being resolved from the crate root. Each identifier in the path must resolve to an item.
So your idea was correct, it is resolving from the crate root.
I can't find where its defined in the crate root.
well libc doesn't in-and-of-itself define anything at the crate root, instead the crate root re-exports the content of the submodule matching the compilation target.
So on unix the "crate root" contains anything exposed by the fixed_width_ints and unix submodules. The former is not really useful for you, but the latter... does define a c_uint symbol.

This syntax works in libc because its compiled using the 2015 Edition of Rust. The Paths reference includes a note:
Edition Differences: In the 2015 Edition, the crate root contains a variety of different items, including external crates, default crates such as std and core, and items in the top level of the crate (including use imports).
Beginning with the 2018 Edition, paths starting with :: can only reference crates.
In 2015, the ::c_uint would find the re-exported type, whereas in 2018 it won't. There were a number of module resolution changes that are described with more detail in the Edition Guide.
You can test it out on the playground (you can change editions in the advanced options menu next to Debug and Stable).

Related

Can I apply a crate attribute only to the crate itself?

I have a Rust project that needs a few binaries with TitleCaseNames. So I created source files like src/bin/MyFooBinary.rs and src/bin/MyBarBinary.rs. The compiler warns that these binary crates should have snake case names, and I want to suppress that warning.
I can add #![allow(non_snake_case)] to the crate, but that then applies to the crate's entire contents as well. Not ideal. I really only want to suppress the warning for the crate name. Is that possible?
I'd suggest to follow the usual snake_name convention for the source file and crate names. Since you need to move the binaries elsewhere during deployment or packaging anyway, you can rename them at that point.
In the nightly compiler build, you can also specify a filename that is different from the crate name in Cargo.toml:
cargo-features = ["different-binary-name"]
[package]
# ...
[[bin]]
name = "foo_bar"
filename = "FooBar"
path = "src/bin/foo_bar.rs"

How do I find the path to the home directory for Linux?

I need the path contained in $HOME, the path to the home directory. The function home_dir seems to do exactly that but is deprecated. What should I use in its place?
The documentation says this :
Deprecated since 1.29.0:
This function's behavior is unexpected and probably not what you want. Consider using a crate from crates.io instead.
What type of crate should I use instead? Is there really no alternative in standard Rust?
From the home crate.
The definition of home_dir provided by the standard library is incorrect because it relies on the $HOME environment variable which has basically no meaning in Windows. This causes surprising situations where a Rust program will behave differently depending on whether it is run under a Unix emulation environment. Neither Cargo nor rustup use the standard libraries definition - instead they use the definition here.
There is discussion about bringing home_dir back into the standard library, but for now the home crate is probably your best option. It provides canonical definitions of home_dir, cargo_home, and rustup_home:
match home::home_dir() {
Some(path) => println!("{}", path.display()),
None => println!("Impossible to get your home dir!"),
}
From the dirs crate.
Note that the crate provides paths to many standard directories as defined by operating systems rules, not only the home directory:
Experience has shown that 90% of those asks for $HOME are better served by one of the other functions this crate provides.
If your requirements are more complex, e. g. computing cache, config, etc. paths for specific applications or projects, consider using the directories crate instead.

Testing a Rust crate outside of the source package

I have created my Rust crate. It's a very trivial affair. It built fine and when tested within it's own source directory works just fine (I just included extern crate my_first_crate; in my test file).
I want to now test the crate in a totally different application.
If I add the same extern crate line to my new application, the compiler tells me that it can't find the crate. I expected this (I'd get the same in C if I told the compiler to link to a library it has no clue about!)
Do I need to copy the my_first_crate.rlib file from the source to the application target/debug folder or is there a way to tell cargo that it needs to link to the rlib file?
You need to add your crate as a dependency for your application. Add this to your application's Cargo.toml:
[dependencies]
my_first_crate = { path = "/path/to/crate" }
"/path/to/crate" is the path to the root of the crate's source (i.e. the directory that contains its Cargo.toml). You can use either a relative or an absolute path (but avoid absolute paths if you intend on publishing your code!).

Figure out code from what module is "use"d in a large rust project (servo)

I'm trying to read the code of servo. As an example, I'm looking at this code in layout_task.rs:
use url::Url;
..and I want to know which code this refers to (the answer is rust-url).
Per the Rust reference §6.1.2.2 Use declarations,
the paths contained in use items are relative to the crate root [...]
It is also possible to use self and super at the beginning of a use item to refer to the current and direct parent modules respectively.
All rules regarding accessing declared modules in use declarations apply to both module declarations and extern crate declarations.
The reference (§5 Crates and source files) does not explicitly say what a "crate root" is, but it does share that:
A crate contains a tree of nested module scopes. The top level of this tree is a module that is anonymous [...] The Rust compiler is always invoked with a single source file as input, and always produces a single output crate. The processing of that source file may result in other source files being loaded as modules.
So it seems that to find the crate root that the current file (layout_task.rs) belongs to, we need to figure out what source file rustc is invoked with when building the crate. With Cargo this is specified in Cargo.toml and defaults to src/lib.rs:
[lib]
path = "src/lib.rs"
In my case, here's Cargo.toml and the lib.rs has:
extern crate url;
pub mod layout_task;
So far so good. To find out what the extern crate refers to, we need to look at Cargo.toml again:
[dependencies.url]
version = "0.2"
The cargo docs claim that "Dependencies from crates.io are not declared with separate sections", but apparently they can be... So we look the package up on crates.io: https://crates.io/crates/url

Multiple Rust source files for cargo

If I have multiple .rs files in the src directory of a Cargo package, what are the rules for visibility, importing, etc.?
Currently, any extra (i.e. not the file that is explicitly identified as the source for the executable in Cargo.toml) files are ignored.
What do I need to do to fix this?
There is nothing special about Cargo at all in this way. It’s all the perfectly normal Rust module system. If Cargo will be compiling src/lib.rs, that’s more or less equivalent to having executed rustc --crate-type lib src/lib.rs (there are more command line arguments in practice, but that’s the basics of it).
Other files are then used with mod, use and so forth. Files are not automatically imported or anything like that. This part is not documented very clearly yet; a couple of things that show briefly how to achieve things are http://rustbyexample.com/mod/split.html and http://doc.rust-lang.org/reference.html#modules, but any non-trivial code base will use them and so you can pick just about any code base to look at for examples.
It's hard to say what you're getting tripped up on from the info you shared. Here are three seemingly trivial things that I still had to refer to the documentaton to figure out:
First of all,
mod foo;
looks like a declaration, but it without arguments it is actually something like an include. So you use the same keyword both for declaring and including modules, i.e. there is no using:: keyword.
Second, modules themselves can be public or private. If you didn't add a pub keyword both on the function in question AND on the containing module, that may be tripping you up.
pub mod foo {pub fn bar();}
Third, there seems to be an implicit module added at the top of every file. This is confusing; the reference manual talks about a strict separation between file paths and names, and the module paths in your code, but that abstraction seems to be leaky here.
Note, Rust is still pre-1.0 (0.12) at the time of writing, at the module system and file paths are relatively high level, so don't be surprised if what I said may already wrong by the time you read this.
Files are implicitly included from your rust code.
For instance, if a file src/foo.rs pointed by path in a [lib] or [[bin]] section of your Cargo.toml contains:
mod bar;
It tells cargo to build src/bar.rs too, and include it.

Resources