Can't compile project when using modules in multiple files: "imports can only refer to extern crate names passed with --extern" - module

I have main.rs and bear.rs under the src directory. Every time I compile, the compiler points to E0658. I've read the docs for E0658, and it tells me that this is an unstable feature.
main.rs
mod bear;
use bear::factory::make_bear;
fn main() {
println!("Hello, world!");
let bear = make_bear();
}
bear.rs
pub mod factory {
pub fn make_bear() -> Bear {
// code to instantiate Bear struct.
}
}
When I compile this code I get this from the compiler:
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
--> src/main.rs:1:5
|
1 | use bear::factory::make_bear;
| ^^^^
...
8 | / mod bear {
9 | | pub mod factory {
10 | | pub fn make_bear() -> Bear {
11 | | // code to instantiate Bear struct.
12 | | }
13 | | }
14 | | }
| |_- not an extern crate passed with `--extern`
|
Do I have to wait for consensus among the Rust community, or is there something I can do right now besides the inconvenient suggestion in the docs?

Change
use bear::factory::make_bear;
to
use crate::bear::factory::make_bear;
This was a change in the 2018 edition of Rust. I won't recreate everything on this page, but I can say that the motivation for this change is twofold, one is to stop requiring the extern crate bear; directives, while also removing the ambiguities that might arise in the case that you have both a local module name bear and also a dependency on an external crate also named bear.

Related

Using conditionally compiled functions in rust benchmarks

Before I begin, let me note that I think there have been many related questions and answers, all of which proved useful to me. However, I couldn't find anyone who thoroughly described a method to do everything I wanted, so I thought I would document the problem and my solution and ask if there were better approaches.
Let's suppose that I have some slow--but definitely correct--code to perform a certain task that I keep in my project to test a faster implementation. For concreteness, define:
pub fn fast(x: T) -> U {
// does stuff and eventually returns a value `out`
// ...
debug_assert_eq!(out, slow(x))
out
}
#[cfg(any(test, debug_assertions))]
pub fn slow(x: T) -> U { ... }
This is all fine and good. However, now suppose that I would like to add some benchmarks to demonstrate how good my fast implementation is...
Attempt 1: Criterion
I think that a standard way to set up benchmarking is to put a benches/ directory in the project, add a [[bench]] to Cargo.toml with the harness disabled, and use the criterion crate. However, if I understand correctly, if we then run cargo bench, the benchmark will have to take the position of a user that cannot access crate features defined only during testing. Thus, slow will not be resolved and the command will fail.
A Quick Aside: Another thing that derailed me for a while is that I kept wanting to use bench as a cfg flag but couldn't find anything about this. As it turns out, I think that test also covers the benching case. (I think all the seasoned rustaceans will be laughing at me, but this seems like a useful thing to note for anyone in a similar situation).
Attempt 2: The Nightly Test Crate
Since the previous method didn't seem fruitful, another popular option seemed to be to use the unstable test crate. This results in a project structure that looks like:
Cargo.toml
src/
lib.rs
bench.rs
Our original file is then revised to be:
// Include the unstable feature
#![feature(test)]
pub fn fast(x: T) -> U { ... }
#[cfg(any(test, debug_assertions))]
pub fn slow(x: T) -> U { ... }
#[cfg(test)]
mod bench;
And then bench.rs should look something like:
extern crate test;
use test::Bencher;
#[bench]
fn bench_it(b: &mut Bencher) {
b.iter(|| {}) // gotta go fast
}
This seemed to do everything I wanted upon running cargo +nightly bench. However, it is also super desirable for the project to be compilable outside of testing without the use of nightly or extra feature flags. That is, I still want to be able to run cargo build and cargo test and not get yelled at for requesting unstable features on a stable channel.
Attempt 2.5: Enter Build Scripts
(Once again, each of the parts is well-documented in other questions, I'm just collecting everything here for fun). Using a bunch of other posts, I learned that we can check for nightly and conditionally enable features by way of a build script. Our project now looks like this:
Cargo.toml
build.rs
src/
lib.rs
bench.rs
And we need to add rustc_version to our [build-dependencies] in Cargo.toml. We then add the following build script:
use rustc_version::{version_meta, Channel};
fn main() {
// Set feature flags based on the detected compiler version
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=RUSTC_IS_STABLE");
}
Channel::Beta => {
println!("cargo:rustc-cfg=RUSTC_IS_BETA");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=RUSTC_IS_NIGHTLY");
}
Channel::Dev => {
println!("cargo:rustc-cfg=RUSTC_IS_DEV");
}
}
}
Finally, if we update lib.rs to be the following:
// Include the unstable feature
#![cfg_attr(RUSTC_IS_NIGHTLY, feature(test))] // <-- Note the change here!
pub fn fast(x: T) -> U { ... }
#[cfg(any(test, debug_assertions))]
pub fn slow(x: T) -> U { ... }
#[cfg(all(RUSTC_IS_NIGHTLY, test))] // <-- Note the change here!
mod bench;
I think we get everything we want.
So... thanks for joining me on this adventure. Would appreciate commentary on whether or not this was the right approach. Also, you might ask "why keep the benchmark around once we know it's slower?" I suppose this might be fair, but perhaps the test could be changed or I'd like to prove the new implementation is faster to a third party that won't just trust me.

