Module import fail - module

I have simple code that imports 2 modules and uses struct from them.
At main.rs I'm using functions from bots/maintrait.rs and gamecore\board.rs They both are imported same way, but func from maintrait.rs cannot be resolved.
Here is structure of my src directory:
.
├── bots
│   ├── maintrait.rs
│   └── mod.rs
├── gamecore
│   ├── board.rs
│   └── mod.rs
└── main.rs
And code:
main.rs
use gamecore::{GameBoard,State};
use bots::{Bot,DummyBot};
mod bots;
mod gamecore;
fn main() {
let board = GameBoard::new();
let bot = DummyBot::new(State::O);
board.make_turn(State::X, (0, 0));
board.make_turn(State::O, bot.get_move(&board));
}
gamecore\mod.rs
pub use self::board::{GameBoard,State};
mod board;
gamecore\board.rs
pub struct GameBoard {
field: [[State, ..3], ..3]
}
impl GameBoard {
pub fn new() -> GameBoard {
GameBoard {
field: [[State::Empty, ..3], ..3]
}
}
...
}
bots\mod.rs
pub use self::maintrait::{Bot,DummyBot};
mod maintrait;
bots\maintrait.rs
use gamecore::{GameBoard,State};
use std::rand;
pub trait Bot {
fn new<'a>() -> Box<Bot + 'a>;
fn get_move(&mut self, board: &GameBoard) -> (uint, uint);
}
pub struct DummyBot {
side: State
}
impl Bot for DummyBot {
fn new<'a>(side: State) -> Box<Bot + 'a> {
box DummyBot{
side: side
}
}
fn get_move(&mut self, board: &GameBoard) -> (uint, uint) {
let turn = rand::random::<uint>() % 9;
(turn / 3, turn % 3)
}
}
ERROR MESSAGE
10:28 error: failed to resolve. Use of undeclared module `DummyBot`
let bot = DummyBot::new(State::O);
^~~~~~~~~~~~~
10:28 error: unresolved name `DummyBot::new`
let bot = DummyBot::new(State::O);
^~~~~~~~~~~~~
Where I'm wrong? Why 2 same imports works diffirent?

Rust by Example has a good example of how to do something similar.
Here's the appropriate bits of code that need to change:
pub trait Bot {
// Your trait and implementation signatures differ, so I picked this one
fn new() -> Self;
}
impl Bot for DummyBot {
fn new() -> DummyBot {
DummyBot{
side: State::Empty
}
}
}
let bot: DummyBot = Bot::new();
I'm guessing a bit, but I think the underlying reason is that you haven't really defined a DummyBot::new, but instead have defined a generic Bot::new that DummyBot happens to implement. You have to call the defined method (Bot::new) and provide enough information to disambiguate the call (the type of the let).

Related

Is there a way to split Trait implementation and defenition across different modules?

I'd like to define a trait with many methods:
pub trait DataSetT{
fn numeric_op_1(&self){...};
fn numeric_op_2(&self)->f64{...};
...
fn io_op_1(&self) {..};
fn io_op_2(&self) -> DataFrame {...};
...
}
Now, if I define all these methods in the same file it would get humongous.
For the sake of clean and visibile code, I'd like to split these definitions across different files/modules.
For example numeric operatins would live in:
src/numerics.rs
And io operations would live in
src/io.rs
Same thing with implementing this trait for a Struct (overriding the default trait behaviour).
As soon as I try doing that, I either get not all trait items implemented or confilicting definitions.
What is the best practice solution in this kind of situtation?
Without macro you should not be able to split a trait definition over different modules. Where you write trait MyTrait { .. } you need to define it.
But you can define multiple traits and have a super trait, like this:
// src/ops/a.rs
pub trait OpA {
fn op_a1(&self);
fn op_a2(&self) -> f64;
}
// src/ops/b.rs
pub trait OpB {
fn op_b1(&self);
fn op_b2(&self);
}
// src/ops/mod.rs
pub trait Op: OpA + OpB {}
// src/ops_impl/mod.rs
struct MyOp {}
impl Op for MyOp {}
// src/ops_impl/a.rs
impl OpA for MyOp {
fn op_a1(&self) {}
fn op_a2(&self) -> f64 {
42.0
}
}
// src/ops_impl/b.rs
impl OpB for MyOp {
fn op_b1(&self) {}
fn op_b2(&self) {}
}

