Implicit use of a trait in its implementation leaks through a module

Consider this code (playground):

mod a {
    pub trait Foo {
        fn bar(&self);
    }
}

impl a::Foo for () {
    fn bar(&self) {
        mod hide { // We're in a new module...
            pub fn baz() {
                // ...so why is `Foo` in scope here?
                ().bar()
            }
        }
        hide::baz();
    }    
}

impl a::Trait for () implicitly brings Foo into scope. Weirdly enough, it stays in scope even when we’re in a nested module inside of a trait function. I have a few questions related to this snippet:

  1. Is this behaviour (implicit use leaking through a module) expected? Is it desired? Edition 2024 is coming, so we could change it if it’s accidental.
  2. Is it documented anywhere?
  3. In fact, is the implicit use itself documented anywhere?
  4. If I were to make PR into reference + book, where do you think it should be documented? Reference’s section on scopes is currently just a stub, and I don’t feel like I’m able to write a whole section.
1 Like

I feel like an appropriate place in the Book to document it is somewhere near here: https://doc.rust-lang.org/stable/book/ch10-02-traits.html#implementing-a-trait-on-a-type

I’m not sure what the appropriate place in the Reference is. Probably here: Implementations - The Rust Reference and preferably also in Scopes section, but it doesn’t actually exist yet. There’re other possible places though, so I’m not sure.

Related: this code compiles

mod a {
    pub trait Foo {
        fn bar(&self);
    }
}

pub fn baz<T: a::Foo>(y: T) {
    y.bar();
}

but this doesn’t:

mod a {
    pub trait Foo {
        fn bar(&self);
    }
}

impl a::Foo for () {
    fn bar(&self) {}
}

pub fn baz<T: a::Foo>(y: T) {
    ().bar();
}

so any generic bound brings its trait in scope, but only for the bound parameter? Reference says that

In the body of a generic function, methods from Trait can be called on Ty values. Likewise associated constants on the Trait can be used.

in Trait and lifetime bounds - The Rust Reference, but I’d add something like “even if the trait isn’t in scope”, because it’s non-obvious IMHO.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.