rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.81k stars 12.5k forks source link

Unresolved import (E0432) when use'ing name that shadows a star-imported one #102855

Open Xion opened 1 year ago

Xion commented 1 year ago

Let's say we have the following layout of files (simplified example with (hopefully) irrelevant details omitted):

common/animation/plugins.rs

use bevy::prelude::*;

// shadows bevy::prelude::AnimationPlugin
pub struct AnimationPlugin;

common/animation/mod.rs

mod animation;

pub use self::plugins::*;

app.rs

use crate::common::animation::AnimationPlugin;

This results in the following error:

error[E0432]: unresolved import `crate::common::animation::AnimationPlugin`
  --> src/app.rs:11:5
   |
11 | use crate::common::animation::AnimationPlugin;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0432`.

At best, this is a confusing diagnostic message. The import isn't unresolved, though it might be ambiguous as to which AnimationPlugin we are referring to here. The message should highlight this fact, making it more clear what the possible solutions are (e.g. replacing use bevy::prelude::*; with more selective imports).

However, I'm not entirely sure if this is even the correct behavior. At any point inside common::animation::plugins, it is perfectly unambiguous which AnimationPlugin we are referring to; the custom one shadows the one defined in bevy::prelude. But for some reason, this doesn't carry over through a simple re-export in common::animation root module.

I'm reluctant to flag this as a compiler bug because I don't claim to fully understand the expected language rules here, but hopefully someone from the Rust team can determine if this is intended. But even if it's correct for the compiler to reject this code, the resulting error message could definitely be more clear.

SNCPlay42 commented 1 year ago

It would be helpful to have complete code to reproduce the issue; my attempt at reproducing behaves the way I would expect it to - there is no error; the locally-defined type is what is imported. It's possible I'm misunderstanding your file/module tree - the fact that common/animation/mod.rs, presumably the source for the module crate::common::animation contains a mod animation; statement implying the existence of a module crate::common::animation::animation seems potentially incorrect.

Note that if the problem in your code is being caused by an ambiguity, you should be getting E0659, not E0432. It is strange that the E0432 message you're getting is not telling you which part of the path crate::common::animation::AnimationPlugin is problematic - usually there would be note like no `bar` in `foo`.

Xion commented 1 year ago

Thanks for the pointer to E0659! If I understand correctly, this means that the ambiguity does exist and it's just the matter of rustc producing the wrong diagnostic.

Also thanks for attempting to reproduce the issue. When I tried to prepare a minimal-ish example myself, I noticed that I missed another star-import of bevy::prelude::* in app.rs. which is likely the ultimate culprit (possibly unrelated to the common::animation submodule). I still think the error message is wrong, as the import in question is definitely NOT unresolved.

In any case, I extracted a minimal-ish repro of the problem and pushed it to https://github.com/Xion/rust-issue-102855 . Let me know if this helps!

SNCPlay42 commented 1 year ago

The repro was very helpful! I managed to reduce it to this:

use self::animation::File;

mod animation {
    mod plugins {
        use std::fs::*;

        #[derive(Default)]
        pub struct File;
    }

    pub use self::plugins::*;
}

I think this is the same thing as #56593.

Xion commented 1 year ago

If the #[derive(Default)] made or broke the repro, then it indeed looks similar to #56593 . Very curious; I'll be watching both issues. Fortunately, the workaround is straightforward (replace the inner-most use foo::* with use foo::{Actual, Symbols};) so it's not a problem one cannot live with :)

Thanks again for looking into this!

Xion commented 1 year ago

I can confirm that in my actual code, removing #[derive(Default)] and restoring use bevy::prelude::*; does indeed fix the error. Same for the repro project.

So this is almost certainly the same issue as #56593.