include module from the same directory level [duplicate] - rust

If you have a directory structure like this:
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.

I'm going to answer this question too, for anyone else who finds this and is (like me) totally confused by the difficult-to-comprehend answers.
It boils down to two things I feel are poorly explained in the tutorial:
The mod blah; syntax imports a file for the compiler. You must use this on all the files you want to compile.
As well as shared libraries, any local module that is defined can be imported into the current scope using use blah::blah;.
A typical example would be:
src/main.rs
src/one/one.rs
src/two/two.rs
In this case, you can have code in one.rs from two.rs by using use:
use two::two; // <-- Imports two::two into the local scope as 'two::'
pub fn bar() {
println!("one");
two::foo();
}
However, main.rs will have to be something like:
use one::one::bar; // <-- Use one::one::bar
mod one { pub mod one; } // <-- Awkwardly import one.rs as a file to compile.
// Notice how we have to awkwardly import two/two.rs even though we don't
// actually use it in this file; if we don't, then the compiler will never
// load it, and one/one.rs will be unable to resolve two::two.
mod two { pub mod two; }
fn main() {
bar();
}
Notice that you can use the blah/mod.rs file to somewhat alleviate the awkwardness, by placing a file like one/mod.rs, because mod x; attempts x.rs and x/mod.rs as loads.
// one/mod.rs
pub mod one.rs
You can reduce the awkward file imports at the top of main.rs to:
use one::one::bar;
mod one; // <-- Loads one/mod.rs, which loads one/one.rs.
mod two; // <-- This is still awkward since we don't two, but unavoidable.
fn main() {
bar();
}
There's an example project doing this on Github.
It's worth noting that modules are independent of the files the code blocks are contained in; although it would appear the only way to load a file blah.rs is to create a module called blah, you can use the #[path] to get around this, if you need to for some reason. Unfortunately, it doesn't appear to support wildcards, aggregating functions from multiple files into a top-level module is rather tedious.

I'm assuming you want to declare 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 { <contents> } } 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");
}

I realize this is a very old post and probably wasn't using 2018. However, this can still be really tricky and I wanted to help those out that were looking.
Because Pictures are worth a thousand words I made this simple for code splitting.
Then as you probably guessed they all have an empty pub fn some_function().
We can further expand on this via the changes to main
The additional changes to nested_mod
Let's now go back and answer the question:
We added blah1 and blah2 to the mod_1
We added a utils with another mod logging inside it that calls some fn's.
Our mod_1/mod.rs now contains:
pub mod blah.rs
pub mod blah2.rs
We created a utils/mod.rs used in main containing:
pub mod logging
Then a directory called logging/with another mod.rs where we can put fns in logging to import.
Source also here https://github.com/DavidWhit/Rust_Modules
Also Check Chapters 7 for libs example and 14.3 that further expands splitting with workspaces in the Rust Book. Good Luck!

Answers here were unclear for me so I will put my two cents for future Rustaceans.
All you need to do is to declare all files via mod in src/main.rs (and fn main of course).
// src/main.rs
mod module1 {
pub mod blah;
pub mod blah2;
}
mod utils {
pub mod logging;
}
fn main () {
module1::blah::doit();
}
Make everything public with pub you need to use externally (copy-pasted original src/utils/logging.rs). And then simply use declared modules via crate::.
// src/module1/blah.rs
use crate::utils::logging;
// or `use crate::utils` and `utils::logging::("log")`, however you like
pub fn doit() {
logging::trace("Logging works");
}
p.s. I shuffled functions a bit for a cleaner answer.

If you create a file called mod.rs, rustc will look at it when importing a module. I would suggest that you create the file src/utils/mod.rs, and make its contents look something like this:
pub mod logging;
Then, in main.rs, add a statement like this:
use utils::logging;
and call it with
logging::trace(...);
or you could do
use utils::logging::trace;
...
trace(...);
Basically, declare your module in the mod.rs file, and use it in your source files.

Related

self keyword after wildcard import

