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: mark it undetermined if single import is not has any bindings #124840

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bvanjoi
Copy link
Contributor

@bvanjoi bvanjoi commented May 7, 2024

This issue arises from incorrect resolution updates, for example:

mod a {
    pub mod b {
        pub mod c {}
    }
}

use a::*;

use b::c;
use c as b;

fn main() {}
  1. In the first loop, binding (root, b) is refer to root::a::b due to use a::*.
    1. However, binding (root, c) isn't defined by use b::c during this stage because use c as b falls under the single_imports of (root, b), where the imported_module hasn't been computed yet. This results in marking the path_res for b as Indeterminate.
    2. Then, the imported_module for use c as b will be recorded.
  2. In the second loop, use b::c will be processed again:
    1. Firstly, it attempts to find the path_res for (root, b).
    2. It will iterate through the single_imports of use b::c, encounter use c as b, attempt to resolve c in root, and ultimately return Err(Undetermined), thus passing the iterator.
    3. Use the binding (root, b) -> root::a::b introduced by use a::* and ultimately return root::a::b as the path_res of b.
    4. Then define the binding (root, c) -> root::a::b::c.
  3. Then process use c as b, update the resolution for (root, b) to refer to root::a::b::c, ultimately causing inconsistency.

In my view, step 2.2 has an issue where it should exit early, similar to the behavior when there's no imported_module. Therefore, I've added an attribute called indeterminate to ImportData. This will help us handle only those single imports that have at least one determined binding.

r? @petrochenkov

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 7, 2024
@rust-log-analyzer

This comment has been minimized.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 7, 2024

#124840 (comment)

CI failed, so mark it as a draft.

reduced:

mod a {
    pub(crate) use crate::S;
}
mod b {
    pub struct S;
}
use b::*;
use self::a::S;

fn main() {}

@bvanjoi bvanjoi marked this pull request as draft May 7, 2024 11:08
@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 7, 2024

Update: I've changed that it now only returns Undetermined when resolving modules.

I'm not sure if there's a better solution or potential edge cases. Regardless, since CI is passing, mark it as ready for review.

@bvanjoi bvanjoi marked this pull request as ready for review May 7, 2024 15:09
@bvanjoi bvanjoi force-pushed the fix-124490 branch 2 times, most recently from 5bdd09b to ebc10a4 Compare May 16, 2024 02:33
@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 24, 2024
@petrochenkov
Copy link
Contributor

  1. It will iterate through the single_imports of use b::c, encounter use c as b, attempt to resolve c in root, and ultimately return Err(Undetermined), thus passing the iterator.

I don't understand, both Err(Undetermined) and the new case introduced in this PR result in

return Err((Undetermined, Weak::No))

and neither of them is "passing the iterator" (if I understand it correctly).

Does resolve_ident_in_module(...) returns Err(Determined) or Ok(binding) maybe, even if single_import.indeterminate is true?
It's not clear to me how this can happen.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 25, 2024

Does resolve_ident_in_module(...) returns Err(Determined)

Yep, it will return Err(Determined) for resolve_ident_in_module(c, root). It might be a typo..

@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 25, 2024

@rustbot ready

@petrochenkov petrochenkov added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 25, 2024
@petrochenkov
Copy link
Contributor

The PR is now looking nice after the cleanup, but I still don't understand why it works :D

Why is "all bindings undetermined" able to correctly reject something that resolve_ident_in_module is not?
I would expect resolve_ident_in_module to return Undetermined without this additional intervention, that feels pretty arbitrary (especially with the module().is_some() condition).
@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 28, 2024
@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 29, 2024

The reason why resolve_ident_in_module(c, root) returns Err(Determined) is because it skips the iteration of single_imports. More specifically, the single_import.vis value is None because it was already taken at the entry point. This results in hitting a continue.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 29, 2024

Also, I tried moving the single_import.imported_module.get() condition before single_import.vis.get(), but ./x.py build failed to compile. Therefore, I've decided not to solve this problem in this manner. :E

@petrochenkov petrochenkov added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 29, 2024
@petrochenkov
Copy link
Contributor

I suspect that resolver may be stuck on some valid code after this change, let's check.
@bors try

@petrochenkov petrochenkov removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 29, 2024
@petrochenkov petrochenkov added the S-waiting-on-crater Status: Waiting on a crater run to be completed. label May 29, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request May 29, 2024
resolve: mark it undetermined if single import is not has any bindings

- Fixes rust-lang#124490
- Fixes rust-lang#125013

This issue arises from incorrect resolution updates, for example:

```rust
mod a {
    pub mod b {
        pub mod c {}
    }
}

use a::*;

use b::c;
use c as b;

fn main() {}
```

1. In the first loop, binding `(root, b)` is refer to `root::a::b` due to `use a::*`.
    1. However, binding `(root, c)` isn't defined by `use b::c` during this stage because `use c as b` falls under the `single_imports` of `(root, b)`, where the `imported_module` hasn't been computed yet. This results in marking the `path_res` for `b` as `Indeterminate`.
    2. Then, the `imported_module` for `use c as b` will be recorded.
2. In the second loop, `use b::c` will be processed again:
    1. Firstly, it attempts to find the `path_res` for `(root, b)`.
    2. It will iterate through the `single_imports` of `use b::c`, encounter `use c as b`, attempt to resolve `c` in `root`, and ultimately return `Err(Undetermined)`, thus passing the iterator.
    3. Use the binding `(root, b)` -> `root::a::b` introduced by `use a::*` and ultimately return `root::a::b` as the `path_res` of `b`.
    4. Then define the binding `(root, c)` -> `root::a::b::c`.
3. Then process `use c as b`, update the resolution for `(root, b)` to refer to `root::a::b::c`, ultimately causing inconsistency.

In my view, step `2.2` has an issue where it should exit early, similar to the behavior when there's no `imported_module`. Therefore, I've added an attribute called `indeterminate` to `ImportData`. This will help us handle only those single imports that have at least one determined binding.

r? `@petrochenkov`
@bors
Copy link
Contributor

bors commented May 29, 2024

⌛ Trying commit 8714888 with merge 6425815...

@bors
Copy link
Contributor

bors commented May 29, 2024

☀️ Try build successful - checks-actions
Build commit: 6425815 (6425815d3821b9c5b1e1629f8757064c759d052f)

@petrochenkov
Copy link
Contributor

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-124840 created and queued.
🤖 Automatically detected try build 6425815
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-crater Status: Waiting on a crater run to be completed. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE:assertion failed: import.imported_module.get().is_none() ICE: inconsistent resolution for an import
6 participants