-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
|
🎉 Experiment
Footnotes
|
The new ambiguities are reported when the import's visibility is ambiguous and may depend on the resolution/expansion order.
1ea10c2 to
a9a2fe7
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. |
Change description for lang teamEarly name resolution has a number of ambiguity errors that are reported when a name declaration that is "unreliable" in some sense (e.g. comes from a glob import or macro expansion) may appear during macro expansion and shadow some more reliable declaration. The rules are documented in rust-lang/reference#2055. Currently those ambiguity errors are not always reported. In general, the benign ambiguities are not really benign, because the exact import chains are important (#141043 (comment)), One such case related to visibilities was discovered in // Outer scope
pub(crate) decl;
// "Unreliable" inner scope
// Both `decl`s refer to the same definition
pub decl;
// There's an ambiguity, and the reexport will either
// - report a privacy error (cannot reexport `pub(crate)` as `pub`)
// - or produce a `pub(crate)` declaration, if there's some other `pub` item called `decl` in a different namespace, that's what happens in `rust-embed`
// - successfully produce a `pub` declaration
// depending on unpredictable resolution internals.
// (An import's visibility is a minimum between it's own `use` item's visibility and its target declaration's visibility.)
pub use decl as rename;This PR reports a future-incompatibility lint called
The lint is warn-by-default and not reported in dependencies for now. |
|
☔ 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? |
The new ambiguities are reported when the import's visibility is ambiguous and may depend on the resolution/expansion order.
Detailed description: #149596 (comment).