Let's say I have the following main.rs and lib.rs files. Why after doing the wildcard import self refers to testing::nested and not the main binary module anymore?
Could somebody point me to documentation where they explain this? I haven't been able to find it.
// main.rs
use testing::nested::*;
fn main() {
self::hello();
}
// lib.rs (testing module)
pub mod nested {
pub hello() {
println!("hello from nested::hello");
}
}
Just like #Ivan and #eggyal mentioned, is not that self refers to nested, is that the use declaration created a binding for hello in the main module.

How to break a large Rust impl block into files?

Here is what I have in foo.rs:
pub struct Foo {
// a few attributes
}
impl Foo {
// 20+ public functions
}
// 100+ tests
The file is too long (2000+ lines of code). How can I break it into files without changing the structure of the code: I want to still have one struct Foo with many functions and many unit tests.
It appears that the tests make up a large portion of the file. If you have followed the usual pattern of having tests in a submodule (mod tests) then the
simplest way to break up this file is to move the tests module to a separate file.
You can either:
create a directory foo containing mod.rs with the non-test code and tests.rs with the contents of the tests sub-module, or
keep foo.rs with the non-test code and create a directory foo only containing the tests.rs file.
// Keep this in foo.rs or move to foo/mod.rs
pub struct Foo {
// a few attributes
}
impl Foo {
// 20+ public functions
}
// Replace this module with `mod tests;`
mod tests {
// move the contents to a new file `foo/tests.rs`
// 100+ tests
}
Rust allows you to have impl blocks in separate files. So you can have, for example:
In file1.rs:
pub struct Foo {
// a few attributes
}
In file2.rs:
impl Foo {
// some methods
}
In file3.rs:
impl Abc for Foo {
// other methods
}
In file4.rs:
impl Xyz for Foo {
// other methods
}
It's also worth mentioning that if you have private fields in your struct Foo (the default, i.e. you don't add pub or any other visibility modifiers to your fields) , you can still access them in other files, but there is a restriction: they can only be accessed by the current module and its descendants.

Why do I get "expected struct file1::A found struct file2::A" error when using a struct in multiple files?