OCaml "include Module" only includes functions exposed by the interface

I'm trying to test an OCaml module, called Game. However, the initialize function for Game, when used in the normal context of my project, only accepts a few parameters. This means certain tests would require me to init Game, then perform a specific combination of hundreds of operations just to get to a desired state, which is infeasible.
My idea was to create a new init function that allows the user to hard-code every component of a Game object. Since it'll only be used for testing, it seems like a bad idea to make this init function be part of the typical mli interface, so I thought using the keyword include in my testGame.ml file would help.
In my testGame.ml, both generate_player_ids and the Game.t type are "unbound," even though I define them in test.ml. This must be because they aren't exposed in game.mli, but I thought that using include would essentially be like copying and pasting the entire module, including the parts of the .ml file that aren't exposed. Is there a way to get testGame.ml to recognize these? Otherwise, what is the idiomatic way to have functions that recognize the hidden parts of a module for the purposes of testing?
testGame.ml:
include Game
let init_game_test
num_players
board
turn
starting_turn
setup_rounds_left
scoring_points
num_rounds =
let player_ids = generate_player_ids num_players in
{
players = players_of_player_ids player_ids;
player_order = player_ids;
board;
turn;
starting_turn;
setup_rounds_left;
scoring_points;
num_rounds;
}
game.ml:
type t = {
players : (PlayerId.t * Player.t) list;
player_order : PlayerId.t list;
board : Board.t;
turn : PlayerId.t;
starting_turn : PlayerId.t;
setup_rounds_left : int;
scoring_points : (Cell.soil * int list) list;
num_rounds : int;
}
let generate_player_ids num_players =
match num_players with
| 2 -> [ 1; 2 ]
| 3 -> [ 1; 2; 3 ]
| 4 -> [ 1; 2; 3; 4 ]
| _ -> failwith "Must be 2-4 players"
You're quite correct in assuming it's because they aren't exposed. include works on OCaml's module system, rather than a straight source inclusion basis as something like C does.
If you leave out the .mli interface file everything is by default exposed.

How do I resolve the error "no module in the root" when using a module in Rust 2018?

