Are module declarations allowed inside functions?


#1

Consider the following code.

fn foo() {
    mod m;
}

fn bar() {
    mod m;
}

It compiles if you have m.rs, but it works strange: the m module is essentially duplicated.

Is this intentional that non inline modules are allowed inside functions?


#2

Well, you’re allowed to put items into functions, and there’s no real reason why modules should be specifically excluded. Also, “non inline” modules are just syntax sugar for “inline” modules; the compiler doesn’t distinguish between the two AFAIK. It does the same thing as if you’d copy+pasted the contents of m.rs twice.

So sure, why not.


#3

Hah, that’s strange and most likely accidental. I filed #29765 about making an explicit decision.


#4

A similar strange piece of code is

mod foo;

#[path = "foo.rs"]
mod bar;

#5

Oh, you haven’t seen anything until you’ve tried:

#[path = "/dev/stdin"]
mod foo;

fn main() {
    foo::hello();
}
$ rustc stdin.rs
pub fn hello() {
    println!("Hi!");
}
$ ./stdin
Hi!

#6

Windows also has this cool feature:

mod Foo;
mod foo;
fn main() {
    foo::hello();
    Foo::hello();
}
// foo.rs
fn hello() { println!("hello"); }

#7

Oh, that’s fun too, but it one isn’t quite so strange IMO: having the attribute is explicitly opting-in to importing the same file twice. (Maybe there could be a lint against it? Although, I imagine most cases where one does it accidentally will result in a compilation error earlier.)


#8

At least you’ll get a warning about snake case names for Foo. But yes, case-insensitivity is ugly. If your file was called Foo.rs and you wrote mod foo; then it would only work on Windows.