mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use self::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
hosting::add_to_waitlist();
hosting::add_to_waitlist();
}
The code is from Rust Book. In this case, if using the relative path, why bother to use self? I find that use front_of_house::hosting works well here.
So, any necessary reason to introduce self here?
The outcome of use front_of_house::hosting depends on the context. If the crate root contains extern crate front_of_house or front_of_house is a dependency in Cargo.toml, this will refer to hosting in that crate. In your case, however, there is the local module front_of_house, which takes priority over external crates. Conveniently, it's located just before the code that uses it, so it's obvious that it's the actual module being used. In larger files, however, there is a chance that the source of a module is ambiguous, i.e. if there is a dependency named the same as a local module. In that case, the extra self adds clarity to the code, helping you differentiate between dependencies and local modules. If, in that case, you wanted to use the dependency, you'd use ::front_of_house::hosting, which unconditionally refers to the dependency and fails if there isn't one named like that.
Related
I am working on a Rust module that has a small external interface, but its internal implementation is large and complex.
Is there a sane way to avoid having a huge file with all the code for the module while still exposing a small interface to external module consumers?
AFAIK, Rust does not allow you to use several files for the same module, as for instance Go allows for package directories. It does not matter that the Rust module is defined in a directory, it still expects one single file.
That way, to split code up you are forced to use sub-modules for sub-types or implementation details that you would want to split apart. I understand that should not matter much for compiled code, all overhead of the module organization is removed.
But there is a design problem, if I split things up in modules, those will need to export things so that I can used them from my other modules... but then those "exported internals" can ALSO be used by external consumers, right? Is there a way to avoid exposing those internal interfaces?
But there is a design problem, if I split things up in modules, those will need to export things so that I can used them from my other modules... but then those "exported internals" can ALSO be used by external consumers, right?
No, they can not.
Making a symbol public in a sub-module only makes it available to its immediate parent. That parent module would then have to re-export that symbol via pub use for the visibility to "bubble up".
mod foo {
mod bar {
pub fn visible_in_foo() {}
pub fn visible_in_root() {}
fn private() {}
}
// Re-export to make visible at the next outer level
pub use bar::visible_in_root;
pub fn foo() {
// We are in the immediate parent, so both `pub` functions are visible
bar::visible_in_foo();
bar::visible_in_root();
// bar::private(); - Won't compile
}
}
// Make it public to consumers of the library, aka. external API
pub use foo::foo;
fn main() {
// Notice that it's just `foo`. Not `foo::bar` or `bar`.
// Re-exporting makes the symbol a part of module `foo`.
foo::visible_in_root();
// foo::visible_in_foo(); - Won't compile
// `foo::foo` does have access to the inner module, though,
// so we can call `foo::bar::visible_in_foo` indirectly here.
foo::foo();
}
Additionally, you can mark symbols as pub(crate), which works like pub, except it prevents the symbol from becoming public outside the crate, even if it were re-exported by all of its parent modules.
Further reading:
The Rust Programming Language - Defining Modules to Control Scope and Privacy
The Rust Reference - Visibility and Privacy
Recently, I started to learn rust. I'm currently at section 7.4 (bringing paths into scope). Tried hard, but I can't understand the purpose of self::some_sort_of_identifier in rust. Would you please explain what is the difference between use self::module_name::function_name and use module_name::function_name? I tried both and they both worked as expected in the example below:
mod my_mod {
pub fn func() {
print!("I'm here!");
}
}
use my_mod::func;
fn main() {
func();
}
Running this program, as expected, I can see this statement printed into the terminal:
I'm here
And this program here gives me exactly the same results and the rust compiler doesn't complain about anything:
mod my_mod {
pub fn func() {
print!("I'm here!");
}
}
use self::my_mod::func;
fn main() {
func();
}
So, is self:: useless in rust? Why should I even use self::my_mod::my_function(); when I can directly call it like so: my_mod::my_function();.
Are there any cases in which they might defer?
For your use-case, it's mainly a relict from the 2015 rust edition.
In this edition the following code would not compile:
use my_mod::func;
mod my_mod {
use my_mod2::func2;
pub fn func() {
func2();
}
mod my_mod2 {
pub fn func2() {
print!("I'm here!");
}
}
}
fn main() {
func();
}
The compiler complains:
error[E0432]: unresolved import my_mod2
--> src\main.rs:4:9
|
| use my_mod2::func2;
| ^^^^^^^ help: a similar path exists: self::my_mod2
Why did it change? You can see the note about the path and module system changes here.
Rust 2018 simplifies and unifies path handling compared to Rust 2015. In Rust
2015, paths work differently in use declarations than they do
elsewhere. In particular, paths in use declarations would always start
from the crate root, while paths in other code implicitly started from
the current scope. Those differences didn't have any effect in the
top-level module, which meant that everything would seem
straightforward until working on a project large enough to have
submodules.
In Rust 2018, paths in use declarations and in other code work the
same way, both in the top-level module and in any submodule. You can
use a relative path from the current scope, a path starting from an
external crate name, or a path starting with crate, super, or self.
The blog post Anchored and Uniform Paths from the language team also underlines this
The uniformity is a really big advantage, and the specific feature we’re changing -
no longer having to use self:: - is something I know is a big
stumbling block for new users and a big annoyance for advanced users
(I’m always having to edit and recompile because I tried to import
from a submodule without using self).
The keyword itself however is still useful in use statments to refer to the current module in the path itself. Like
use std::io::{self, Read};
being the same as
use std::io;
use std::io::Read;
I have a crate that has lots of code, so I've split it into multiple files/modules. However, some modules have internal unsafe stuff (e.g. raw pointers) that I need to make public to the different modules, but I don't want to expose to users of my crate. How can I do that?
The only way I can think of is to actually have my crate just be one big module, but then there's no way to split it into different files, other than this solution which seems a bit hacky.
Normally when I come up against a real world problem that the simple examples in the Rust docs don't adequately explain I just copy a popular real world crate, e.g. git2-rs, but that just seems to effectively make everything public, including the raw pointers.
In order for an item to be exported from a library crate, there must be at least one path leading to it in which every component is public. This means that all you need to make an item public within your crate but not exported from the crate (I'll call this "internal" from now on, to mimic C# terminology) is to put it in a private module under the crate root.
However, that solution is quite restrictive. What if you'd like to have a module with exported functions and internal functions? In order to export some functions, we need to make the module public, and that mean all public items in that module will be exported as well.
Since Rust 1.18, there's a solution adapted to this kind of scenario: pub(restricted). This feature lets you specify "how public" an item should be. The syntax is pretty flexible (you can make an item visible to a particular module tree instead of the whole crate), but if you want to keep it simple, pub(crate) will make an item accessible anywhere within the crate, but not to other crates (equivalent to internal in C#).
For example, suppose we'd like to have a module util in which foo is exported (as mycrate::util::foo), bar is internal and baz is private to the module. The code might look like this:
pub mod util {
pub fn foo() {
unimplemented!()
}
pub(crate) fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
If you're stuck on pre-1.18 Rust, there's a workaround, but it's a bit clunky. It involves defining all your items in private modules, and reexporting only those that you want to make public (with pub use) in public modules that only contain reexports. Here's what the example above would look like:
pub mod util {
pub use util_impl::foo;
}
mod util_impl {
pub fn foo() {
unimplemented!()
}
pub fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
Not only is this not easy to read and understand, it doesn't cover all situations where pub can be used. For example, how would you make some fields of an exported struct accessible in other modules in the same crate without also exporting them? The only option would be to expose a wrapper with a single private field whose type is the struct that has public fields; that works fine if you want to hide all fields from other crates, but not if you want to expose some fields and make some other fields internal in the same struct.
I've got a toy project that's using the Amethyst game engine. I'm trying to write my own System for collecting user input, similar to the FlyMovementSystem and ArcBallRotationSystem they have implemented here.
It appears the right way to go about collecting mouse movements is via an EventChannel<Event>, where Event comes from the winit crate, which Amethyst depends on, but does not re-export.
What's the "right" way to reference the same winit::Event that Amethyst does?
Should I add winit to my Cargo.toml file? If so, what is the recommended way to specify the version? (Is there some keyword I can use instead of a specific version number, to allow me to "inherit" the dependency from Amethyst?)
Is referencing sub-dependencies actually discouraged? If so, what should I be doing instead?
There is currently no great solution to this problem. The best workaround is to add a direct dependency on the same version of the transitive dependency:
[dependencies]
foo = "0.1"
bar = "0.2" # `foo` depends on bar 0.2 and we need to keep these in sync
You can use tools like cargo tree to manually identify the versions needed by foo and keep your Cargo.toml up to date. I highly recommend adding a comment specifying why you've picked a specific version.
If the crate is very difficult to use without also using the underlying dependency alongside it, I'd also encourage you to file an issue with the parent crate to request that they re-export what is needed. A good example of this is the Tokio crate, which re-exports large chunks of the futures crate.
Similar to your idea, I proposed having a way to use the same version as a dependency. Instead, the Cargo team opted to add the distinction of public and private dependencies. While this will be a better solution from an engineering point of view, very little progress has been made on the implementation of it.
See also:
Why is a trait not implemented for a type that clearly has it implemented?
I'm leaving #Shepmaster's answer as the accepted one, as it answers the general question I was going for. But thanks to a gentle push from #trentcl, in case anyone found this question specifically for its relation to Amethyst, here's what I ended up doing.
Don't try to get the winit::Events at all.
When you attach an InputBundle<AX, AC> to your GameData, it sets up an InputSystem<AX, AC>, which re-publishes winit::Events in the form of InputEvent<AC>.
It does this by setting up an EventChannel<InputEvent<AC>> as a Resource, which you can access via the Read type in the ECS system. EventChannels and their usage are explained in the Amethyst Book.
I've since switched to a different approach for handling my user input, but here's roughly what it looked like (note: Amethyst a little after v0.10.0):
pub struct MouseMovementSystem {
reader: Option<ReaderId<InputEvent<()>>>, // AC = ()
}
impl<'s> System<'s> for MouseMovementSystem {
type SystemData = (
Read<'s, EventChannel<InputEvent<()>>>,
/* and others */
}
fn run(&mut self, (events, /* and others */): Self::SystemData) {
let foo = events.read(self.reader.as_mut().unwrap())
.yadda_yadda(/* ... */); // event processing logic
do_stuff(foo);
}
fn setup(&mut self, res: &mut Resources) {
use amethyst::core::specs::prelude::SystemData;
Self::SystemData::setup(res);
self.reader = Some(res.fetch_mut::<EventChannel<InputEvent<()>>>().register_reader());
}
}
I'm trying to figure out how to compile multi-file crates in Rust, but I keep getting a compile error.
I have the file I want to import into the crate thing.rs:
mod asdf {
pub enum stuff {
One,
Two,
Three
}
}
And my crate file test.rc:
mod thing;
use thing::asdf::*;
fn main(){
}
When I run rust build test.rc I get:
test.rc:3:0: 3:19 error: `use` and `extern mod` declarations must precede items
test.rc:3 use thing::asdf::*;
^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
There's obviously something simple about how modules, crates and use work that I'm just not getting. My understanding was that mod something; for files in the same directory or extern mod something; for libraries on the library path caused the object file to be linked. Then use would allow you to import parts of the module into the current file, function or module. This seems to work for stuff in the core library.
This is with version 0.6 of the rust compiler.
You just need to put the use at the top of the file:
use thing::asdf::*;
mod thing;
fn main() {}
This looks very strange, but
It's what the error message says (anything that you can put at the top level that is not use or extern mod is an "item", including mods), and
It's how Rust name resolution works. use is always relative to the top of the crate, and the whole crate is loaded before name resolution happens, so use thing::asdf::*; makes rustc look for thing as a submodule of the crate (which it finds), and then asdf as a submodule of that, etc.
To illustrate this last point better (and demonstrate the two special names in use, super and self, which import directly from the parent and current module respectively):
// crate.rs
pub mod foo {
// use bar::baz; // (an error, there is no bar at the top level)
use foo::bar::baz; // (fine)
// use self::bar::baz; // (also fine)
pub mod bar {
use super::qux; // equivalent to
// use foo::qux;
pub mod baz {}
}
pub mod qux {}
}
fn main() {}
(Also, tangentially, the .rc file extension no longer has any special meaning to any Rust tools (including in 0.6), and is deprecated, e.g. all the .rc files in the compiler source tree were recently renamed to .rs.)