-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
resolve: Report more visibility-related early resolution ambiguities for imports #149596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@bors try |
This comment has been minimized.
This comment has been minimized.
resolve: Report more early resolution ambiguities for imports
|
|
|
@craterbot run mode=check-only p=1 crates=https://crater-reports.s3.amazonaws.com/pr-149145/retry-regressed-list.txt |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🎉 Experiment
Footnotes
|
9c25090 to
1ea10c2
Compare
This comment has been minimized.
This comment has been minimized.
|
@bors try |
This comment has been minimized.
This comment has been minimized.
resolve: Report more early resolution ambiguities for imports
|
☔ The latest upstream changes (presumably #147984) made this pull request unmergeable. Please resolve the merge conflicts. |
|
During the lang meeting today, Niko and I batted back and forth some ideas on how this model could be simpler by adopting a model where import chains don't matter for final visibility. In this model, all that matters is the original item visibility and the final import visibility, assuming each import along the way is allowed according to the current scope visibility. (We decided to take the discussion to Zulip and didn't discuss the other reasons you gave in #141043 (comment) for why import chains matter.) After the meeting, @Nadrieril pointed out that this is problematic when talking about glob imports (should have seen that one coming..), and would silently change the public API of existing crates: mod internal {
mod inner {
pub struct Foo;
}
pub(crate) use inner::Foo;
pub struct Bar;
}
pub use internal::*; // `Foo` would now be part of the public API of the crateWhile I still like the idea of simplifying the story for non-glob imports, we can't change the public API of existing crates. Adopting this model is therefore going to require one of two options:
Either way, we are going to need to handle ambiguous cases like the ones caught by this PR. |
|
@petrochenkov thanks for the writeup in #149596 (comment). This seems like a reasonable step to make our model more precise. I hope it eventually helps us unblock efforts on parallel resolution. As I detailed in my comment above, the kind of ambiguity this PR catches is going to matter whether we like it or not. So we might as well start cleaning them up now. @rfcbot fcp merge lang |
|
@rfcbot fcp merge lang |
|
Team member @tmandry has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
|
Possibly-relevant rules, by the way, in the pending Reference PR, include:
(See the PR for examples for each of these rules and explanatory admonitions.) |
|
Let's talk through what we're doing here. Today, this is an error: mod m {
pub struct S {}
}
macro_rules! mac { () => { struct S {} }}
pub use m::*;
mac!();
pub use S as _;
//~^ error[E0659]: `S` is ambiguousWhy? What do the rules say? First:
Are there two name candidates? Yes; the struct in Do they resolve to the same entity? No; they have two distinct definitions. Is one permitted to shadow the other? Let's see.
This is indeed
So this would be allowed normally. If
Because the Conversely, this is accepted today: mod m {
pub struct S {}
}
macro_rules! mac { () => { use m::S; }}
pub use m::*;
mac!();
pub use S as _; //~ OKWhy? Are there two name candidates? Yes. But now they resolve to the same entity. The ambiguity still exists, but because both resolution paths lead to the same definition, the compiler currently considers it benign and accepts it. Should we lint about this? @petrochenkov gives three rules:
Taking them in turn: One. What's ambiguous mean? As I read this (and, @petrochenkov or @yaahc, correct me if I'm wrong), this is suggesting that two declarations are ambiguous when they are candidates for the same name in the same scope and neither is permitted to shadow the other or the resolution order would make the shadowing unpredictable. I.e., they are ambiguous when we would give an error if the definitions of those declarations are not the same. So these declarations are ambiguous. Two. They have the same definition. Do they have different visibilities? Yes. Three. The visibility of the import is QED. We lint this case. Net-net, with this FCW, we're reducing the scope of what we consider to be a benign ambiguity. Based on that understanding... @rfcbot reviewed |
I do note a possible counterexample to the way I stated it here (in the i.e.). We give an error for this: mod m1 {
pub struct S {}
}
mod m2 {
pub struct S {}
}
pub mod m3 {
pub use crate::m1::*;
use crate::m2::*;
}
pub use m3::S as _;
//~^ error[E0659]: `S` is ambiguousBut the PR branch does not warn if we make the definition for each declaration the same: mod m1 {
pub struct S {}
}
pub mod m3 {
pub use crate::m1::*;
use crate::m1::*;
}
pub use m3::S as _;Do we not consider these declarations ambiguous, or what's the rule we're using to decide to not lint here? |
They are also ambiguous, this part of the lint is just not implemented yet. I plan to implement it too, but to do that you'd need something like https://github.com/petrochenkov/rust/tree/neverwrite, which it is mostly blocked on #149195. |
|
Makes sense. So we're expecting a later expansion of this lint. |
|
@petrochenkov, I wanted to ask you a question. Thinking through this issue made me realize that my "mental model" for how How I think the code worksI believe that when you have a mod mod_a {
use crate::mod_b::B;
pub struct A;
}
mod mod_b {
pub struct B;
}
use mod_a::A; // errors, the `use` is not public hereHowever it also means that this example errors: mod mod_a {
use crate::mod_b::B as B2; // "private" item
pub use B2 as B3; // re-exporting a private item as public, error
pub struct A;
}
mod mod_b {
pub struct B;
}
use mod_a::B2; // errors, the `use` is not public here
use mod_a::B3; // errors, the `use` is not public hereIndeed, I think this is the case that the issue describes. An alternative modelThings could also work a bit different. Instead of having To resolve a path In a This implies that the first example errors, but the second example behaves a touch differently: mod mod_a {
use crate::mod_b::B as B2; // "private" item
pub use B2 as B3; // re-exporting a private item as public, error
pub struct A;
}
mod mod_b {
pub struct B;
}
use mod_a::B2; // errors, the `use` is not public here
use mod_a::B3; // OK!
My question then
|
Yes, but there are more nuances because mod m {
pub type name = ();
pub(crate) fn name() {}
macro name() {}
}
pub use m::name;
// Works like
pub use m::name as type;
pub(crate) use m::name as fn;
// macro `name` is filtered away as too private, not imported, exactly like with glob imports pub use m::*;
// Works like
pub use m::name as type;
pub(crate) use m::name as fn;
// macro `name` is filtered away as too private, not imported |
This comment was marked as resolved.
This comment was marked as resolved.
The new ambiguities are reported when the import's visibility is ambiguous and may depend on the resolution/expansion order.
a9a2fe7 to
8238790
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
The new ambiguities are reported when the import's visibility is ambiguous and may depend on the resolution/expansion order.
Detailed description: #149596 (comment).