How do I "export" things from a submodule? - module

I'd like to write a mod.rs file like:
pub use foo::*;
mod foo;
pub mod bar;
But I get the error unresolved import foo. What's the correct way to do this?

Here's an MCVE of your problem:
pub mod sub {
use foo::function;
pub mod foo {
pub fn function() {}
}
}
fn main() {}
As Adrian mentions, the solution is to use the keyword self in the use statement:
pub mod sub {
use self::foo::function;
pub mod foo {
pub fn function() {}
}
}
fn main() {}
So, what's going on? The Rust Programming Language describes the problem:
What about the self? Well, by default, use declarations are absolute paths, starting from your crate root. self makes that path relative to your current place in the hierarchy instead.
That is, use foo means to use foo from the root of the crate. use self::foo means to use foo relative to the current module.

Related

How do I place a Rust module in a separate file? [duplicate]

This question already has answers here:
Can't understand Rust module system
(1 answer)
Split a module across several files
(7 answers)
How to use one module from another module in a Rust cargo project?
(3 answers)
Closed 2 years ago.
The code below is adapted from "the book" (rustup docs --book), and works as intended in this form - as a single .rs file. I simply want the module to reside in a separate file. I've read Chapter 7 of "the book", "Managing Growing Projects with Packages, Crates, and Modules". I'm just not getting "it". My notion is that the "main" code belongs in main.rs, and the module may need to be in lib.rs, but the exact forms and placements are still a mystery. The chapter often states to run "cargo new/build whatever", but doesn't state from what directory. Likewise, it states that src/main.rs or src/lib.rs should look like such-and-such for a particular example, but it's not clear (without a full path) if one "src" directory is actually in the same location as another.
So, I imagine that's there more than one way to do this, but I'll be happy with a relatively simple answer. In this instance, I only care that the module is accessible from the main() function seen below.
mod guess_mod {
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess{value}
}
pub fn value(&self) -> i32 {
self.value
}
}
}
use guess_mod::Guess;
fn print_guess_value(guess: Guess) {
println!("The value of the guess is {} ", guess.value());
}
fn main() {
let g = Guess::new(18);
print_guess_value(g);
}
You could create the following folder structure within src:
src
├── guess
│   └── mod.rs
└── main.rs
Your guess module could either live in a file called guess.rs or in a folder named guess/ with a mod.rs inside (as in the structure above).
In your mod.rs (or guess.rs) you could put the content of module):
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
pub fn value(&self) -> i32 {
self.value
}
}
In your main.rs you could use it as follows:
// This declaration will look for a file named `guess.rs` or `guess/mod.rs`
mod guess;
use guess::Guess;
fn print_guess_value(guess: Guess) {
println!("The value of the guess is {} ", guess.value());
}
fn main() {
let g = Guess::new(18);
print_guess_value(g);
}
You run cargo from the root of your folder structure (i.e src).
If the rust book is not clear enough for you, perhaps try Rust by Example: https://doc.rust-lang.org/rust-by-example/mod.html
Maybe you are mixing the concepts of crates and modules. They are somewhat related but different.
Crates are separated units of compilation, distribution, versioning, and dependency management.
Modules are pieces of a crate that are logically separated, with visibility barriers maybe also compiled separately, but finally linked together, and bundled into a crate.
If you talk C, you can see crates as libraries and modules as compilation units. Or if you talk C++ or C# you can see modules as namespaces. Except that executables are also crates, but of a different kind.
Now, how do you create them? The easiest are modules. There are three options:
Modules #1
You write the module inline inside other file:
//src/main.rs
mod foo {
pub fn test() {}
}
fn main() {
foo::test();
}
Modules #2
You write the module in a separated file, in the same source directory:
//src/main.rs
mod foo;
fn main() {
foo::test();
}
//src/foo.rs
pub fn test() {}
You can add submodules of foo in a subdirectory named src/foo.
Modules #3
You write the module in a subdirectory, the file must be named mod.rs:
//src/main.rs
mod foo;
fn main() {
foo::test();
}
//src/foo/mod.rs
pub fn test() {}
You can use the subdirectory src/foo to create submodules of foo.
Crates
The easiest way to link a crate is to add it to the [dependencies] section of your Cargo.toml. Then cargo is just magic.
When you create a crate, it may have 0 or 1 libraries and 0 or many binaries. A usual pattern is to create dual Cargo project, that has library and a binary all together. Then you will have a src/main.rs and a src/lib.rs files. The dependency is handled automatically.
//src/main.rs
fn main() {
foo::test();
}
//src/lib.rs
pub fn test() {}
For more complex projects you can split your source into several crates, and handle all them together into a workspace, but I think that is out of scope of this question.

