@ebebbington there are two different things that mod mod_name; do, and I think that's the source of many confusions:
-
They allow to have code located in another file, like
include!("path/to/file.rs");does. -
But they also bundle that code within a module. And modules create their own namespace, which is a property that goes in both directions: to refer to items inside that module you need the
module_name::path prefix, and to refer to items from the parent module (the file containing themod ...declaration), you need thesuper::path prefix. In that regard, modules behave very similarly to a filesystem.-
use ..."statements" then allow to "skip" using a special path prefix for theused items: we say these items have been brought into the scope of the place where theuse ..."statement" was located. And that scope, in and on itself, is namespaced too.Back to the filesystem analogy,
use"statements" are the equivalent of a symlink. -
File system analogy:
-
So, in order to understand this characteristics, it is better to dissociate those two things: try and refrain yourself from using mod mod_name; (that is a mod with a semicolon instead of { ... }). And instead, use inline modules mod mod_name { /* mod contents here */ }, and include!(); statements (ideally independently, so that you understand stuff better).
In that direction, I would even recommend to start having all the code bundled within a single file, and only after such single-file code works, start extracting stuff with those include!s.
use ::std::net::TcpListener;
use ::std::thread;
mod server {
pub struct HttpOptions {
pub hostname: String,
pub port: u32,
}
pub fn listen (...) {
... thread::spawn ( ... )
// ^^^^^^ no item `thread` in the scope of `server::*`
}
}
Finally, try to have code (that compiles!) using the pattern:
mod mod_name {
include!("mod_name.rs");
}
// or
mod mod_name {
include!("mod_name/mod.rs");
}
And only once you reach that point, you can replace either with the mod modname; shorthand.
See also:
