Split main.rs into files that refer each other - module

I have the following structure:
|-- Cargo.toml
|-- src
| |-- file1.rs
| |-- file2.rs
| `-- main.rs
src/file1.rs
pub fn function1() {}
src/file2.rs
// ERROR (1): error[E0583]: file not found for module `file1`
// mod file1;
use crate::file1;
pub fn function2() {
file1::function1();
}
src/main.rs
// ERROR (2): no `file1` in the root
// use crate::file1;
mod file1;
mod file2;
fn main() {
file1::function1();
file2::function2();
}
Basically, I have a different way to import function1, depending on the fact that I am in the crate root or in an arbitrary Rust file (please see ERROR (1) and ERROR (2)).
I am a bit lost on how Rust manages arbirary files: they behave differently from the root crate, where a simple mod keyword does the trick.
So, the mentioned answer for which this is a duplicate only partially only answers how to refer a file from the crate root, not why referring the same file from another one should be different (use crate::<filename>).

Related

How do I use a module from multiple unit test modules?

I have two modules with unit tests and I want to access constants/variables with expected test results from both of those modules.
File: src/lib.rs
mod other;
#[cfg( test )]
mod tests {
mod expected;
use crate::tests::expected::FOUR;
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!( result, FOUR );
}
}
File: src/other.rs
#[cfg( test )]
mod tests {
use crate::tests::expected::EIGHT;
#[test]
fn it_works() {
let result = 4 + 4;
assert_eq!( result, EIGHT );
}
}
File src/tests/expected.rs
pub const FOUR: i32 = 4;
pub const EIGHT: i32 = 8;
From src/lib.rs I can access the constants within expected.rs. But this is not true from src/other.rs. I get the follwing error:
error[E0603]: module `expected` is private
--> src/other.rs:3:20
|
3 | use crate::tests::expected::EIGHT;
| ^^^^^^^^ private module
|
note: the module `expected` is defined here
--> src/lib.rs:5:2
|
5 | mod expected;
| ^^^^^^^^^^^^^
I have no idea how to make expected public. Where would I place expected.rs or how would I make it accessible from the test code of other modules of the library?

rust - trouble importing module

I have encountered a strange error preventing one of my files from importing a module
This is my src directory
src/
functions.rs
main.rs
unit_test.rs
Here is unit_test.rs
mod functions;
#[cfg(test)] // only compiles on test
// make module f_test
mod f_test{
// mark function as test
#[test]
#[should_panic]
fn test_basic() {
assert_eq!();
panic!("oh no");
}
#[test]
fn test_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
#[test]
#[should_panic]
fn test_bad_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
}
When I try to run cargo test I get this
[vinessa#komputilo unitTest]$ cargo test
Compiling unitTest v0.1.0 (/home/vinessa/Dev/Rust/unitTest)
error[E0583]: file not found for module `functions`
--> src/unit_test.rs:1:5
|
1 | mod functions;
| ^^^^^^^^^
|
= help: name the file either unit_test/functions.rs or unit_test/functions/mod.rs inside the directory "src"
Strange thing, if I add "mod functions;" to main.rs, cargo won't complain about that file, only for unit_test.rs
I am lost please help
I think you want to declare mod functions in main.rs:
mod unit_test;
mod functions; // declare this module here
fn main() {
println!("Hello, world!");
}
I think you want this in unit_test.rs:
#[cfg(test)] // only compiles on test
// make module f_test
mod f_test{
use crate::functions; // use module here
// mark function as test
#[test]
#[should_panic]
fn test_basic() {
assert_eq!(1, 1);
panic!("oh no");
}
#[test]
fn test_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
#[test]
#[should_panic]
fn test_bad_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
}
Additionally, your #[should_panic] is incorrect as it stands.
Obligatory link: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html

Why Isn't This Module Visible?

I'm coding a hash in Rust for practice. The code looks like this:
pub fn get_fnv1a32(to_hash:&str) -> u32{
const OFFSET_BASIS:u32 = 2_166_136_261;
const PRIME:u32 = 16_777_619;
if !to_hash.is_empty(){
let mut hash = OFFSET_BASIS;
for b in to_hash.bytes(){
hash = hash ^ (b as u32);
hash = hash.wrapping_mul(PRIME);
}
hash
}
else
{
0
}
}
And this is the code I'm trying to use to test this:
mod fnv;
#[cfg(test)]
mod tests {
#[test]
fn get_correct_hash(){
assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
}
#[test]
fn hash_handles_empty_string_correctly(){
assert_eq!(0, fnv::get_fnv1a32(""));
}
}
The test code is in lib.rs and the get_fnv1a32 function is in fnv.rs. They're both in the same directory. But when I try to run cargo test I keep getting these messages:
Compiling hashes v0.1.0 (U:\skunkworks\rust\hashes)
warning: function is never used: `get_fnv1a32`
--> src\fnv.rs:1:8
|
1 | pub fn get_fnv1a32(to_hash:&str) -> u32{
| ^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:7:32
|
7 | assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
| ^^^ use of undeclared type or module `fnv`
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:12:23
|
12 | assert_eq!(0, fnv::get_fnv1a32(""));
| ^^^ use of undeclared type or module `fnv`
error: aborting due to 2 previous errors
I can't figure out what I'm doing wrong. I tried changing the mod fnv; line at the top to pub mod fnv; and that gets rid of the dead code warning but it doesn't fix the two errors. What do I need to do to get the get_fnv1a32 function to be visible in the lib.rs file?
Not that I would think it would matter but the version of rustc is rustc 1.41.0 (5e1a79984 2020-01-27)
The test module is separate from the outer module. Add
use super::*;
or an equivalent statement like use crate::fnv inside the tests module to make the fnv module visible.

How to split the code in modules in Rust? [duplicate]

This question already has an answer here:
Can't understand Rust module system
(1 answer)
Closed 3 years ago.
I am reading the Rust Book, I am in the chapter 7.2, but I must be missing something, because I cannot organize my code in modules, the compiler (rustc 1.32.0) keeps giving me errors.
What I have read
I read rustc --explain E0433, which is the advice of the compiler, but I still cannot solve it.
I checked Rust by examples, and it seems that my code is correct, (my/mod.rs is using module my/nested.rs in its own folder)
I found some info on Internet, but it is of 4 years ago, and include the use of use, which is not yet in the book.
I also checked this question, but I am not using folders, and again, it gets away from the book explanation.
Minimal example
This is a minimal example that tries to mimic the "sound" example of the book, there is only two files: /src/main.rs and /src/m.rs.
main.rs
mod m;
fn main() {
let st_0 = m::St::new();
}
m.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
And this is what cargo tells me:
Compiling min v0.1.0 (/home/user/min)
error[E0433]: failed to resolve: could not find `St` in `m`
--> src/main.rs:3:19
|
3 | let st_0 = m::St::new();
| ^^ could not find `St` in `m`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
error: Could not compile `min`.
To learn more, run the command again with --verbose.
When you have everything in one file, like this:
main.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
mod m;
fn main() {
let st_0 = m::St::new();
}
you wrap the module with the
pub mod mode_name {
//code...
}
Once you put the module in another file, that wrapping goes away. The Rust book, shows it, but if you don't look carefully or if you are programming drunk, you may get confused with the pub mod instrument {...} of the nested module.
So m.rs has to look like this:
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}

How can I declare and use a Perl 6 module in the same file as the program?

Sometimes I don't want multiples files, especially if I'm playing around with an idea that I want to keep a nice structure that can turn into something later. I'd like to do something like this:
module Foo {
sub foo ( Int:D $number ) is export {
say "In Foo";
}
}
foo( 137 );
Running this, I get a compilation error (which I think is a bit odd for a dynamic language):
===SORRY!=== Error while compiling /Users/brian/Desktop/multi.pl
Undeclared routine:
foo used at line 9
Reading the Perl 6 "Modules" documentation, I don't see any way to do this since the various verbs want to look in a particular file.
Subroutine declarations are lexical, so &foo is invisible outside of the module's body. You need to add an import statement to the mainline code to make it visible:
module Foo {
sub foo ( Int:D $number ) is export { ... }
}
import Foo;
foo( 137 );
Just for the record, you could also manually declare a &foo variable in the mainline and assign to that from within the module:
my &foo;
module Foo {
sub foo ( Int:D $number ) { ... } # no export necessary
&OUTER::foo = &foo;
}
foo( 137 );