Why does Rust allow public access to a private module?

I am a newbie in Rust and just started to read the programming book while doing rustling exercises. In the modules2.rs exercise, I am confused why the following code compiles:
mod delicious_snacks {
pub use self::fruits::PEAR as fruit;
pub use self::veggies::CUCUMBER as veggie;
mod fruits {
pub const PEAR: &'static str = "Pear";
pub const APPLE: &'static str = "Apple";
}
mod veggies {
pub const CUCUMBER: &'static str = "Cucumber";
pub const CARROT: &'static str = "Carrot";
}
}
fn main() {
println!(
"favorite snacks: {} and {}",
delicious_snacks::fruit,
delicious_snacks::veggie
);
}
Specifically, I am wondering why it is OK for main to access private fruits and veggies modules just because their uses are marked pub? On the other hand, if we don't use pub use, then, without making fruits and veggies pub, one cannot access e.g., delicious_snacks::fruits::PEAR in main because fruits is not public. Similarly, if we don't use pub for const PEAR, even with pub use self::fruits::PEAR as fruit, we still cannot compile delicious_snacks::fruit. So what exactly is the rule here? Why is it OK to not mark pub for those modules?
The constants PEAR/APPLE/CUCUMBER/CARROT are marked as pub, which means they can be accessed from everywhere, even if they're in a private module.
This is a common technique, to implement something in a private module, and re-export only the things we want, e.g.
// actual implementation is here
mod foo_internal;
pub use foo_internal::{Foo, Bar};
This still maintains privacy/visibility, since Foo and Bar can't be re-exported if they're private.
You can also create a new module hierarchy for users of your library:
mod foo_internal;
pub mod foo {
pub use foo_internal::Foo;
}
pub mod bar {
pub use foo_internal::Bar;
}
This clearly separates the public interface from implementation details, so the implementation can be freely refactored without changing the public modules.

error[E0277]: the trait bound `my_struct::MyStruct: my_trait::MyTrait` is not satisfied

