Skip to content
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

Glob Time Travel #74556

Closed
vlad20012 opened this issue Jul 20, 2020 · 16 comments · Fixed by #77421
Closed

Glob Time Travel #74556

vlad20012 opened this issue Jul 20, 2020 · 16 comments · Fixed by #77421
Assignees
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@vlad20012
Copy link
Member

vlad20012 commented Jul 20, 2020

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

@vlad20012 vlad20012 added the C-bug Category: This is a bug. label Jul 20, 2020
@jonas-schievink jonas-schievink added A-resolve Area: Name/path resolution done by `rustc_resolve` specifically T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jul 20, 2020
@HeroicKatora
Copy link
Contributor

This use bar::bar; shadows one (glob-imported) bar with another bar. As far as I know, this should be forbidden.

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:

// implicit: use std::prelude::v1::*; containing Vec
struct Vec;

fn a() -> Vec { unimplemented!() }

playground.

@matklad
Copy link
Member

matklad commented 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 bar meaning two things at the same time in the same scope.

@petrochenkov
Copy link
Contributor

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 petrochenkov self-assigned this Jul 21, 2020
@petrochenkov
Copy link
Contributor

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 by use bar::bar; itself. Otherwise we'd have cycles even in trivial cases like use my_crate; where my_crate is a name from extern prelude.

If you take this detail into consideration, then all paths seem to be resolved correctly.

@petrochenkov
Copy link
Contributor

cc #62769 (somewhat related)

@vlad20012
Copy link
Member Author

vlad20012 commented Jul 21, 2020

I think, the difference with use my_crate; is that use my_crate; doesn't replace one resolution with another. We already have a name my_crate in the scope that is resolved to a particular extern crate.

In my example, use bar::bar; uses bar name from the scope, and then rebinds this bar name to another item.

I can complicate my example a bit.

mod foo {
    pub mod bar {
        pub mod bar {
            pub fn foobar() { println!("111") }
        }
        pub fn foobar() { println!("222") }
    }
}

use foo::*;
use bar::bar;
use bar::foobar;

fn main() {
    foobar();
}

What this program prints, "111" or "222"? It'd say, it depends on imports resolution order, but looks like it always prints "111".

@petrochenkov
Copy link
Contributor

It'd say, it depends on imports resolution order

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.)

but looks like it always prints "111"

That's what I'd expect.

  • foobar resolves to use bar::foobar
  • bar in bar::foobar resolves to use bar::bar (because non-globs shadow globs)
  • first bar in bar::bar resolves to use foo::* (which the only bar in scope after excluding use bar::bar itself)

@petrochenkov
Copy link
Contributor

I'd still be ok with replacing the former ICE with an error though, since that's a more conservative choice.

@petrochenkov
Copy link
Contributor

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
Copy link
Contributor

Sigh, the issue already affects three stable releases - from 1.44 to 1.46.
I'll try to prioritize it.

@petrochenkov petrochenkov added the regression-from-stable-to-stable Performance or correctness regression from one stable version to another. label Oct 1, 2020
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Oct 1, 2020
@petrochenkov
Copy link
Contributor

Addressed in #77421.

@petrochenkov petrochenkov removed the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Oct 1, 2020
@camelid
Copy link
Member

camelid commented Oct 2, 2020

Assigning P-high so this isn't lost. See the relevant discussion.

@petrochenkov
Copy link
Contributor

The fix caused some regressions - #77586.

@vlad20012
Copy link
Member Author

@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
Copy link
Contributor

@vlad20012
The fix was reverted due to breakage (#78784) and the current behavior is considered by design since then.

@petrochenkov
Copy link
Contributor

(Also it's not exactly a time travel - #77586 (comment).)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants