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

resolve: improve import resolution #31461

Merged
merged 12 commits into from
Feb 11, 2016

Conversation

jseyfried
Copy link
Contributor

This PR adds to NameBinding so it can more fully represent bindings from imports as well from items, refactors away Target, generalizes ImportResolution to a simpler type NameResolution, and uses a single NameResolution-valued map in place the existing maps children and import_resolutions (of NameBindings and ImportResolutions, respectively), simplifying duplicate checking and name resolution.

It also unifies the resolve_name_in_module in lib.rs with its namesake in resolve_imports.rs, clarifying and improving the core logic (fixes #31403 and fixes #31404) while maintaining clear future-comparability with shadowable globs (i.e., never reporting that a resolution is a Success or is Failing unless this would also be knowable with shadowable globs).

Since it fixes #31403, this is technically a [breaking-change], but it is exceedingly unlikely to cause breakage in practice. The following is an example of code that would break:

mod foo {
    pub mod bar {} // This defines bar in the type namespace
    pub use alpha::bar; // This defines bar in the value namespace

    // This should define baz in both namespaces, but it only defines baz in the type namespace.
    pub use self::bar as baz;
    pub fn baz() {} // This should collide with baz, but now it does not.
}

pub fn f() {}
mod alpha {
    pub use self::f as bar; // Changing this to `pub fn bar() {}` causes the collision right now.
    pub use super::*;
}

r? @nrc

@jseyfried jseyfried force-pushed the remove_import_resolutions branch from 828bd48 to 6a2f81e Compare February 7, 2016 08:18
@jseyfried
Copy link
Contributor Author

cc @petrochenkov @nikomatsakis

@jseyfried jseyfried force-pushed the remove_import_resolutions branch from 6a2f81e to eb1a9b6 Compare February 7, 2016 10:37
@petrochenkov
Copy link
Contributor

single NameResolution-valued map in place the existing maps children and import_resolutions

🎉

fixes #31403 and fixes #31403

The issue numbers are the same.

I'll read this today.

@jseyfried
Copy link
Contributor Author

The issue numbers are the same.

The second one was supposed to be #31404, edited.

I'll read this today.

Awesome, I look forward to any feedback.

@petrochenkov
Copy link
Contributor

Ok, I give up, too many things are happening here at the same time.
I'm happy with the direction of unifying use items with other items, but can't follow many concrete changes, especially that I'm not very familiar with the import resolution code.

By the way, how much of the code treating imports and extern crates specially is caused only by error message compatibility?

// Define the name or return the existing binding if there is a collision.
fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> {
let old_binding = match self.binding {
Some(_) if binding.defined_with(DefModifiers::SHADOWABLE) => return Ok(()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if we try to define a shadowable binding (1) conflicting with another existing shadowable binding (2), then (2) wins or the conflict is reported somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, binding (2) would win (since the first match arm would be taken) and the conflict would not be reported (it would also not be reported in the original code). This isn't a problem since the only SHADOWABLE bindings are from the special prelude import, so there can't be conflicts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I should rename SHADOWABLE to PRELUDE.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I should rename SHADOWABLE to PRELUDE.

That would be much clearer, because prelude and shadowable glob imports would behave differently (I suppose).
The resolution result depending on the resolution order is still pretty bad, even if the concern is theoretical at the moment due to absence of user-defined preludes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I'll make it an error to have duplicate SHADOWABLE / PRELUDE imports.

@jseyfried
Copy link
Contributor Author

too many things are happening here at the same time

I'll split the first commit into more smaller commits.

how much of the code treating imports and extern crates specially is caused only by error message compatibility?

The special treatment in report_conflicts is for error message compatibility and the special treatment in record_use is for compatibility with the unused extern crate tracking system (which itself needs some refactoring; it tracks extern crates themselves, and not extern crate items so that if the same extern crate is declarated twice in different modules and only one declaration is used, the unused declaration will not be reported).
Apart from that, the special treatment is a reflection of semantics.

@jseyfried jseyfried force-pushed the remove_import_resolutions branch from eb1a9b6 to fe6ecd7 Compare February 8, 2016 01:11
@jseyfried
Copy link
Contributor Author

I addressed @gereeter's and @petrochenkov's comments and rewrote history to make the biggest commit a little cleaner and easier to review.

@jseyfried jseyfried force-pushed the remove_import_resolutions branch 2 times, most recently from 85afd8e to a847317 Compare February 8, 2016 02:13
@jseyfried jseyfried force-pushed the remove_import_resolutions branch from a847317 to 3c62d90 Compare February 8, 2016 02:25
@petrochenkov
Copy link
Contributor

Reviewed everything except for jseyfried@7000e70

@jseyfried jseyfried force-pushed the remove_import_resolutions branch from 69635f0 to 3c62d90 Compare February 9, 2016 04:07
…sts)

Derive the Default impl for NameResolution
@jseyfried jseyfried force-pushed the remove_import_resolutions branch from 1e71fc0 to 3df40c0 Compare February 9, 2016 17:33
@nrc
Copy link
Member

nrc commented Feb 11, 2016

@bors: r+

@bors
Copy link
Contributor

bors commented Feb 11, 2016

📌 Commit 3df40c0 has been approved by nrc

@bors
Copy link
Contributor

bors commented Feb 11, 2016

⌛ Testing commit 3df40c0 with merge 1de70d3...

bors added a commit that referenced this pull request Feb 11, 2016
This PR adds to `NameBinding` so it can more fully represent bindings from imports as well from items, refactors away `Target`, generalizes `ImportResolution` to a simpler type `NameResolution`, and uses a single `NameResolution`-valued map in place the existing maps `children` and `import_resolutions` (of `NameBinding`s and `ImportResolution`s, respectively), simplifying duplicate checking and name resolution.

It also unifies the `resolve_name_in_module` in `lib.rs` with its namesake in `resolve_imports.rs`, clarifying and improving the core logic (fixes #31403 and fixes #31404) while maintaining clear future-comparability with shadowable globs (i.e., never reporting that a resolution is a `Success` or is `Failing` unless this would also be knowable with shadowable globs).

Since it fixes #31403, this is technically a [breaking-change], but it is exceedingly unlikely to cause breakage in practice. The following is an example of code that would break:
```rust
mod foo {
    pub mod bar {} // This defines bar in the type namespace
    pub use alpha::bar; // This defines bar in the value namespace

    // This should define baz in both namespaces, but it only defines baz in the type namespace.
    pub use self::bar as baz;
    pub fn baz() {} // This should collide with baz, but now it does not.
}

pub fn f() {}
mod alpha {
    pub use self::f as bar; // Changing this to `pub fn bar() {}` causes the collision right now.
    pub use super::*;
}
```

r? @nrc
@jseyfried
Copy link
Contributor Author

@nrc Thanks!

@bors bors merged commit 3df40c0 into rust-lang:master Feb 11, 2016
jseyfried added a commit to jseyfried/rust that referenced this pull request Feb 11, 2016
bors added a commit that referenced this pull request Feb 15, 2016
This fixes a regression caused by #31461 allowing extern crates to be glob imported, and it fixes the test that was supposed to catch it.
r? @nrc
bors added a commit that referenced this pull request Feb 20, 2016
Now that #31461 is merged, a failing resolution can never become indeterminate or succeed, so we no longer have to keep trying to resolve failing import directives.
r? @nrc
@jseyfried jseyfried deleted the remove_import_resolutions branch March 25, 2016 22:54
@jseyfried jseyfried changed the title Resolve: refactor away Module::import_resolutions and improve import resolution resolve: improve import resolution Feb 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants