`use self::super` is accepted. Is this intended?

If we use super in the middle of the path, we will get a compile error: "super in paths can only be used in start position".

However, we can sometimes use super in non-initial positions. Here is an example:

pub fn main() {
    println!("Hello, world!");
}

pub mod submodule {
    // use super::main;  // OK
    use self::super::main;  // Somehow accepted
    // use crate::submodule::super::main;  // Error

    pub fn foo() {
        main();
    }

    pub mod yet_another_submodule {
        // use super::super::main; // OK
        use self::super::super::main;  // Somehow accepted
        // use super::self::super::main; // Error

        pub fn foo() {
            main();
        }
    }
}

Is this an intended behavior?

2 Likes

The logic resolving self::super is ancient, it works since Rust 1.0.

You can find inside fn resolve_path_with_ribs in compiler\rustc_resolve\src\lib.rs.
I doubt anyone remembers now whether it's intended or not.
You can use git blame https://github.com/rust-lang/rust/blame/master/compiler/rustc_resolve/src/lib.rs to go through the history and find out when exactly it was introduced, maybe the PR/commit description will shed some light on this problem.

The behavior is reasonable though.
self and super are equivalents of . and .. on the filesystem, and they occasionally work when not written at the path start, e.g. in use a::b::{self} = a/b/. = a/b = a::b.
So the restriction regarding their positions in paths is artificial, and I'd personally just lift it entirely some day.

5 Likes