Repository navigation
Closed
Labels
A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyC-bugCategory: This is a bug.Category: This is a bug.P-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
I tried this code:
mod foo {
pub mod bar {
pub mod bar {
pub fn foobar() {}
}
}
}
use foo::*;
use bar::bar;
use bar::foobar;
fn main() {
bar::foobar();
}I expected to see this happen: Compilation error. This use bar::bar; shadows one (glob-imported) bar with another bar. As far as I know, this should be forbidden.
Instead, this happened: this code successfully compiled.
Meta
rustc --version --verbose:
rustc 1.47.0-nightly (d7f945163 2020-07-19)
binary: rustc
commit-hash: d7f94516345a36ddfcd68cbdf1df835d356795c3
commit-date: 2020-07-19
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0
c.c. @matklad
c.c. @petrochenkov
Metadata
Metadata
Assignees
Labels
A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyC-bugCategory: This is a bug.Category: This is a bug.P-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Activity
197g commentedon Jul 21, 2020
Shadowing a glob import with a specific item is allowed and will unambiguously resolve to the specific one. This is also how the prelude works. The following compiles fine as well:
playground.
matklad commentedon Jul 21, 2020
To clarify, the problem is not shadowing, but time travel. We shadow identifier which have been already used to resolve another import, so we end up with
barmeaning two things at the same time in the same scope.petrochenkov commentedon Jul 21, 2020
This is a change from Rust 1.44, in Rust 1.43 this is an ICE "inconsistent resolution for an import".
Possibly a consequence of #70236.
petrochenkov commentedon Jul 21, 2020
I'm not sure this is a bug.
When resolving
use bar::bar;we are looking at all names in scope except for the names introduced byuse bar::bar;itself. Otherwise we'd have cycles even in trivial cases likeuse my_crate;wheremy_crateis a name from extern prelude.If you take this detail into consideration, then all paths seem to be resolved correctly.
petrochenkov commentedon Jul 21, 2020
cc #62769 (somewhat related)
vlad20012 commentedon Jul 21, 2020
I think, the difference with
use my_crate;is thatuse my_crate;doesn't replace one resolution with another. We already have a namemy_cratein the scope that is resolved to a particular extern crate.In my example,
use bar::bar;usesbarname from the scope, and then rebinds thisbarname to another item.I can complicate my example a bit.
What this program prints, "111" or "222"? It'd say, it depends on imports resolution order, but looks like it always prints "111".
petrochenkov commentedon Jul 21, 2020
The intent for the resolution results is to never depend on internal resolution order.
(cc #53778 (comment), order-dependence can probably happen in practice due to the current not very principled implementation, but hopefully still can be eliminated in backward-compatible-in-practice way by rewriting the main resolution/expansion loop more carefully.)
That's what I'd expect.
foobarresolves touse bar::foobarbarinbar::foobarresolves touse bar::bar(because non-globs shadow globs)barinbar::barresolves touse foo::*(which the onlybarin scope after excludinguse bar::baritself)petrochenkov commentedon Jul 21, 2020
I'd still be ok with replacing the former ICE with an error though, since that's a more conservative choice.
petrochenkov commentedon Jul 21, 2020
Actually enabling the property "name resolve to the same thing whether some items were excluded during its resolution to avoid cycles or not" may be useful for using something like "inference variables" for unresolved imports and making import resolution more like unification in type inference.
That's an idea I had for quite some, but I hadn't realized that merging #70236 went against it.
petrochenkov commentedon Sep 30, 2020
Sigh, the issue already affects three stable releases - from 1.44 to 1.46.
I'll try to prioritize it.
petrochenkov commentedon Oct 1, 2020
Addressed in #77421.
camelid commentedon Oct 2, 2020
Assigning
P-highso this isn't lost. See the relevant discussion.petrochenkov commentedon Oct 5, 2020
The fix caused some regressions - #77586.
vlad20012 commentedon Mar 10, 2023
@petrochenkov The code in the issue produce no errors using Rust 1.67.1. Should we re-open the issue or is it not considered a bug now?
petrochenkov commentedon Mar 10, 2023
@vlad20012
The fix was reverted due to breakage (#78784) and the current behavior is considered by design since then.
petrochenkov commentedon Mar 10, 2023
(Also it's not exactly a time travel - #77586 (comment).)