I am used to organising files in separate directories depending on the problem domain (for example grouping image processing stuff together, IO stuff in another directory etc). I am not sure if this way or organisation is even recommended in Rust.
I have setup my project in multiple directories:
- helloworld
- Cargo.toml
- src
- main.rs
- test
- one.rs
I am trying to use a function from one.rs in main.rs
one.rs
fn test() {
println!("Calling test...");
}
main.rs
use test::one::*;
fn main() {
println!("Hello, world!");
test();
}
This results in a compile time error:
error[E0432]: unresolved import `test::one::*`
--> src/main.rs:1:5
|
1 | use test::one::*;
| ^^^^^^^^^^^^^ Maybe a missing `extern crate test;`?
error[E0425]: cannot find function `test` in this scope
--> src/main.rs:6:5
|
6 | test();
| ^^^^ not found in this scope
Looking at some online projects, it seems like something like this should be possible.
It is possible, however you need to inform your code about additional module that is inside your code using:
mod test;
And then create additional file
// src/test/mod.rs
pub mod one;
Related
It seems like I haven't fully understood Rust's module system yet. I have the following file structure:
module_issue
|_Cargo.toml
|_src
|_main.rs
|_lib.rs
|_bindings
|_mod.rs
This code compiles and runs without issues:
// file: bindings/mod.rs
pub fn say_hello() {
println!("Hello from the bindings module!");
}
// file: lib.rs
mod bindings;
pub fn try_bindings() {
bindings::say_hello();
}
// file: main.rs
use module_issue;
fn main() {
module_issue::try_bindings();
}
However, if I make a sub-module in lib.rs and try to use bindings::say_hello() from there, I get a compiler error. Here's what lib.rs now looks like:
// file: lib.rs
mod bindings;
pub fn try_bindings() {
bindings::say_hello();
}
mod debugging {
pub fn try_bindings_debug() {
bindings::say_hello(); // <- can't find 'bindings' - shouldn't it be in scope?
}
}
and this is the error I get:
error[E0433]: failed to resolve: use of undeclared type or module `bindings`
--> src\lib.rs:10:9
|
10 | bindings::say_hello();
| ^^^^^^^^ use of undeclared type or module `bindings`
error: aborting due to previous error
In lib.rs, I also tried replacing mod bindings; with use crate::bindings;, but that resulted in a different error:
error[E0432]: unresolved import `crate::bindings`
--> src\lib.rs:2:5
|
2 | use crate::bindings;
| ^^^^^^^^^^^^^^^ no `bindings` in the root
error[E0433]: failed to resolve: use of undeclared type or module `bindings`
--> src\lib.rs:10:9
|
10 | bindings::say_hello();
| ^^^^^^^^ use of undeclared type or module `bindings`
error: aborting due to 2 previous errors
My understanding of the module system was as follows: If I bring a module A into the scope of module B, then the public members of A will be accessible in B and all the sub-modules of B. In this case, I bring the bindings module into the scope of the library root. The debugging module is a sub-module of that root, so it should have access to bindings as well. Can you tell me where I went wrong? My priority isn't really to solve the problem, but to understand why this doesn't work.
I'm working on Windows 10, with the following toolchain:
cargo 1.39.0 (1c6ec66d5 2019-09-30)
rustc 1.39.0 (4560ea788 2019-11-04)
If I bring a module A into the scope of module B, then the public members of A will be accessible in B and all the sub-modules of B.
This assertion is incorrect. The scope of each module contains only things defined or used in the module itself, not in its parents.
You can, however, pull items from the parent explicitly:
mod debugging {
use super::bindings; // referring to library root
pub fn try_bindings_debug() {
bindings::say_hello();
}
}
Playground
I'd like to write a server that resizes a huge image. Since loading it on every request would take a lot of time, I decided to pre-load it. Unfortunately I got the following error:
Compiling hello_world v0.0.0 (/tmp/Rocket/examples/hello_world)
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> examples/hello_world/src/main.rs:9:35
|
9 | static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> examples/hello_world/src/main.rs:9:35
|
9 | static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
error: Could not compile `hello_world`.
To learn more, run the command again with --verbose.
Here's the code:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[cfg(test)] mod tests;
extern crate image;
static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
#[get("/")]
fn hello() -> Vec<u8> {
"".into()
}
fn main() {
rocket::ignite().mount("/", routes![hello]).launch();
}
To compile it, you'll need rocket installed based on its latest Github checkout (currently: 831d8dfbe30dd69f0367a75361e027127b2100e1) and image crate.
Is it possible to create such a global variable? If not, do I have any other options?
EDIT: this was flagged as a duplicate of this question, but as Boiethios showed, this specific case is better solved by Rocket's API.
If you want to share something in Rocket, you will have to use a managed state:
Say to Rocket you want to manage the resource:
let image = image::open("/home/d33tah/tmp/combined.png").unwrap();
rocket::ignite().manage(image);
Retrieve it in the routes where you need it:
#[get("/foo")]
fn foo(image: State<DynamicImage>) {
// Can use `image`.
}
I don't understand mod or use; I suppose that mod will import files into the project and use will use them.
I have a project with this hierarchy:
.
|-- Cargo.lock
|-- Cargo.toml
|-- src
| |-- display.rs
| |-- list.rs
| |-- main.rs
| |-- parser.rs
| |-- sort.rs
Why do I need use in list.rs and not in main.rs? I use the function sorting() and print_files() in list.rs like I use the function parse() and listing() in main.rs.
main.rs
mod parser; // Ok
mod list; // Ok
mod sort; // Ok
mod display; // Ok
// use parser;// The name `parser` is defined multiple times
fn main() {
parser::parse();
list::listing();
}
list.rs
//mod sort; // file not found in module `sort`
//mod display; // file not found in module `display`
use sort; // Ok
use display; // Ok
pub fn listing() {
parcours_elements();
sort::sorting();
display::print_files();
}
fn parcours_elements() {
}
sort.rs
pub fn sorting() {
}
display.rs
pub fn print_files() {
}
First things first, go back and re-read mod and the Filesystem. Then read it again. For whatever reason, many people have trouble with the module system. A ton of good information is contained in The Rust Programming Language.
I suppose that mod will import files into the project and use will use them.
mod foo "attaches" some code to the crate hierarchy, relative to the current module.
use bar avoids needing to type out the full path to something in the crate hierarchy. The path bar starts from the root of the crate.
When you have mod parser in main.rs, you are saying
go find the file parser.rs1 and put all the code in that file in the hierarchy relative to the crate root2.
When you try to then add use parser in main.rs, you are saying
go to the root of the hierarchy, find the module parser, and make it available here (at the crate root) as the name parser.
This already exists (because that's where the module is defined!), so you get an error.
When you have use sort is list.rs, you are saying
go to the root of the hierarchy, find the module sort, and make it available here (inside the module list) as the name sort.
This works fine.
1 Or parser/mod.rs.
2 Because main.rs (or lib.rs) are the crate roots.
See also:
Why is there a mod keyword in Rust?
Split a module across several files
How to include module from another file from the same project?
I am trying to configure an example project in Rust to work.
My structure is:
src/potter.rs
tests/tests.rs
And my Cargo.toml
[package]
name = "potter"
version = "0.1.0"
authors = ["my name"]
[dependencies]
My potter.rs contains:
pub mod potter {
pub struct Potter {
}
impl Potter {
pub fn new() -> Potter {
return Potter {};
}
}
}
And my tests.rs contains:
use potter::Potter;
#[test]
fn it_works() {
let pot = potter::Potter::new();
assert_eq!(2 + 2, 4);
}
But I receive this error:
error[E0432]: unresolved import `potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^ Maybe a missing `extern crate potter;`?
error[E0433]: failed to resolve. Use of undeclared type or module `potter`
--> tests/tests.rs:6:19
|
6 | let pot = potter::Potter::new();
| ^^^^^^ Use of undeclared type or module `potter`
warning: unused import: `potter::Potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
If I add extern crate potter;, it doesn't fix anything...
error[E0463]: can't find crate for `potter`
--> tests/tests.rs:1:1
|
1 | extern crate potter;
| ^^^^^^^^^^^^^^^^^^^^ can't find crate
Go back and reread The Rust Programming Language about packages, crates, modules and the filesystem.
Common pain points:
Every programming language has its own way of dealing with files — you cannot just assume that because you've used any other language that you will magically get Rust's take on it. That's why you should go back and re-read the book chapter on it.
Each file defines a module. Your lib.rs defines a module of the same name as your crate; a mod.rs defines a module of the same name as the directory it's in; every other file defines a module of the name of the file.
The root of your library crate must be lib.rs; binary crates may use main.rs.
No, you really shouldn't try to do non-idiomatic filesystem organization. There are tricks to do most anything you want; these are terrible ideas unless you are already an advanced Rust user.
Idiomatic Rust does not generally place "one type per file" like many other languages. Yes, really. You can have multiple things in one file.
Unit tests usually live in the same file as the code it's testing. Sometimes they will be split out into a file containing the submodule, but that's uncommon.
Integration tests, examples, benchmarks all have to import the crate like any other user of the crate and can only use the public API.
To fix your issue:
Move your src/potter.rs to src/lib.rs.
Remove pub mod potter from src/lib.rs. Not strictly required, but removes needless nesting of modules.
Add extern crate potter to your integration test tests/tests.rs (Only needed if you are using Rust 2015).
filesystem
├── Cargo.lock
├── Cargo.toml
├── src
│ └── lib.rs
├── target
└── tests
└── tests.rs
src/lib.rs
pub struct Potter {}
impl Potter {
pub fn new() -> Potter {
Potter {}
}
}
tests/tests.rs
use potter::Potter;
#[test]
fn it_works() {
let pot = Potter::new();
assert_eq!(2 + 2, 4);
}
I'm trying to write a procedural macro that implements a #[derive()] trait for a struct. In the generated implementation code I need to use AnyMap.
To avoid multi crate imports, and based on what I read in some other crate's code (namely Serde) I put my generated code into a const _IMPL_xxx_FOR_xxx : () = { /* generated code */ }; block but it fails to compile.
I was able to replicate my issue with the following code
const BLOCK_1: () = {
extern crate anymap;
use anymap::AnyMap;
};
const BLOCK_2: () = {
extern crate anymap;
use anymap::AnyMap;
};
fn main() {
println!("foo");
}
The compile error I'm getting is the following:
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:3:9
|
3 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:9:9
|
9 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
Is it an issue specific to AnyMap? Would you know of any way to fix this (including maybe a different approach to generating procedural macro code if the pattern I'm using is not recommended?
I can replicate this on the playground using simply
const A: () = {
extern crate core;
use core::option::Option;
};
fn main() {}
However, it appears only the use statement is broken, and I can still use items from core, but I have to name them explicitly each time:
const A: () = {
extern crate core;
do_stuff!(core::option::Option)
};
The reason is that use statements typically assume a path relative to the root, and there is no way to explicitly name the block you are in (self refers to the current module unfortunately).
Here's a better workaround - as I said before, Rust uses self to refer to the current module, so you can just put a module in your code block and then have the use statements reference self.
In your case it would be:
const BLOCK_1: () = {
mod inner {
extern crate anymap;
use self::anymap::AnyMap;
}
};
On the specific issue of making this work for procedural macro, a suggested solution was to reexport the needed crate as part of the crate containing the derive macro (or the one containing the class I'm trying to export) using something like pub extern crate anymap and then use <my_crate>::anymap::AnyMap;