I'm working on a project that is utilizing some local modules in folders under src/. I'm currently using Rust 2018 edition and one of the major changes for that is the handling of imports/use statements.
My module code is all working correctly, but as I started to pull it together to be used for the project as a whole I started getting this error:
error[E0432]: unresolved import `crate::lexer`
--> src/main.rs:1:5
|
1 | use crate::lexer;
| ^^^^^^^^^^^^ no `lexer` in the root
Currently, my code is set up like this:
src/
| main.rs
| lexer/
| mod.rs
| lexer.rs
lexer/lexer.rs
pub fn lex_stuff() -> Vec<String> { vec![String::new("test")] }
lexer/mod.rs
pub mod lexer;
main.rs
use crate::lexer;
fn main() {
println!("Hello, world!");
lexer::lexer::lex_stuff();
}
I've attempted to resolve this by changing the statement to use lexer as well as use self::lexer and adding extern crate lexer (which obviously doesn't work, but what the heck, figured I'd try it). However, none of these have worked.
What can I do to resolve the no 'lexer' in the root error?
You still need to declare that main.rs contains a module:
mod lexer; // This, not `use`
fn main() {
println!("Hello, world!");
lexer::lexer::lex_stuff();
}
Please take the time to re-read The Rust Programming Language, specifically the section about Separating Modules into Different Files.
You need to move mod.rs to lexer.rs:
src/
| main.rs
| lexer.rs
| lexer/
| lexer.rs
| tokens.rs
This change is described here.
What most beginners (aka me perpetually) want to do is move some functions from one file like lib.rs into a file named submod.rs and access the functions in it as submod::myfunc. The answer that inspired me to write this suggests lexer::lexer::lex_stuff() which is slightly infuriating. We should never see a name twice for no serious reason. And adding another name, as the book does with hosting isn't helpful since naming is a hard problem in CS.
So hence, here's how to make a crepe instead of a stack of crepes (using the example from the book):
lib.rs
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
front_of_house::seating_capacity();
hosting::add_to_waitlist();
}
front_of_house.rs (or optionally front_of_house/mod.rs)
pub fn seating_capacity() {}
pub mod hosting {
pub fn add_to_waitlist() {}
}
Now if you add a pub fn put_up_chairs() {} to lib.rs and decide, wait a minute, that belongs in front_of_house (but not hosting), you can simply move the function over to front_of_house.rs and refer to it in lib.rs as front_of_house::put_up_chairs(). Simple..? I hope? I'm writing to myself in the future when I forget this and find this answer again, not you gentle reader.
Note everything gets more exciting when the pub keyword is gone or altered, at which point maybe you should reread the book. ;)
Also one more thing, adding pub use front_of_house; after the mod front_of_house is an error, because you already have declared the module. If you do cargo gives a loud answer (because it assumes you know what you're doing, if you're like me and program computers by bashing rocks together, you don't)
error[E0255]: the name `front_of_house` is defined multiple times
--> src/lib.rs:2:9
|
1 | mod front_of_house;
| ------------------- previous definition of the module `front_of_house` here
2 | pub use crate::front_of_house;
| ^^^^^^^^^^^^^^^^^^^^^ `front_of_house` reimported here
|
= note: `front_of_house` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
2 | pub use crate::front_of_house as other_front_of_house;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0365]: `front_of_house` is only public within the crate, and cannot be re-exported outside
--> src/lib.rs:2:9
|
2 | pub use crate::front_of_house;
| ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `front_of_house`
|
= note: consider declaring type or module `front_of_house` with `pub`
If you made the above mistake of 'double using' it's ok, it's a little odd that the mod keyword also gives you a use for free. But it does and we should be thankful for it. :)
Motivation
In over a decade I've never written an answer on SO. But I've hit this question so many times and been so absolutely twisted in knots by the "Please take the time to re-read" answer by beloved rust wiz #Shepmaster that I'm writing an answer. The Rust Book example is like a recipe for baking a crepe cake before showing you how to make a single crepe, at least as of the 2nd edition.

Why can't I map Path::new over the std::env::args iterator?

This works:
let paths: Vec<String> = args.collect();
let paths = paths.iter().map(|f| std::path::Path::new(&f));
This doesn't work:
let paths = ::std::env::args().map(|f| std::path::Path::new(&f));
error[E0597]: `f` does not live long enough
--> src/main.rs:2:66
|
2 | let paths = ::std::env::args().map(|f| std::path::Path::new(&f));
| ^-- borrowed value needs to live until here
| ||
| |`f` dropped here while still borrowed
| borrowed value does not live long enough
Why do I need to collect the args iterator into a vector just to produce another iterator? Why can't I produce one iterator directly from another?
The Args iterator returns values of type String. When you map over an iterator, the closure is given ownership of each value.
The code that doesn't work attempts to take a reference to the String, but that string will go out of scope at the end of the closure. This is disallowed as discussed in Return local String as a slice (&str).
The code that does work is not iterating over Strings but &Strings; see What is the difference between iter and into_iter?. Thus there's nothing to go out of scope in the closure and returning a reference from the closure is fine.
The correct solution is to transfer ownership of the String's data to a new type. PathBuf is the appropriate choice. PathBuf is to &Path as String is to &str:
let paths = ::std::env::args().map(std::path::PathBuf::from);
PathBuf is mutable. I don't need mutability here. Why do you think I need PathBuf?
You are confused about how mutability works in Rust. Go back and re-read The Rust Programming Language, especially the chapter on Variables and Mutability.
Types in Rust are not mutable or immutable by themselves. Mutability is a property of the variable binding:
let buf = std::path::PathBuf::new();
buf.push("home");
error[E0596]: cannot borrow immutable local variable `buf` as mutable
--> src/main.rs:3:5
|
2 | let buf = std::path::PathBuf::new();
| --- consider changing this to `mut buf`
3 | buf.push("home");
| ^^^ cannot borrow mutably

Split a module across several files