I am writing projects in Rust to help me learn it, but am having trouble implementing a trait and then using a function required by that trait when a type implementing it is passed to a function.
To try and narrow down the problem, I've created an MVCE. Here is the error message and code:
error message
error[E0277]: the trait bound `my_struct::MyStruct: my_trait::MyTrait` is not satisfied
--> src\main.rs:12:5
|
12 | invoke_print_i32(&MyStruct { });
| ^^^^^^^^^^^^^^^^ the trait `my_trait::MyTrait` is not implemented for `my_struct::MyStruct`
|
note: required by `invoke_print_i32`
--> src\main.rs:7:1
|
7 | fn invoke_print_i32<T: MyTrait>(instance: &T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
my_trait.rs
pub trait MyTrait {
fn print_i32(&self, n: i32);
}
my_struct.rs
#[path = "my_trait.rs"]
mod my_trait;
use my_trait::MyTrait;
pub struct MyStruct { }
impl MyTrait for MyStruct {
fn print_i32(&self, n: i32) {
println!("n: {}", n);
}
}
main.rs
mod my_trait;
use my_trait::MyTrait;
mod my_struct;
use my_struct::MyStruct;
fn invoke_print_i32<T: MyTrait>(instance: &T) {
instance.print_i32(42);
}
fn main() {
invoke_print_i32(&MyStruct { });
}
My attempts at researching the problem mostly found people trying to implement fairly standard Rust traits, for example:
How can I implement Rust's Copy trait?
The trait bound is not satisfied in Rust
The trait bound is not satisfied
I also read somewhere that I needed to reimplement the trait for variables such as &MyStruct, but my attempts to do so didn't resolve the issue.
extra info
rustc -V outputs rustc 1.36.0 (a53f9df32 2019-07-03)
cargo -V outputs cargo 1.36.0 (c4fcfb725 2019-05-15)
Platform/OS is Windows 10 Pro (x86_64)
question
What am I doing wrong; how can I correctly implement the trait?
You have declared the module my_trait twice, so there are actually two different traits called MyTrait: crate::my_trait and crate::my_struct::my_trait.
You don't need to declare the module in the my_struct module. Instead, use the module that is declared in the crate root, with:
use crate::my_trait::MyTrait;
Or
use super::my_trait::MyTrait;

Including a file from another that is not main.rs nor lib.rs

(I'm a Rust beginner) I have three files : main.rs, board.rs and case.rs.
I want to include case.rs into board.rs, and board.rs into main.rs, so the board uses the case, and we can access the board in main.
I've successfully added the board into main, but the way I did doesn't seem to work for the second part.
I've tried to encapsulate every file's content into "mod {}" but it doesn't change the problem.
Also I tried every combinations of "mod" and "use".
Every file is in the folder src/, and I'd like them not to move from there if possible.
main.rs
mod board;
fn main() {
let mut b: Board = Board::new();
}
board.rs
mod case;
pub struct Board {
board: [ Case; 9 ]
}
// There is also the impl part of course, let's keep it short
case.rs
pub enum Case { Empty, Full(Player) }
Using VSCode with the Rust plugin, the "case" word on the first line of the board.rs file is underlined red, and it says :
"src/case.rs
file not found for module case
help: name the file either board\case.rs or board\case\mod.rs inside the directory "src""
Why doesn't it search in the current directory?
Your files could look like as follows:
case.rs:
#[derive(Clone, Copy, Debug)]
struct Player;
#[derive(Clone, Copy, Debug)]
pub enum Case {
Empty,
Full(Player)
}
board.rs:
use crate::case::Case;
#[derive(Debug)]
pub struct Board {
board: [ Case; 9 ]
}
impl Board {
pub fn new() -> Self {
Self { board: [Case::Empty; 9] }
}
}
main.rs:
mod case;
mod board;
use crate::board::Board;
fn main() {
println!("{:?}", Board::new());
}
Basically you create a crate (a binary one, because of your main.rs) and that crate can have modules. A module can be a file, or it can be a folder as well (if it happens to have a mod.rs). (And for the sake of completeness, it could also be an inline module without direct relation to the file system.)
Your mod statements (the ones which are indicating files and folders, not the ones which you use to create inline modules) should either be placed at the top level of your crate (e.g. in your main.rs or lib.rs) or at the module levels (in your mod.rs files) depending on the desired structure.
For further info on this, please read the The Rust Programming Language book's relevant chapter: Packages and Crates.

Rust Can't import Singleton From global space into another module in another file

Using the lazy_static library to create a singleton. I am unable to access that singleton in a module in another file. If the module is defined below the main function I can access it fine.
Given a main file such as the following, test_stuff can access gamedata fine:
extern crate gamedata;
#[macro_use]
extern crate lazy_static;
lazy_static! {
pub static ref GAMEDATA: &'static str = "I am a test STrings";
}
fn main() {
println!("Game Data:{}",*GAMEDATA);
let obj = gamedata::readinginstatic::readinginstatic {
structure:"working".to_string()
};
obj.print_static();
}
mod test_stuff {
use ::GAMEDATA;
fn printthing() {
println!("herenow:{}", *GAMEDATA);
}
}
With a lib.rs file such as:
pub mod readinginstatic;
And a module in another file readinginstatic.rs as described below:
use ::GAMEDATA;
pub struct readinginstatic {
pub structure:String,
}
impl readinginstatic {
pub fn print_static(&self) {
println!("In Print static width:{}", *::GAMEDATA);
}
}
I get the error:
not found in the crate root
When trying to import GAMEDATA.
Is it possible to access a lazy_static singleton in another module if it is defined in another file?
To insure I have provided a Minimal, Complete, and Verifiable example here is my whole example code on GitHub: https://github.com/camccar/moduleError
::GAMEDATA refers to some value called GAMEDATA in the crate root of the gamedata crate. However where you defined GAMEDATA was not in that crate, it was in your main.rs file which has gamedata as a dependency.
So what you're trying to do here is reach out of a crate use something from the crate that is depending on you, which I'm not sure but I don't think is allowed.
You could consider inverting this and instead initialising GAMEDATA inside your gamedata crate instead and if you need to use it in main you can just use it normally:
extern crate gamedata;
use gamedata::GAMEDATA;
fn main(){
println!("Game Data:{}", *GAMEDATA);
...
}
Alternatively if GAMEDATA is not something your game data crate should know how to define, you could construct it inside main and pass it to some function in the gamedata crate as a parameter.