In my view, there can be important gains in improving both the documentation and the compiler diagnostics.
Let me provide a concrete example, with some pretending to be a newbie and āthinking aloudā
use std::path::Path;
fn main() {
let p = Path::new("");
}
Super boring code, but letās imaging that copied it from a tutorial (that is, I wrote it without deeply understanding everything. I see a use std::path::Path at the top, and then I call this Path thing later, this looks reasonable. Since Iām come from another programming language, Iāve started to synthesize a mental model about how to use use.
Now I try to write a test, using the test module boilerplate that cargo auto generates:
use std::path::Path;
fn main() {
let p = Path::new("");
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let p = Path::new("");
}
}
My it_works() function seems to visually have the same form as my main() function, yet this code will not compile:
error[E0433]: failed to resolve. Use of undeclared type or module `Path`
--> a.rs:14:17
|
14 | let p = Path::new("");
| ^^^^^^^^^ Use of undeclared type or module `Path`
People familiar with this issue will immediately see the problem, but the compiler generated error message is not helpful in this case. I believe it can be improved, perhaps by noticing the use std::path::Path; at the top of the file and suggesting that the test module on line xyz needs to have the same use statement.
If I open the rust book and scroll to the section titled āImporting Modules with useā, hereās what the first part reads (paraphrased, since I wonāt bother to reproduce the whole section in this forum post)
Rust has a use keyword, which allows us to import names into our local scope. The two use lines import each module into the local scope, so we can refer to the functions by a much shorter name.
Well, apart from some confusion about what ālocal scopeā means, it appears that Iāve done just what the docs suggest, but my code still fails. Here is where I believe the book misses an opportunity to explain how each file is part of an implicit module, and use statements that appear to be global (at the top of the file) are in fact local to this implicitly created model.
One of the very first things in the chapter (under the Basic Terminology section) is this sentence:
Each crate has an implicit root module that contains the code for that crate.
But as a newbie, this single sentence is too terse for me to fully grok itās implications and itās relevance to my particular problem
Going one step further, I notice how a use can be used to use a thing by a shorter name, so maybe in the interest of experimentation, I try this:
fn main() {
let p = std::path::Path::new("");
}
Cool! It works! Letās try to apply it to my test module:
error[E0433]: failed to resolve. Use of undeclared type or module `std`
Now Iām still a really confused newbie.
I know that withoutboatsā blog post didnāt directly mention this case, but I hope Iāve given a compelling example where some hopefully minor changes could have the potential to have a proportionally lager positive impact on new users.