I want to have a module with multiple structs in it, each in its own file. Using a Math module as an example:
Math/
Vector.rs
Matrix.rs
Complex.rs
I want each struct to be in the same module, which I would use from my main file, like so:
use Math::Vector;
fn main() {
// ...
}
However Rust's module system (which is a bit confusing to begin with) does not provide an obvious way to do this. It seems to only allow you to have your entire module in one file. Is this un-rustic? If not, how do I do this?
Rust's module system is actually incredibly flexible and will let you expose whatever kind of structure you want while hiding how your code is structured in files.
I think the key here is to make use of pub use, which will allow you to re-export identifiers from other modules. There is precedent for this in Rust's std::io crate where some types from sub-modules are re-exported for use in std::io.
Edit (2019-08-25): the following part of the answer was written quite some time ago. It explains how to setup such a module structure with rustc alone. Today, one would usually use Cargo for most use cases. While the following is still valid, some parts of it (e.g. #![crate_type = ...]) might seem strange. This is not the recommended solution.
To adapt your example, we could start with this directory structure:
src/
lib.rs
vector.rs
main.rs
Here's your main.rs:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
And your src/lib.rs:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
And finally, src/vector.rs:
// exports identifiers from private sub-modules in the current
// module namespace
pub use self::vector_a::VectorA;
pub use self::vector_b::VectorB;
mod vector_b; // private sub-module defined in vector_b.rs
mod vector_a { // private sub-module defined in place
#[derive(Debug)]
pub struct VectorA {
xs: Vec<i64>,
}
impl VectorA {
pub fn new() -> VectorA {
VectorA { xs: vec![] }
}
}
}
And this is where the magic happens. We've defined a sub-module math::vector::vector_a which has some implementation of a special kind of vector. But we don't want clients of your library to care that there is a vector_a sub-module. Instead, we'd like to make it available in the math::vector module. This is done with pub use self::vector_a::VectorA, which re-exports the vector_a::VectorA identifier in the current module.
But you asked how to do this so that you could put your special vector implementations in different files. This is what the mod vector_b; line does. It instructs the Rust compiler to look for a vector_b.rs file for the implementation of that module. And sure enough, here's our src/vector_b.rs file:
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
From the client's perspective, the fact that VectorA and VectorB are defined in two different modules in two different files is completely opaque.
If you're in the same directory as main.rs, you should be able to run it with:
rustc src/lib.rs
rustc -L . main.rs
./main
In general, the "Crates and Modules" chapter in the Rust book is pretty good. There are lots of examples.
Finally, the Rust compiler also looks in sub-directories for you automatically. For example, the above code will work unchanged with this directory structure:
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
The commands to compile and run remain the same as well.
The Rust module rules are:
A source file is just its own module (except the special files main.rs, lib.rs and mod.rs).
A directory is just a module path component.
The file mod.rs is just the directory's module.
The file matrix.rs1 in the directory math is just the module math::matrix. It's easy. What you see on your filesystem you also find in your source code. This is an one-to-one correspondence of file paths and module paths2.
So you can import a struct Matrix with use math::matrix::Matrix, because the struct is inside the file matrix.rs in a directory math. Not happy? You'd prefer use math::Matrix; very much instead, don't you? It's possible. Re-export the identifier math::matrix::Matrix in math/mod.rs with:
pub use self::math::Matrix;
There's another step to get this working. Rust needs a module declaration to load the module. Add a mod math; in main.rs. If you don't do that, you get an error message from the compiler when importing like this:
error: unresolved import `math::Matrix`. Maybe a missing `extern crate math`?
The hint is misleading here. There's no need for additional crates, except of course you really intend to write a separate library.
Add this at the top of main.rs:
mod math;
pub use math::Matrix;
The module declaration is also neccessary for the submodules vector, matrix and complex, because math needs to load them to re-export them. A re-export of an identifier only works if you have loaded the module of the identifier. This means, to re-export the identifier math::matrix::Matrix you need to write mod matrix;. You can do this in math/mod.rs. Therefore create the file with this content:
mod vector;
pub use self::vector::Vector;
mod matrix;
pub use self::matrix::Matrix;
mod complex;
pub use self::complex::Complex;
Aaaand you are done.
1Source file names usually start with a lowercase letter in Rust. That's why I use matrix.rs and not Matrix.rs.
2Java's different. You declare the path with package, too. It's redundant. The path is already evident from the source file location in the filesystem. Why repeat this information in a declaration at the top of the file? Of course sometimes it's easier to have a quick look at the source code instead of finding out the filesystem location of the file. I can understand people who say it's less confusing.
Rusts purists will probably call me a heretic and hate this solution, but this is much simpler: just do each thing in its own file, then use the "include!" macro in mod.rs:
include!("math/Matrix.rs");
include!("math/Vector.rs");
include!("math/Complex.rs");
That way you get no added nested modules, and avoid complicated export and rewrite rules.
Simple, effective, no fuss.
Alright, fought my compiler for a while and finally got it to work(thanks to BurntSushi for pointing out pub use.
main.rs:
use math::Vec2;
mod math;
fn main() {
let a = Vec2{x: 10.0, y: 10.0};
let b = Vec2{x: 20.0, y: 20.0};
}
math/mod.rs:
pub use self::vector::Vec2;
mod vector;
math/vector.rs
use std::num::sqrt;
pub struct Vec2 {
x: f64,
y: f64
}
impl Vec2 {
pub fn len(&self) -> f64 {
sqrt(self.x * self.x + self.y * self.y)
}
// other methods...
}
Other structs could be added in the same manner. NOTE: compiled with 0.9, not master.
I'd like to add in here how you include Rust files when they are deeply nested. I have the following structure:
|-----main.rs
|-----home/
|---------bathroom/
|-----------------sink.rs
|-----------------toilet.rs
How do you access sink.rs or toilet.rs from main.rs?
As others have mentioned, Rust has no knowledge of files. Instead it sees everything as modules and submodules. To access the files inside the bathroom directory you need to export them or barrel them to the top. You do this by specifying a filename with the directory you'd like to access and pub mod filename_inside_the_dir_without_rs_ext inside the file.
Example.
// sink.rs
pub fn run() {
println!("Wash my hands for 20 secs!");
}
// toilet.rs
pub fn run() {
println!("Ahhh... This is sooo relaxing.")
}
Create a file called bathroom.rs inside the home directory:
Export the filenames:
// bathroom.rs
pub mod sink;
pub mod toilet;
Create a file called home.rs next to main.rs
pub mod the bathroom.rs file
// home.rs
pub mod bathroom;
Within main.rs
// main.rs
// Note: If you mod something, you just specify the
// topmost module, in this case, home.
mod home;
fn main() {
home::bathroom::sink::run();
}
use statements can be also used:
// main.rs
// Note: If you mod something, you just specify the
// topmost module, in this case, home.
use home::bathroom::{sink, toilet};
fn main() {
sink::run();
sink::toilet();
}
Including other sibling modules (files) within submodules
In the case you'd like to use sink.rs from toilet.rs, you can call the module by specifying the self or super keywords.
// inside toilet.rs
use self::sink;
pub fn run() {
sink::run();
println!("Ahhh... This is sooo relaxing.")
}
Final Directory Structure
You'd end up with something like this:
|-----main.rs
|-----home.rs
|-----home/
|---------bathroom.rs
|---------bathroom/
|-----------------sink.rs
|-----------------toilet.rs
The structure above only works with Rust 2018 onwards. The following directory structure is also valid for 2018, but it's how 2015 used to work.
|-----main.rs
|-----home/
|---------mod.rs
|---------bathroom/
|-----------------mod.rs
|-----------------sink.rs
|-----------------toilet.rs
In which home/mod.rs is the same as ./home.rs and home/bathroom/mod.rs is the same as home/bathroom.rs. Rust made this change because the compiler would get confused if you included a file with the same name as the directory. The 2018 version (the one shown first) fixes that structure.
See this repo for more information and this YouTube video for an overall explanation.
One last thing... avoid hyphens! Use snake_case instead.
Important Note
You must barrel all the files to the top, even if deep files aren't required by top-level ones.
This means, that for sink.rs to discover toilet.rs, you'd need to barrel them by using the methods above all the way up to main.rs!
In other words, doing pub mod sink; or use self::sink; inside toilet.rs will not work unless you have exposed them all the way up to main.rs!
Therefore, always remember to barrel your files to the top!
A more rustlings method to export module, which I picked up from Github.
mod foo {
//! inner docstring comment 1
//! inner docstring comment 2
mod a;
mod b;
pub use a::*;
pub use b::*;
}
Adjusting the question's example directory and file names to conform to Rust naming conventions:
main.rs
math.rs
math/
vector.rs
matrix.rs
complex.rs
Make sure to export the public symbols (types, functions, etc.) in each of the files in the math directory by preceding them with the keyword pub.
Define math.rs:
mod vector;
pub use vector::*;
mod matrix;
pub use matrix::*;
mod complex;
pub use complex::*;
The above file keeps the sub-modules of math private but the submodules' public symbols are exported from module math. This effectively flattens the module structure.
Use math::Vector in main.rs:
mod math;
use crate::math::Vector;
fn main() {
// ...
}