Is it possible to have a module which is partially accessible outside of a crate and partially only inside the crate?

Is there any better way than just put everything in the same module?
sub_module.rs
pub struct GiantStruct { /* */ }
impl GiantStruct {
// this method needs to be called from outside of the crate.
pub fn do_stuff( /* */ ) { /* */ };
}
lib.rs
pub mod sub_module;
use sub_module::GiantStruct;
pub struct GiantStructBuilder{ /* */ }
impl GiantStructBuilder{
pub fn new_giant_struct(&mut self) -> GiantStruct {
// Do stuff depending on the fields of the current
// GiantStructBuilder
}
}
The problem is with GiantStructBuilder::new_giant_struct(); this method should create a new GiantStruct but to do this you either need pub fn new() -> GiantStruct inside of sub_module.rs or all fields of GiantStruct have to be public. Both options allow for access from outside of my crate.
While writing this question, I realized that I could do something like this:
sub_module.rs
pub struct GiantStruct { /* */ }
impl GiantStruct {
// now you can't call this method without an appropriate
// GiantStructBuilder
pub fn new(&mut GiantStructBuilder) -> GiantStruct { /* */ };
pub fn do_stuff( /* */ ) { /* */ };
}
However, this seems really counterintuitive as normally the caller is the thing that is acting while the function variables are what is is acted upon, which is obviously not the case when doing it like this. So I would still like to know if there is any better way...
You could use the newly stabilized pub(restricted) privacy.
This will allow you to expose types/functions to only a limited module tree, e.g.
pub struct GiantStruct { /* */ }
impl GiantStruct {
// Only visible to functions in the same crate
pub(crate) fn new() -> GiantStruct { /* */ };
// this method needs to be called from outside of the crate.
pub fn do_stuff( /* */ ) { /* */ };
}
Or you could apply this to fields on your GiantStruct to allow you to create it from GiantStructBuilder:
pub struct GiantStruct {
pub(crate) my_field: u32,
}
Instead of crate you could also use super to specify it's only public to the parent module.

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.

How to reference private types from public functions in private modules?

I want to group similar functions in a file. Those functions need to return a type which is not public:
struct MyStruct;
mod my_mod {
use super::MyStruct;
// There are other, similar functions that also return `MyStruct`
pub fn foo() -> MyStruct {
MyStruct
}
}
fn main() {
let _var = my_mod::foo();
}
This fails with the error
error[E0446]: private type `MyStruct` in public interface
--> src/main.rs:7:3
|
1 | struct MyStruct;
| - `MyStruct` declared as private
...
7 | pub fn foo() -> MyStruct { MyStruct }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
In general, it makes sense not to allow public functions to have private types in their signature, but in this specific case the structure is available at the modules root level.
Is there a way to support this without making MyStruct public?
I have a feeling that this error is unwarranted. It should only be an error if my_mod is pub or if the functions are re-exported in an outer scope.
That said, I found a workaround: move MyStruct to a sibling module and make MyStruct pub, but not the module.
use types::MyStruct;
mod types {
pub struct MyStruct;
}
mod my_mod {
use super::MyStruct;
pub fn foo() -> MyStruct {
MyStruct
}
}
fn main() {
let _var = my_mod::foo();
}
I encountered this same problem. Rust 2018 seems to have solved it; just refer to the submodule's "public" function as pub(crate), AKA pub(crate) fn foo().
This makes the function only public to the crate: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/module-system/more-visibility-modifiers.html

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

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();
}