I have a "use" that doesn't work even though it's in my src

126 Views Asked by At

The directory that contains everything is called p, in p is:

.git
.gitignore
Cargo.lock
Cargo.toml
todo.md
src
target

in src is:

action_functions.rs
execute_action_functions.rs
lib.rs
main.rs
network.r

in network.rs:

pub mod network{
        use rand::Rng    //to generate random numbers
    //use crate::action_functions::{/*insert all the action functions */};
    use rand_distr::{Normal, Distribution}; //to generate different dist. of random numbers
    use serde::{Serialize, Deserialize};    //to save/load my neural network
    use std::fs::File;
    use std::io::{BufReader, BufWriter};
    use chrono::Utc;            //for timestamp
    use std::path::Path;        //for help in representing file paths

then I have a bunch of pub structs then I have impl NeuralNetwork { inside pub mod network with a bunch of pub functions.

in Cargo.toml:

[package]
name = "p"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.5"
rand_distr = "0.4.3"
serde_json = "1.0.108"
serde = {version = "1.0.193", features = ["derive"]}
chrono = "0.4"

in main.rs:

use crate::network::NeuralNetwork;
fn main() -> std::io::Result<()> {
    let mut network = NeuralNetwork {
        layers: Vec::new(),
        weights: Vec::new(),
        biases: Vec::new(),
    };
    network.initialization(10, 10, 2); // Initialize with your parameters

    // Print the network
    network.print();

    // Save the network
    network.save_v2()?;

    // Load the network
    //let path = "D:\\Downloads\\PxOmni\\rust_save_states\\your_file_name"; // Replace with your file path
    //let loaded_network = NeuralNetwork::load(path)?;

    // Print the loaded network
    //loaded_network.print();

    Ok(())

}

in lib.rs is:

pub mod network;
//pub mod Network;
pub mod action_functions;
pub mod execute_action_functions;

everything is code commented out in action_functions.rs except for: pub mod action_functions {} with everything code commented inside of action_functions, and the same goes for execute_action_functions. Just for transparency this is my execute_action_functions.rs: pub mod execute_action_functions {}

and there's no errors detected by rust-analzer anywhere and no compilation errors. Except for this:

error[E0432]: unresolved import `crate::network`
 --> src/main.rs:5:12
  |
5 | use crate::network::NeuralNetwork;
  |            ^^^^^^^
  |            |
  |            unresolved import
  |            help: a similar path exists: `p::network`

And in main whenever I do: use crate::p::network::NeuralNetwork;

it says:

error[E0433]: failed to resolve: could not find `p` in the crate root
 --> src\main.rs:5:12
  |
5 | use crate::p::network::NeuralNetwork;
  |            ^ could not find `p` in the crate root

For more information about this error, try `rustc --explain E0433`.
error: could not compile `p` (bin "p") due to previous error

I then tried to add a [[bin]] and do cargo run --bin your_binary_name and same error:

[[bin]]
name = "your_binary_name"
path = "src/main.rs"

I even tried adding:

[lib]
path = "src/lib.rs"

and no change.

2

There are 2 best solutions below

0
Chayim Friedman On

You have two mistakes here.

The first is that lib.rs and main.rs are two different crates. If you want to access lib.rs from main.rs, you cannot do that with crate because it's not the same crate; you have to use the crate name (p).

The second is that pub mod network; in lib.rs already creates a module network, if you do pub mod network { ... } inside network.rs you crate a nested module: p::network::network.

0
Todd On

Some Basics on Structuring a Project Into Multiple Files

I've run into this headache myself when I was first learning Rust. And had to figure out how it worked through some experimentation. Here are my learnings from way back boiled down to simplicity.

The lib.rs and main.rs Files

Below I mention the main.rs and lib.rs files. Which of these files your project uses depends on the type of project. For projects with the goal of creating a shared crate - or library - other projects can be linked to, you'll use the lib.rs file to adjust the access of items in modules within the project. For an executable project, you'll use main.rs for this purpose.

A project can have both of these files, which I believe results in the compiler producing a shared library crate, and also producing an executable binary that can be run from the command line. Why confuse things though. I recommend creating a shared lib crate, and then moving the executable program to another project that links to the crate.

Recognizing the Need to Partition a Project

Say you have one big main.rs or lib.rs file full of various structs. And it's becoming an effort to scroll up and down as you make changes. You can split this file up into separate module files, which are just files with names other than "lib.rs" or "main.rs".

The content of these files are implicitly already contained in their own module namespaces of the same names as the files they reside in, so there's no need to explicitly add mod mynewmodule { ... } inside these files.

So, you want to move all things related to your WindowScreen struct off into another file because it's beginning to explode in LOC because window screens are highly technical, feature rich, pieces of equipment.

Doing the Partitioning

So you move this all into a "window_screen.rs" file that you place at the same level as your lib.rs file. I'm not going to cover how to create a nested folder hierarchy for a project - why make things complicated? Anyway, here's the file:

window_screen.rs

pub struct WindowScreen {
    // Tons of attributes...
}
impl WindowScreen {
    // Item is "pub" so it can be accessible within the same project,
    // or outside project, if the lib.rs or main.rs file allows it.
    pub fn new() -> Self {
        Self { ... }
    }
    // Example of crate level scope modifier.
    pub(crate) fn only_called_within_project() -> bool {
        true
    }
    // Tons of other methods...
}

That just reduced your lib.rs file by half the lines of code. So much more manageable now. But how do you refer to items in it from within lib.rs, and also from the "window.rs" file that you want to create and move your Window struct to?

After creating the window.rs file, that holds the Window struct which sometimes needs to hold an instance to a WindowScreen you need to make the members of window_screen.rs accessible to other files in the project by adding a line to lib.rs (or main.rs depending on project type).

lib.rs (or main.rs)

mod window_screen;

There that was simple. Now you can refer to WindowScreen from window.rs like so.

window.rs

use crate::window_screen::WindowScreen; // <-- add this.

fn takes_screen(ws: WindowScreen) { ... }

Now suppose you want to flatten the nesting of namepaces in the project to make things simpler for users of the crate. You can make the WindowScreen struct part of the project's base namespace by adding a use window_screen::WindowScreen; statement to the lib.rs file.

lib.rs (or main.rs)

mod window_screen;
use window_screen::WindowScreen; // <-- flattens WindowScreen into base namespace.

Now the other file in the project doesn't need to prefix it with its file module to access it.

window.rs

use crate::WindowScreen;

As mentioned, using the lib.rs file to pull items from other files within the project into the main namespace can simplify things for other developers who use your crate.

If, for instance, something that is obviously a primary struct of the crate is implemented in a file other than lib.rs, you may want to pull it into the main namespace so users can simply refer to it from the crate's primary namespace. Say the name of the crate is great-windows, they could access the WindowScreen with:

uses_crate.rs

use great_windows::WindowScreen;

The above won't work unless the WindowScreen struct is made public within the crate's lib.rs file despite whatever scope keyword was added to it within its own file. So to make it accessible to crate users, we adjust its related lines in lib.rs.

lib.rs (shared crates generally only use a lib.rs file)

mod window_screen;
pub use window_screen::WindowScreen; // "pub" added.

If we wanted to make the window_screen namespace accessible outside the crate, we could also modify that line too: pub mod window_screen;. WindowScreen would then be accessible with or without prefixing with window_screen::.

Items don't have to be flattened in to the crate's primary namespace if it doesn't seem logical to do so. In that case, we would have to make the mod window_screen line within lib.rs pub to make WindowScreen accessible via great_windows::window_screen::WindowScreen;.

And that about covers the basics needed to partition a project into multiple files.