snippetrustModerate
How do you use parent module imports in Rust?
Viewed 0 times
youhowmoduleimportsparentuserust
Problem
If you have a directory structure like this:
How do you use functions from other files?
From the Rust tutorial, it sounds like I should be able to do this:
main.rs
logging.rs
blah.rs
blah2.rs
However, this produces an error:
It appears that importing down the path, i.e. from
If I use the magical
blah2.rs
Do I really have to manually use relative file paths to import something from a parent scope level? Isn't there some better way of doing this in Rust?
In Python, you use
src/main.rs
src/module1/blah.rs
src/module1/blah2.rs
src/utils/logging.rs
How do you use functions from other files?
From the Rust tutorial, it sounds like I should be able to do this:
main.rs
mod utils { pub mod logging; }
mod module1 { pub mod blah; }
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}blah.rs
mod blah2;
pub fn doit() {
blah2::doit();
}blah2.rs
mod utils { pub mod logging; }
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}However, this produces an error:
error[E0583]: file not found for module logging
--> src/main.rs:1:21
|
1 | mod utils { pub mod logging; }
| ^^^^^^^
|
= help: name the file either logging.rs or logging/mod.rs inside the directory "src/utils"
It appears that importing down the path, i.e. from
main to module1/blah.rs works, and importing peers, i.e. blah2 from blah works, but importing from the parent scope doesn't.If I use the magical
#[path] directive, I can make this work:blah2.rs
#[path="../utils/logging.rs"]
mod logging;
pub fn doit() {
logging::trace("Blah2 invoked");
}Do I really have to manually use relative file paths to import something from a parent scope level? Isn't there some better way of doing this in Rust?
In Python, you use
from .blah import x for the local scope, but if you want to access an absolute path you can use from project.namespace.blah import x.Solution
I'm assuming you want to declare
The only change I made was the
Also, notice that I write it all inline, placing the contents of
(By the way,
It's not idiomatic to get the exact structure you want, you have to make one change to the location of blah2.rs:
main.rs
utils/logging.rs
module1/blah.rs
module1/blah/blah2.rs (the only file that requires any changes)
utils and utils::logging at the top level, and just wish to call functions from them inside module1::blah::blah2. The declaration of a module is done with mod, which inserts it into the AST and defines its canonical foo::bar::baz-style path, and normal interactions with a module (away from the declaration) are done with use.// main.rs
mod utils {
pub mod logging { // could be placed in utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
}
}
mod module1 {
pub mod blah { // in module1/blah.rs
mod blah2 { // in module1/blah2.rs
// *** this line is the key, to bring utils into scope ***
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
}
pub fn doit() {
blah2::doit();
}
}
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}The only change I made was the
use crate::utils; line in blah2 (in Rust 2015 you could also use use utils or use ::utils). Also see the second half of this answer for more details on how use works. The relevant section of The Rust Programming Language is a reasonable reference too, in particular these two subsections:- Separating Modules into Different Files
- Bringing Paths into Scope with the use Keyword
Also, notice that I write it all inline, placing the contents of
foo/bar.rs in mod foo { mod bar { } } directly, changing this to mod foo { mod bar; } with the relevant file available should be identical.(By the way,
println(": {}\n", msg) prints two new lines; println! includes one already (the ln is "line"), either print!(": {}\n", msg) or println!(": {}", msg) print only one.)It's not idiomatic to get the exact structure you want, you have to make one change to the location of blah2.rs:
src
├── main.rs
├── module1
│ ├── blah
│ │ └── blah2.rs
│ └── blah.rs
└── utils
└── logging.rs
main.rs
mod utils {
pub mod logging;
}
mod module1 {
pub mod blah;
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}module1/blah.rs
mod blah2;
pub fn doit() {
blah2::doit();
}module1/blah/blah2.rs (the only file that requires any changes)
// this is the only change
// Rust 2015
// use utils;
// Rust 2018
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}Code Snippets
// main.rs
mod utils {
pub mod logging { // could be placed in utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
}
}
mod module1 {
pub mod blah { // in module1/blah.rs
mod blah2 { // in module1/blah2.rs
// *** this line is the key, to bring utils into scope ***
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
}
pub fn doit() {
blah2::doit();
}
}
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}mod utils {
pub mod logging;
}
mod module1 {
pub mod blah;
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}pub fn trace(msg: &str) {
println!(": {}\n", msg);
}mod blah2;
pub fn doit() {
blah2::doit();
}// this is the only change
// Rust 2015
// use utils;
// Rust 2018
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}Context
Stack Overflow Q#20922091, score: 49
Revisions (0)
No revisions yet.