This question already has answers here:
How do I import from a sibling module?
(1 answer)
How to use one module from another module in a Rust cargo project?
(3 answers)
Split a module across several files
(7 answers)
Closed 2 years ago.
Welcome, this question is for sure repeated, but for past 2 hours my mod didn't work and im sure I've done everything correctly.
Here is my tree:
project \
|- target...
|
|- rust_stuff...
|
\- src
|- main.rs
|
|- first_file.rs
|
\- second_file.rs
And here is second one, for reference when i will list what i tried:
project \
|- target...
|
|- rust_stuff...
|
\- src
|- main.rs
|
|- first_file.rs
|
\- cool_folder
|
\second_file.rs
Ok, so we have:
// -- MAIN --
mod first_file;
pub use first_file::*;
fn main() {
call_first();
}
Now, first_file.rs contains
// -- FIRST_FILE --
mod second_file; //E: Not found
pub use second_file; //E: Not used
pub fn call_first(){
call_second(); //E: Out of scope
}
I will stop here, second_file exists, and cannot be accesed by first_file but can be accessed by main just like this:
// -- MAIN --
mod first_file;
pub use first_file::*;
mod second_file;
pub use second_file::*;
fn main() {
call_first(); //Would call 'call_second' but as i presented it can't
call_second(); //Returns "Hello world" in terminal
}
(Thats assuming second_file is same as first_file with just different function naming)
Now, reffering to second tree i showed, i tried putting those files in cool_file, but it worked out the same except i used:
mod cool_file; //Err
pub use cool_file::*;
// this does not work
pub use second_file::*;
// neither does this
In documentation from what i understand, i wrote it the right way, in regards to first example, i have no idea what to do. Please help.
Related
I have a Cargo project set up with a library and a binary. The library is meant to be used on many platforms, including Android, while the binary is only meant to be used on Linux. As such, the binary contains a bunch of Linux-specific code that does not compile when I target Android. Is there a way to specify (without using features) that the binary should only be compiled on Linux?
I tried putting #![cfg(target_os = "linux")] in the main.rs of my binary, but then I got this error:
error[E0601]: `main` function not found in crate `server`
--> src/bin/server/main.rs:1:1
|
1 | / #![cfg(target_os = "linux")]
2 | |
3 | | use anyhow::{self, Context};
4 | |
... |
36 | | }
37 | | }
| |_^ consider adding a `main` function to `src/bin/server/main.rs`
I had exactly the same problem. The official Rust docs do not seem to mention how to solve it. But I found a solution.
The trick is to specify two main() functions in the file main.rs. The first one contains the code you want to execute when you are on Linux. The second one remains empty. With the help of conditional compilation, you tell the compiler which of the two main() functions to compile.
// within main.rs
#[cfg(target_os = "linux")]
fn main() {
// Your Linux-specific code goes here...
}
#[cfg(not(target_os = "linux"))]
fn main() {} // remains empty for all other OS
If you have OS-specific imports or other code at the top-level, just wrap it inside a module and use conditional compilation for it as well.
#[cfg(target_os = "linux")]
mod linux {
use anyhow::{self, Context};
// ...
}
The below link has related information that should help you in terms of target selection and selective compilation https://doc.rust-lang.org/cargo/commands/cargo-build.html#target-selection
Main Question
How to use code from helper1.rs in main.rs.
// main.rs
mod lib;
use lib::lib_function;
use lib::public_library;
mod module_a;
mod module_b;
use module_a::{helper1::helper1_function, mod_a_function};
use module_b::{helper2, helper3, mod_b_function};
fn main() {
println!("Hello, world from main!");
lib_function();
public_library::public_library_mod_function();
helper1_function();
mod_a_function();
helper2::helper2_function();
helper3::helper3_function();
mod_b_function();
}
// module_b/mod.rs
pub mod helper2;
pub mod helper3;
pub fn mod_a_function() {
println!("Printing from module_b/mod.rs");
}
// module_b/helper2.rs
pub fn helper2_function() {
println!("Hello from Helper 2!!");
}
I get the error:
error: couldn't read src\module_b\mod.rs: stream did not contain valid UTF-8
--> src\main.rs:14:1
|
14 | mod module_b;
| ^^^^^^^^^^^^^
error: could not compile `rust_modules_cheat_sheet` due to previous error
I'm not sure what non-utf-8 character is in module_b but isn't in module_a.
Cheat Sheet for modules and importing in Rust
I've seen a lot of tutorials online that kind of say the same thing, but it's not complete or sophisticated for other cases. I wanted to ask the community as well as research how to use code from various situations and modules in rust. If you would like to comment below for the two cases I am unsure of right now, that would be appreciated.
Example Directory
/src
| main.rs
| lib.rs
| other.rs
|- module_a/
| | mod.rs
| | helper1.rs
|- module_b/
| | mod.rs
| | helper2.rs
| | helper3.rs
Various Situation
Using code from other.rs in main.rs (Understood)
Using code from lib.rs in main.rs (Understood)
Using code from mod.rs in lib.rs (Understood)
Using code from helper1.rs in main.rs (Understood)
Using code from helper2.rs in helper3.rs (Unsure)
Using code from module_a/mod.rs in module_b/mod.rs (use crate::module_a)
Github Repo for Future Reference
Link to repo
Hopefully, this helps others in the future. I know I need it.
Thanks
This is not from a misunderstanding of Rust's module system. Your module_b\mod.rs file is UTF-16 encoded instead of UTF-8 encoded as Rust is expecting.
If you're using VS Code: Change the encoding of a file in Visual Studio Code You can change the encoding by clicking on the UTF-16 LE part of the bottom status bar and selecting Save with encoding and then selecting UTF-8.
If using Vim: How can I change a file's encoding with vim?
This question already has answers here:
How to include files from same directory in a module using Cargo/Rust?
(3 answers)
How do I do a basic import/include of a function from one module to another in Rust 2015?
(3 answers)
Why can't I import module from different file in same directory? [duplicate]
(2 answers)
How do I import from a sibling module?
(1 answer)
Closed 1 year ago.
according to https://stackoverflow.com/a/26435155/5884503, mod something searches for something.rs.
Here's what I'm trying to do based on that:
main.rs
message_socket.rs
mod.rs
body.rs
mod.rs:
mod message_socket;
mod body;
body.rs:
struct Body{}
message_socket.rs:
mod body;
error:
error[E0583]: file not found for module `body`
--> src/message_socket.rs:7:1
|
7 | mod body;
| ^^^^^^^^^
|
= help: to create the module `body`, create file "src/message_socket/body.rs"
It's trying to look inside message_socket which is a file, not a directory.
Why?
This question already has an answer here:
Why do I need to import a trait to use the methods it defines for a type?
(1 answer)
Closed 2 years ago.
I'm stuck on the first example given in the Rust book, the guessing game. I just cannot find the gen_range method on thread_rng() to generate the number. The only methods that show up are fill_bytes, next_u32, next_u64 and try_fill_bytes, and if I try to write it anyway I get an error saying the method doesn't exist. However, when I tried the random function, which according to the documentation is simply a shortcut for thread_rng().gen(), it works. I've tried other functions, updating and reinstalling everything but it still doesn't work and I really don't know what to do.
Welcome to Stack Overflow. In the future, please try to add more information to your question, including relevant links (which doc are you talking about), source code and error messages. This will make it easier for us to give relevant and useful answers.
I'm assuming you're doing something like this:
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
Which gives the following error:
error[E0599]: no method named `gen_range` found for struct `rand::rngs::thread::ThreadRng` in the current scope
--> src/main.rs:4:26
|
4 | let x = thread_rng().gen_range(0, 10);
| ^^^^^^^^^ method not found in `rand::rngs::thread::ThreadRng`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.3/src/lib.rs:212:8
|
212 | fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
| ---------
| |
| the method is available for `std::boxed::Box<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::sync::Arc<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::rc::Rc<rand::rngs::thread::ThreadRng>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use rand::Rng;
|
Note that the Rust compiler is very good in giving suggestions for ways to fix your code. In this case, the last line from the error suggests adding use rand::Rng;, and now it works:
use rand::Rng;
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
This is because the gen_range method is not implemented directly on the ThreadRng struct, but instead it is implemented in the general Rng trait, which makes it automatically available for all random number generators. However methods from traits are only available if the trait itself is available, hence the need to import rand::Rng first.
You can try installing the the following version, works for me in this version.
Add this to your Cargo.toml dependencies:
rand = "0.7.3"
Import:
use rand::Rng;
Usage:
rand::thread_rng().gen_range(0, 10);
I have a small reproduction project which fails to compile. The project can be downloaded here: https://github.com/Jasperav/proc_macro_collision. The error is:
error[E0659]: `proc_macro_call` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
I have 3 libraries and 1 executable in the project:
Lib 1 - parser - parses the proc macro call
Lib 2 - proc_two - returns the literal string as a proc macro call
Lib 3 - proc_one - forwards the macro to proc_two (although it does not have a dependency on proc_two). This is like proc_two also a proc macro.
Relevant code for proc_one:
#[proc_macro_hack]
pub fn one(input: TokenStream) -> TokenStream {
let parse = parse_macro_input!(input as Parser);
let r = parse.lit;
let x = quote! {
two!(#r) // This is the problem I guess...
};
x.into()
}
Executable: calls proc_one (gives compile error).
Relevant code:
use proc_macro_hack::proc_macro_hack;
extern crate proc_one;
extern crate proc_two;
#[proc_macro_hack]
use proc_one::one;
#[proc_macro_hack]
use proc_two::two;
fn main() {
let hi: &'static str = one!("hi");
assert_eq!("hi", hi);
}
I don't understand why the call in the executable is ambiguous, lib 2 and 3 do not dependent on each other. This is the full error:
error[E0659]: `proc_macro_call` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
--> src\main.rs:10:1
|
10 | #[proc_macro_hack]
| ^^^^^^^^^^^^^^^^^^ ambiguous name
...
14 | let hi: &'static str = one!("hi");
| ---------- in this macro invocation
|
note: `proc_macro_call` could refer to the macro defined here
--> src\main.rs:11:15
|
11 | use proc_two::two;
| ^^^
...
14 | let hi: &'static str = one!("hi");
| ---------- in this macro invocation
note: `proc_macro_call` could also refer to the macro defined here
--> src\main.rs:9:15
|
9 | use proc_one::one;
| ^^^
...
14 | let hi: &'static str = one!("hi");
| ---------- in this macro invocation
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
According to proc_macro_hack documentation nested invocations are not supported:
By default, nested invocations are not supported i.e. the code emitted by a proc-macro-hack macro invocation cannot contain recursive calls to the same proc-macro-hack macro nor calls to any other proc-macro-hack macros. Use proc-macro-nested if you require support for nested invocations.
Therefore the code marked by you is the real issue:
let x = quote! {
two!(#r) // This is the problem
};
And there is a suggestion to look at proc-macro-nested "if you require support for nested invocations".