Why rust can't find a function in a submodule? [duplicate] - module

This question already has answers here:
How can I include a module from another file from the same project?
(6 answers)
Closed 5 years ago.
I'm trying to call a function from a module located in a separate file, the function is public and I am calling it using a full path, but rustc still complains about "unresolved name".
a.rs
pub mod b;
fn main() {
b::f()
}
b.rs
pub mod b {
pub fn f(){
println!("Hello World!");
}
}
compilation
$ rustc a.rs
a.rs:3:5: 3:9 error: unresolved name `b::f`.
When I move the module to the crate's main file, everything works fine.
one_file.rs
pub mod b {
pub fn f(){
println!("Hello World!");
}
}
fn main() {
b::f()
}
Aren't these two ways supposed to be equivalent?
Am I doing something wrong, or it's a bug in rustc?

When you have separate files, they are automatically considered as separate modules.
Thus, you can do :
othermod.rs
pub fn foo() {
}
pub mod submod {
pub fn subfoo() {
}
}
main.rs
mod othermod;
fn main () {
othermod::foo();
othermod::submod::subfoo();
}
Note that if you use sub-directories, the file mod.rs is special and will be considered as the root of your module :
directory/file.rs
pub fn filebar() {
}
directory/mod.rs
pub mod file;
pub fn bar() {
}
main.rs
mod directory;
fn main() {
directory::bar();
directory::file::filebar();
}

Related

mock trait implementation for concrete struct

So I have a function. And I want to test it. It takes a struct as param. And the struct has some trait implemented. This trait has a long running io method. I don't want this io method to actually go fetch data, I want to mock this io method and just return the result. I am a little lost about how this can be done. Here is my try (not working)
struct TestStruct {
a: u32,
b: u32,
}
pub trait TestTrait {
fn some_long_running_io_method(&self) -> u32 {
156
}
}
fn important_func(a: TestStruct) {
println!("a: {}", a.some_long_running_io_method());
}
impl TestTrait for TestStruct {
fn some_long_running_io_method(&self) -> u32 {
self.a + self.b
}
}
#[cfg(test)]
mod tests {
use super::*;
use mockall::predicate::*;
use mockall::*;
#[cfg(test)]
mock! {
pub TestStruct {}
impl TestTrait for TestStruct {
fn some_long_running_io_method(&self) -> u32;
}
}
#[test]
fn test_important_func() {
let mut mock = MockTestStruct::new();
mock.expect_some_long_running_io_method()
.returning(|| 1);
important_func(mock);
}
}
I obviously get this error:
error[E0308]: mismatched types
--> src/test.rs:35:24
|
35 | important_func(mock);
| -------------- ^^^^ expected struct `TestStruct`, found struct `MockTestStruct`
| |
| arguments to this function are incorrect
How can I achieve mocking trait methods? 1) One way is to change function param and instead of accepting a concrete struct accept trait. And implement this trait on MockTestStruct. But then we have dynamic dispatching and it hurts the performance. I don't want a performance degrade just for the test. 2) I also tried reimplementing the Trait right where the test is, but conflicting implementations are not allowed in Rust. 3) Make function accept TestStruct or MockTestStruct? Probably not great way either.
Could you please tell me what is the idiomatic way to do it?
You can make your function, important_func a generic function. You can then use generic bounds to restrict the type to implementors of your trait.
Here is an example with your code:
struct TestStruct {
a: u32,
b: u32,
}
pub trait TestTrait {
fn some_long_running_io_method(&self) -> u32 {
156
}
}
// important_func can now use any type T which implements TestTrait,
// including your mock implementation!
fn important_func<T: TestTrait>(a: T) {
println!("a: {}", a.some_long_running_io_method());
}
impl TestTrait for TestStruct {
fn some_long_running_io_method(&self) -> u32 {
self.a + self.b
}
}
#[cfg(test)]
mod tests {
use super::*;
use mockall::predicate::*;
use mockall::*;
#[cfg(test)]
mock! {
pub TestStruct {}
impl TestTrait for TestStruct {
fn some_long_running_io_method(&self) -> u32;
}
}
#[test]
fn test_important_func() {
let mut mock = MockTestStruct::new();
mock.expect_some_long_running_io_method().returning(|| 1);
important_func(mock);
}
}

