One line module re-export - rust

I'm am trying to re-export a submodule from another file from a parent module.
Give this file structure,
src/
- lib.rs
- module/
-- mod.rs
-- submodule/
--- mod.rs
...can this be accomplished in a single line?
// mod.rs
mod submodule;
pub use submodule::*;
// something like pub use mod submodule::*;

If I understand correctly, you're asking if the mod and the use can be combined into a single line.
No, there is no allowance for combining a mod with a use. The right way to think about mod is that it defines where the module is located in the module hierarchy. The fact that it also brings the module name into the namespace of the current module, as if you had written use some_module;, is essentially a part of that, since it would be pointless to ever write mod some_module without making it visible in its parent.
If you want to also make additional names available, there is no special syntax for combining it with a mod; you have to use use.

Related

Difference between "pub use" and "pub mod"?

Suppose I have this file hierarchy in a Rust package:
src/...
src/m1/mod.rs
src/m1/path/m2.rs
What would be the practical difference between having the line:
pub mod path::m2;
in my file m1/mod.rs, versus having the line:
pub use path::m2;
Trying to refresh my understanding of Rust after a time away, so this isn't my first learning cycle. (Of course, for other readers it may be.) I'm saying this because I'm not asking for a general explanation of the differences between use and mod. My unclarity is specific to the two directives above. It seems like they would both serve to make the module in file src/m1/path/m2.rs available to the module m1 and to anything else that imported it (because of the pub prefix on both directives). Is that right? Would these be perfect aliases, or would there be some differences? Is either idiom preferable to the other?
mod foo; is akin to copying and pasting a module into the current scope. That is, if the current scope can find module foo at its own "top level" — basically, if there's a file foo.rs or a folder foo in the same directory — then mod foo; basically gets transformed into mod foo { /* contents of foo */ }. Note that the syntax for mod requires that the thing after mod be an identifier, not an arbitrary path (so mod path::m2; would be illegal). I can only assume that modules that could be brought into scope aren't automatically brought into scope in order to limit the amount of work the compiler has to do when resolving names.
Meanwhile, once a container of items — whether that be a module, type, trait, etc — has been made available in the current scope, shortcuts to its items can be created with use path::to::item. If containers of items were ordinary variables, this would be akin to something like let item = path.to.item, if that were legal.
I'll edit this answer later to give a fuller explanation. But, with help from the comments and other answer posted here, plus some experimentation, I think I've come to a better understanding of these directives. There may be circumstances where one could use either pub use or pub mod, though they'd be contrived and in any case where both could work one should prefer the former (see third point below). The key differences are:
pub use is followed by a path (a bare identifier m2 would be the same as self::m2). pub mod is only followed by an identifier.
pub mod m2; in main.rs or lib.rs would include the contents of file ./m2.rs (or ./m2/mod.rs). If the line pub mod m2; is instead in a file path/m1.rs (or path/m1/mod.rs) then the included file would instead be path/m1/m2.rs (or path/m1/m2/mod.rs).
(You could include a module from another location using mod m2 { include!("path/m2.rs") } but this isn't idiomatic. I've also seen some attribute tricks that affect the location of the loaded module. But generally things work as described in the previous paragraph.)
The use directive doesn't request/order the compilation of any additional files. A mod directive is needed to do that.
(In fact the additional files aren't compiled separately, but merged into the source file where the mod directive occurs. Only the files that are crate roots (plus whatever is merged into them) get compiled.)
If one file in your crate had a pub mod m2; line, then another file could conceivably have a choice of also using pub mod or pub use. Subject to the constraints imposed by point 1 above.
But if you were in such circumstances, you wouldn't want to use the mod directive, as that would merge the relevant code into your source tree a second time. Perhaps the compiler might eventually undo the duplication, but what would you gain by hoping for that?
There's also this statement from the "Separating Modules into Different Files" chapter in the book:
Note that you only need to load the contents of a file using a mod declaration once somewhere in your module tree. Once the compiler knows the file is part of the project (and knows where in the module tree the code resides because of where you’ve put the mod statement), other files in your project should refer to the code in that file using a path to where it was declared...

Why duplicate function names in mod.rs as another .rs file?

For example, have module within /xyz/ sub-directory. Inside the directory are two files, mod.rs and network.rs say.
Why do mod.rs and network.rs have the same function names, but different code within the functions? Is there any reason for this? I thought mod.rs was just basically a defintions file to declare a module, and specify which other .rs files within the sub-directory should be treated as their own creates / modules.
Any help?
It sounds like you are referring to a design decision made by a specific crate. You are correct in assuming there is no special consideration given by the compiler to function/type/ident names in separate files/modules.
That being said it seems likely that what you are referring to might be using conditional compilation. Conditional compilation lets the compiler decide if a given piece of code is compiled or not. You will usually see this used to handle which implementation of a function is used when compiling code on different operating systems since it is often it too inefficient or simply impossible to check at runtime. Some library authors might also decide to add an implementation that it can fallback to instead of throwing a hard error.
Here is a quick example of why xyz might want to have 3 different implementations of foobar.
// xyz/mod.rs
mod windows;
mod unix;
// If this crate is compiled on windows re-export the contents of windows.rs
#[cfg(windows)]
pub use windows::*;
// If this crate is compiled on unix/linux re-export the contents of unix.rs
#[cfg(unix)]
pub use unix::*;
// If not on either windows or unix provide a default implementation to use instead
#[cfg(not(any(windows, unix)))]
pub fn foobar() -> i32 {
panic!("This function is unsupported on the current os")
}

How to include all Rust modules from a given folder in mod.rs file in one line?

I'm looking for a convenience method to include all the Rust files in a given folder into my mod.rs file automatically. My folder structure looks like the following:
views/
mod.rs
view1.rs
view2.rs
view3.rs
Is there something like pub mod ** which would be equivalent to writing pub mod view1.rs, pub mod view2.rs and pub mod view3.rs? Just trying to save a little extra time here, since any rs file I put in this folder I want to be included in that module.
There is no build in language feature for implicitly picking up all files in a folder. You could write a procedural macro iterating over directory entries and generating use viewX statements, but I would dis-advice invoking that much magic, for a bit of convenience.
On another node. Rust does allow you to declare the module in a views.rs file which would be located next to the views folder in the hierarchy.

How can I access items in a top level module from another top level module without changing main.rs?

I have following file structure:
main.rs
-- module_a
-- mod.rs
output.rs
In output.rs, I have a function called log_info() and I'd like to call it from module_a/mod.rs.
I can place mod output; in main.rs and after that I can reference it from module_a/mod.rs, but I don't like having to place all my dependencies in main.rs in order to use them in my application.
Is there any way I can reference the output module in module_a/mod.rs without messing with main.rs?
Is there any way I can reference the output module in module_a/mod.rs without messing with main.rs?
No. Each module (including the crate entry point of main.rs or lib.rs) has to explicitly define what modules are its children.
You could move the output module to be a child of module_a, however.

Can I include modules "sideways" in Rust?

I want to split a Rust program into multiple files, but the use of mod doesn't see to allow me to reference files in the same directory from files other than main.rs.
For example, if I have main.rs, game.rs, and matrix.rs in the same folder, I can reference structs/functions from game.rs or matrix.rs in main.rs with a mod game; or mod matrix;. I can't, however, reference matrix.rs from game.rs with a statement like mod matrix.
I've looked at several resources and all of them only have modules structures like trees that don't reference each other. Is it possible to use structs/functions from files in each other in Rust, or is that against the rules? If so, why doesn't Rust let you do that?
mod is module declaration. This directive declares a module and all of its contents. It just so happens that these contents may be located in another file. So this:
mod game;
mod matrix;
is roughly equivalent to this:
mod game {
// game.rs contents
}
mod matrix {
// matrix.rs contents
}
Naturally, since mod is a declaration of a module, you can't do it multiple times for the same module. That is, you can try and write something like
mod game {
mod matrix;
...
}
mod matrix;
but, as you can see, matrix and game::matrix are different modules, and naturally rustc requires different paths to their respective files, if they are external.
use, however, is import declaration. use declarations pull names from other modules for use in the current module. You can use any module and any public items from it any number of times from anywhere this module is accessible.
So, in order to reference matrix from game you need to use it:
// game.rs
use matrix;
Naturally, in order for this to work matrix should be declared with mod in the crate root.
As a side note, I personally think that the simplest way to understand Rust module system is to first forget that modules can be put in different files at all. That is, think as if a crate can only be defined in a single file. In Rust mod directives can have bodies and can nest, so nested mods actually define the module system of a crate:
mod foo {
mod bax {
...
}
mod baz {
...
}
}
mod bar {
mod qux {
mod zux {
...
}
}
}
If you only have a single file, you can easily see how mod and use directives would work, and relationship between modules should become clear.
And now you only need to add to the picture the fact that if a module is declared without a body, like in mod name;, its content is loaded either from name.rs or name/mod.rs, whatever is available. However, the full picture does not change in the slightest - these still are nested modules which can always be represented as a single source file with nested mod directives. In fact, cargo rustc -Z unstable-options --pretty=normal will print your crate in this form, after all modules in external source files are assembled into a single document. I suggest running this command on some crates with complex module structure to see how it looks in practice.

Resources