Reputation: 8712
I came across some code in a piece of published code that had something like the following structure (which compiles and runs fine):
pub mod foo {
pub const BAR: u32 = 53;
#[allow(non_snake_case)]
pub mod BAR {
pub fn eep() {
println!("This is attached to BAR");
}
}
}
fn main() {
println!("Hello, world!, {}", foo::BAR);
foo::BAR::eep();
}
This seems strange and interesting to me. The strange bit being BAR
being defined as both a const
and a mod
.
Is this idiomatic Rust?
What is going on here? Should I be able to find out about this in the docs? When is such a pattern valid?
I can see that this might be useful, but is there some really compelling use case?
Upvotes: 3
Views: 2812
Reputation: 431669
No, it's not idiomatic, and the compiler already tells you this:
warning: module `BAR` should have a snake case name
--> src/main.rs:4:13
|
4 | pub mod BAR {
| ^^^ help: convert the identifier to snake case: `bar`
|
= note: #[warn(non_snake_case)] on by default
The warning has been silenced in the code you have presented, for whatever reason.
normally whilst programming one can't attach the same label to multiple constructs in the same namespace
That's correct. Modules and constants are in different namespaces. There are three namespaces:
fn main() {
macro_rules! BAR { () => {} }
mod BAR {}
let BAR = 1;
}
Modules are in the type namespace.
I don't understand what
BAR
is. Is it a module, or is it a const?
There's one of each.
See also:
I'd probably write this:
pub mod foo {
use std::fmt;
pub const BAR: Bar = Bar(53);
pub struct Bar(u32);
impl Bar {
pub fn eep(&self) {
println!("This is attached to Bar");
}
}
impl fmt::Display for Bar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
}
fn main() {
println!("Hello, world!, {}", foo::BAR);
foo::BAR.eep();
}
Upvotes: 4