Multiple files in a (binary) project

I'm trying to grok the appropriate way to split up my binary project into multiple files. In the Rust book, 7.1 Packages and Crates starts off by including an example of creating a bin project with cargo, but the rest of the examples are lib. I don't really care about the hierarchy of my code since I'm not exposing it in a library. Other, older questions (for example) mention that you generally need <module_name>/mod.rs; while this isn't strictly required, it does seem appropriate for larger library projects.
I have three files:
src/main.rs:
mod A;
mod B;
fn main() {
let a = A::A { a: 123 };
let b = B::B { b: 3.14 };
println!("{:?}", a);
println!("{:?}", b);
}
src/A.rs:
use crate::B;
#[derive(Debug)]
pub struct A {
pub a : u32
}
impl From<B::B> for A {
fn from(b : B::B) -> A {
A { a: b.b as u32 }
}
}
src/B.rs:
use crate::A;
#[derive(Debug)]
pub struct B {
pub b : f32
}
impl From<A::A> for B {
fn from(a : A::A) -> B {
B { b: a.a as f32 }
}
}
This works as expected (snake case warnings removed for brevity):
$ cargo run
A { a: 123 }
B { b: 3.14 }
However, this seems like a bit more song-and-dance than should be necessary: qualifying references with their module name for every reference seems excessive. I would have assumed that I could do something like mod A::A or use A::* to 'import' types, functions, etc.
Is this the expected, idiomatic way to split code up?
Edit:
Per discussion, I updated my source to use use a::*. New code is:
main.rs:
mod a;
mod b;
use a::*; // !
use b::*; // !
fn main() {
let a = A { a: 123 };
let b = B { b: 3.14 };
println!("{:?}", a);
println!("{:?}", b);
}
a.rs:
use crate::b::*;
#[derive(Debug)]
pub struct A {
pub a : u32
}
impl From<B> for A {
fn from(b : B) -> A {
A { a: b.b as u32 }
}
}
b.rs:
use crate::a::*;
#[derive(Debug)]
pub struct B {
pub b : f32
}
impl From<A> for B {
fn from(a : A) -> B {
B { b: a.a as f32 }
}
}
Including both mod a; and use a::*; (changed to follow snake_case convention, but importantly to prevent name conflicts with the previously uppercase A module from conflicting with the still-uppercase A struct) now lets components be referenced without qualification.

Using a phantom scope to bypass bounds-checking

I want to construct a indexing-type associated to a value which is a wrapper around a usize such that any vector created from that value I don't need to bounds-check the index. It seems like phantom lifetimes can be used to do some small amount of dependently typed programming like this. Will this work or are there things I'm not considering?
In other words, using the module below is it impossible to write ("safe") code which will step out of memory?
Also, is there a way to do this without the unit references?
pub mod things {
use std::iter;
#[derive(Clone, Copy)]
pub struct ThingIndex<'scope>(usize, &'scope ());
pub struct Things {
nthings: usize,
}
pub struct ThingMapping<'scope, V>(Vec<V>, &'scope ());
impl Things {
pub fn in_context<F: FnOnce(&Things) -> V, V>(nthings: usize, continuation: F) -> V {
continuation(&Things { nthings })
}
pub fn make_index<'scope>(&'scope self, i: usize) -> ThingIndex<'scope> {
if i >= self.nthings {
panic!("Out-of-bounds index!")
}
ThingIndex(i, &())
}
pub fn make_mapping<'scope, V: Clone>(&'scope self, def: V) -> ThingMapping<'scope, V> {
ThingMapping(iter::repeat(def).take(self.nthings).collect(), &())
}
}
impl<'scope, V> ThingMapping<'scope, V> {
pub fn get<'a>(&'a self, ind: ThingIndex<'scope>) -> &'a V {
unsafe { &self.0.get_unchecked(ind.0) }
}
// ...
}
}
Update:
This doesn't seem to work. I added a test that I expected would fail to compile and it compiled without complaint. Is there a way to repair it and make it work? What if I write a macro?
#[cfg(test)]
mod tests {
use crate::things::*;
#[test]
fn it_fails() {
Things::in_context(1, |r1| {
Things::in_context(5, |r2| {
let m1 = r1.make_mapping(());
let i2 = r2.make_index(3);
assert_eq!(*m1.get(i2), ());
});
})
}
}
Note: in_context is loosely based on Haskell's runST function. In Haskell the type-signature of runST requires RankNTypes. I wonder if perhaps this is impossible because the Rust compiler does nothing conjugate to the behavior of RankNTypes.

