Repository: rust
Issue: Trait fn impl takes precedence over concrete type's fn impl depending on visibility
Labels: A-trait-system,A-visibility,T-compiler,C-bug,T-types

How function names are resolved to concrete implementations on concrete struct and trait objects appears to be incorrect for a specific (but reasonable) corner case.

Suppose we have

 * a concrete struct type `MyStruct`
 * a method `foo_function(…)` implemented on `MyStruct` (i.e. within `impl MyStruct{}`)
 * a trait `MyTrait` having a trait method `foo_function(…)`
 * a submodule `my_submodule` within whatever module contains `MyStruct`.
 * an implementation of `MyTrait` for `MyStruct`, which necessarily has an implementation for the `MyTrait`  `foo_function(…)` function. (It doesn't matter if it's the default impl of `foo_function(…)` for `MyTrait`.)

Which function the expression `MyStruct::foo_function(…)` resolves to depends on whether the implementation of  `foo_function(…)` for `MyType` is inside of `sub_module`. See the code below.

I tried this code:

```rust
struct MyStruct{}

impl MyStruct {
    pub fn bar_function(&self) {
        // Which function is called in the following depends on the visibility of the concrete type's `foo_function`.
        // This behavior is NOT exhibited if we move the concrete type's `foo_function` impl to the same module.

        // Call the function on the concrete `MyStruct` instance. Which function is _actually_ called?
        self.foo_function();

        // Same as above but with explicit notation to emphasize we are naming the MyStruct version in the call.
        MyStruct::foo_function(self);
    }

    // The following is an error if its counterpart in `my_submodule` exists.
    // fn foo_function(&self){
    //     println!("a third possibility.");
    // }
}

// Some of the `MyStruct` impl in a submodule, for example, another file to keep the codebase navigable.
mod my_submodule {
    // pub(crate) // Has no effect on behavior in question.
    use crate::{MyStruct};

    impl MyStruct {
        pub // Different behavior depending on whether `fn` is `pub` or not.
        fn foo_function(&self) {
            println!("The MyStruct fn");
        }

        pub fn baz_function(&self) {
            // Resolves to the method immediately above this one in every case.
            MyStruct::foo_function(self);
        }
    }
}

trait MyTrait {
    fn foo_function(&self);
}

impl MyTrait for MyStruct {
    fn foo_function(&self) {
        println!("The trait impl fn.");
    }
}

fn main() {
    let my_concrete_struct: &MyStruct = &MyStruct{};

    my_concrete_struct.foo_function();
    my_concrete_struct.bar_function();
    my_concrete_struct.baz_function();
}
```

**I expected to see this happen:**

In any context in which private methods of `MyStruct` are normally visible, I expect `MyStruct::foo_function` to resolve to the implementation of `foo_function(…)` on `MyStruct` regardless of the visibility of that implementation. In other words, I expect the statement  `MyStruct::foo_function(my_concrete_struct);` and `my_concrete_struct.foo_function();`  to print `The MyStruct fn` whenever they are in the implementation of a method on `MyStruct`. Moreover, I expect a `pub` annotation on an implementation on `MyStruct` to modify the visibility of the function outside of the implementation of `MyStruct` while having no effect on its visiblity within a module.

**Instead, this happened:** 

When the implementation of  `foo_function` on `MyStruct` is `pub` (i.e. `pub fn foo_function(…)…`), the expression `MyStruct::foo_function` does preferentially resolve to the implementation on `MyStruct` regardless of where it is called from. However…

When  the implementation of  `foo_function` on `MyStruct` is not `pub`, that function is inaccessible even to other methods of `MyStruct` the implementations of which are outside of `my_submodule`, but remain accessible to methods on `MyStruct` defined within `my_submodule`. There appears to be no "fully qualified name" which allows methods outside of `my_submodule` to access the method inside `my_submodule` nor a "fully qualified name" which allows methods inside `my_submodule` to access methods outside of `my_submodule` except by importing the trait and using `MyTrait::foo_function(&self)`.

Apparently, declaring the `foo_function` within `my_submodule` as `pub` makes it public not just within the struct but within the submodule as well. Likewise, declaring the `foo_function` within `my_submodule` *without* the `pub` annotation makes it not only private to code outside of the implementation of `MyStruct` but also private within `my_submodule`. For other methods on `MyStruct` defined within `my_submodule`, the `foo_function` within `my_submodule` shadows any definition outside of `my_submodule`.

Curiously, if there is an implementation of  `foo_function`  on `MyStruct` (as opposed to a trait implementation) outside of `my_submodule`, that implementation *cannot* be shadowed by another implementation of  `foo_function`  on `MyStruct` defined within `my_submodule` . One might expect otherwise considering the notation `MyStruct::foo_function` is allowed to vary depending on scope.

A consequence of this behavior is that a trait fn impl can take precedence over a concrete type's fn impl when the concrete type's impl is not pub and in a submodule.

### Meta

Doesn't appear to depend on compiler version.