I am trying to share a struct between two files, but I am getting an error.
I have the following folder structure:
src/
Models/
Login.rs
Routes/
LoginRoute.rs
Services/
LoginService.rs
main.rs
In Login.rs I have:
#[derive(Serialize, Deserialize, Debug)]
pub struct UserLoginResponse {
id: i32,
username: String,
token: String
}
In LoginRoute.rs I have:
#[path = "../Models/Login.rs"]
pub mod Login;
#[path = "../Services/LoginService.rs"]
pub mod LoginService;
#[post("/login", format = "application/json", data = "<user>")]
pub async fn login(user: String) -> Json<Login::UserLoginResponse> {
if let Ok(sk) = LoginService::callAuthenticate(user).await {
return sk
......
In LoginService.rs I have:
#[path = "../Models/Login.rs"]
pub mod Login;
pub async fn callAuthenticate(user: String)-> Result<Json<Login::UserLoginResponse>, Error> {
...
let userLoginResponse :Login::UserLoginResponse = Login::UserLoginResponse::new(1, "admin".to_string(), api_reponse.return_result);
Ok(Json(userLoginResponse))
}
I am getting error in LoginRoute.rs on the return sk line:
expected struct 'LoginRoute::Login::UserLoginResponse', found struct 'LoginService::Login:UserLoginResponse'
Please do not use the #[path = ...] attribute for your typical organization; it should only be used in obscure cases. Each time you do mod something, you are declaring a new module. Even if two modules point to the same file due to #[path = ...], they will be distinct.
So you have multiple UserLoginResponse structs declared:
one at crate::LoginRoute::Login::UserLoginResponse
one at crate::LoginService::Login:UserLoginResponse
and maybe another if you've also declared Login in main.rs.
Since they're in distinct modules, the Rust compiler sees them as different types, which is not what you want.
Just use the idiomatic way of declaring modules. If you want to keep your existing folder structure without intermediate mod.rs files, you can declare them all in main.rs like so:
mod Models {
pub mod Login;
}
mod Routes {
pub mod LoginRoute;
}
mod Services {
pub mod LoginService;
}
And then access them elsewhere via crate::Models::Login and whatnot.
See:
How do I import from a sibling module?
You've probably already run into warnings from the compiler trying to encourage a specific style: "module [...] should have a snake case name". Idiomatic file structure would typically look like this:
src/
models/
login.rs
mod.rs
routes/
login_route.rs
mod.rs
services/
login_service.rs
mod.rs
main.rs
Where main.rs would have:
mod models;
mod routes;
mod services;
And src/models/mod.rs (for example) would have:
pub mod login;

Confused on how to use rust modules [duplicate]

This question already has answers here:
Split a module across several files
(7 answers)
How can I include a module from another file from the same project?
(6 answers)
How to use one module from another module in a Rust cargo project?
(3 answers)
Closed 2 years ago.
I have three files. main.rs, foo.rs, bar.rs all in the src directory. I want to use whats in foo.rs in bar.rs. So i have mod foo; inside of bar. But i get an error as shown below. I do not want to put the foo.rs in a sub directory e.g. src/bar/foo.rs is there another way to structure the code? Because i want foo.rs to be used in many different places besides bar.rs. Optionally if you could tell me how you structure a big project with multiple files then that will suffice.
file not found for module `foo`
--> src/bar.rs:1:1
|
1 | mod foo;
| ^^^^^^^^
|
= help: to create the module `foo`, create file "src/bar/foo.rs"
error: aborting due to previous error
main.rs
mod bar;
fn main() {
println!("Hello, world!");
}
foo.rs
pub fn do_something() {
}
bar.rs
mod foo;
You only have to declare modules once, and in this case you would declare both in main and then you would be able to import them from anywhere else in your codebase using use crate::{mod_name}. Example:
src/main.rs
// declare foo & bar modules
mod foo;
mod bar;
fn main() {
foo::foo();
foo::call_bar();
bar::bar();
bar::call_foo();
}
src/foo.rs
// import bar module
use crate::bar;
pub fn foo() {
println!("foo");
}
pub fn call_bar() {
bar::bar();
}
src/bar.rs
// import foo module
use crate::foo;
pub fn bar() {
println!("bar");
}
pub fn call_foo() {
foo::foo();
}

How to use functions from one file among multiple files?

I'm trying to use the functions from one file with multiple other files.
When I try adding 'mod somefile' to the files, the Rust compiler wants them to be nested in a subfolder, which isn't how I want to structure the project, as it would mean duplicating the file each time.
// src/main.rs
mod aaa;
mod bbb;
fn main() {
aaa::do_something();
bbb::do_something_else();
}
// src/aaa.rs
mod zzz; // rust compiler wants the file to be nested in a subfolder as aaa/zzz.rs
pub fn do_something() {
zzz::do_stuff();
}
// src/bbb.rs
mod zzz; // again, compiler wants the file nested in a subfolder as bbb/zzz.rs
pub fn do_something_else() {
zzz::do_stuff();
}
// src/zzz.rs
pub fn do_stuff() {
// does stuff here
}
I would like to be able to leave src/zzz.rs in the root src folder and use its functions among any of the other files in the project, instead of having to duplicate it in subfolders for each file (ex: src/aaa/zzz.rs, src/bbb/zzz.rs).
You need mod zzz; only once in the main.rs.
In aaa.rs and bbb.rs you need a use crate::zzz;, not a mod zzz;.
An example:
File src/aaa.rs:
use crate::zzz; // `crate::` is required since 2018 edition
pub fn do_something() {
zzz::do_stuff();
}
File src/bbb.rs:
use crate::zzz;
pub fn do_something_else() {
zzz::do_stuff();
}
File src/main.rs:
// src/main.rs
mod aaa;
mod bbb;
mod zzz;
fn main() {
aaa::do_something();
bbb::do_something_else();
}
File src/zzz.rs:
pub fn do_stuff() {
println!("does stuff zzz");
}
You would need a mod zzz; inside of aaa module only if you had a directory called aaa and inside of it a files mod.rs and zzz.rs. Then you would have to put mod zzz; in mod.rs to make the submodule aaa::zzz visible to the rest of your program.

Resources