What is the proper way to pass a module as an argument?

I have a module file (src/map/map.rs):
type Layer = Vec<Vec<Tile>>;
pub struct Map {
height: i32,
width: i32,
data: Layer,
rooms: Vec<Rect>,
}
impl Map {
pub fn new(width: i32, height: i32) -> Self {
Map {
height: height,
width: width,
data: vec![vec![Tile::wall(); height as usize]; width as usize],
rooms: vec![Rect],
}
}
pub fn generate_with(&self, creator: module) {
creator::generate(&self)
}
}
a nested module map::gen::dungeon::basic (src/map/gen/dungeon/basic.rs)
with one function in the file:
pub fn generate(map: &mut Map) -> (Map, (i32, i32)) {}
and the map module file (src/map/mod.rs):
mod rect;
mod tile;
mod map;
pub mod room;
pub mod gen;
pub use self::map::Map;
pub use self::rect::Rect;
pub use self::tile::Tile;
imported into main.rs like this:
mod map;
use map::*;
use map::gen;
I want to be able to use it like this:
let (map, (player_x, player_y)) = Map::new(MAP_WIDTH, MAP_HEIGHT).generate_with(gen::dungeon::basic);
the error I get though is:
[cargo] expected value, found module 'gen::dungeon::basic': not a value [E]
A complete repo is available.
As stated in the comments, a module is not a concrete concept like that; what you are attempting to do is not possible.
Instead, you can pass something that can be a value:
mod basic {
pub fn generate() -> u8 {
0
}
}
mod advanced {
pub fn generate() -> u8 {
42
}
}
fn play_the_game(generator: fn() -> u8) {
let dungeon = generator();
println!("{}", dungeon);
}
fn main() {
play_the_game(basic::generate);
play_the_game(advanced::generate);
}
You could also introduce a trait and pass the implementing type as a generic:
trait DungeonGenerator {
fn generate() -> u8;
}
mod basic {
use DungeonGenerator;
pub struct Basic;
impl DungeonGenerator for Basic {
fn generate() -> u8 {
0
}
}
}
mod advanced {
use DungeonGenerator;
pub struct Advanced;
impl DungeonGenerator for Advanced {
fn generate() -> u8 {
42
}
}
}
fn play_the_game<G>()
where
G: DungeonGenerator,
{
let dungeon = G::generate();
println!("{}", dungeon);
}
fn main() {
play_the_game::<basic::Basic>();
play_the_game::<advanced::Advanced>();
}

How to reference a member of a module in its parent scope, from a module?

This simple example works in main.rs
pub mod types {
pub struct Foo {
_var: usize,
}
}
use types::Foo;
fn main() {
let _unused: Foo;
println!("Hello, world!");
}
However, when its compiled in a file which is its self a module, this gives an error:
error: unresolved import `types::Foo`. Maybe a missing `extern crate types`?
Is it possible to make a reference to a submodule's public member, from a module?
When in a module, self needs to be used, eg:
pub mod types {
pub struct Foo {
_var: usize,
}
}
use self::types::Foo; // <-- self here
Thanks to #nox on IRC for this answer.