-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Bug #21221: Show candidates for names not in scope #31674
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Aatch (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
@@ -91,7 +91,7 @@ fn parse_expected(last_nonfollow_error: Option<usize>, | |||
(which, line) | |||
}; | |||
|
|||
debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg); | |||
println!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably stay debug!(...);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, sorry, will fix in a moment.
5155347
to
5870906
Compare
The previous commit failed to build after the rebase on the latest |
suggestion_str.push_str(&path_strings[0]); | ||
suggestion_str.push_str("`, which you need to import with the `use` keyword."); | ||
suggestion_vec.push(suggestion_str); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to else if !paths.is_empty()
to remove the empty if-block above
@oli-obk Thank you for the suggestions! I will push an update asap. |
5870906
to
5f1b4a4
Compare
☔ The latest upstream changes (presumably #31685) made this pull request unmergeable. Please resolve the merge conflicts. |
5f1b4a4
to
686814b
Compare
Thanks Bors, nice helpful robot :) |
cc @jseyfried @petrochenkov, resident resolve experts :) |
} | ||
} | ||
} | ||
|
||
pub fn def_id(&self) -> DefId { | ||
self.def_id_opt().expect(&format!("attempted .def_id() on invalid def: {:?}", self)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: put these on two separate lines (lining up the .
) -- seems a bit long for one line to me
OK, did a read through and left some notes -- this looks pretty good to me, actually. I like the suggestion infrastructure, I wonder if there are other places it could profitably be employed. I left some nits and some larger comments. |
@jseyfried, can you please have a look at the conditions now? I will address merging the |
@nikomatsakis, the commit messages should be much shorter now: VladUreche@ddeb147#diff-aeb0880081a991f34aef2ab889e1fb7aL3735 |
// declared as public | ||
lookup_results_everything.push(path.clone()); | ||
if !in_module_is_extern || | ||
name_binding.is_public() && in_module_is_accessible { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be just !in_module_is_extern || name_binding.is_public()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, since we prune the search by not adding to the worklist
. Good point!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After making the changes, I realized why I did not go with pruning:
session.fileline_help(
span,
&format!("there are {} other candidates that are not \
accessible.", not_accessible_count),
);
When pruning the search, we do not count all inaccessible definitions with the given name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now we are collecting all crate local items in lookup_results_accessible
, so lookup_results_everything
has all the paths that lookup_results_accessible
has except for inaccessible external items. I don't think we should report inaccessible external items under any circumstances, so there's no need for the two lists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want two lists, I think lookup_results_accessible
should have all accessible items and lookup_results_everything
should also have inaccessible items from the current crate. In that case, you'd need that ancestor checking method to distinguish between inaccessible and accessible items in the current crate. I don't think it's worth it to implement this distinction.
@jseyfried, the last commit merges the two data structures for storing candidates.
Otherwise, once you had a look at the code, I can squash the commits again. |
I think we should always report all items in the current crate and all accessible items in external crates and we should never report inaccessible items from external crates. |
Also, feel free to squash whenever |
Thanks! I removed the inaccessible definitions list and re-enabled the pruning. I'll have the new commit ready in a few minutes. |
e180806
to
2c613a5
Compare
/// mod bar { trait T {}; }; | ||
/// // make private T accessible through an import: | ||
/// pub use bar::T as T; | ||
/// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple things:
- To
pub use
something, it has to bepub
, so this example would be an error unlesstrait T
waspub
. - Since we don't care about accessibility in the current crate, we would report
foo::bar::T
, right? name_binding.is_import()
is can only be true for bindings in the current crate since our crate metadata does not distinguish between public imports and public items. If this code were in an external crate, we would reportfoo::T
as desired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That simplifies things a lot. I was under the impression that you can "reveal" private parts of a crate through pub use
statements. If imports are only visible on the current crate, we're perfectly fine ignoring them 👍
Thanks a lot for explaining this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To answer the 2nd bullet point, yes, we would report foo::bar::T
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I probably should have mentioned this earlier :)
pub use
statements actually can "reveal" private parts of a crate, for example
mod foo { pub trait T {} }
pub use foo::T; // FYI, we wouldn't be able to do this if `trait T` were not `pub`
Here, T
would not be accessible to other traits if we didn't pub use foo::T
.
What I mean by not distinguishing between public imports and public items is that when we load this external crate, both binding
s for T
will be !binding.is_import()
-- that is, we "forget" if bindings came from items or from imports. In other words, we wouldn't be able to distinguish the above external crate from
mod foo { pub use T; }
pub trait T;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which, if I'm interpreting well, means we should report external_crate::T
as a valid suggestion. Let me add this as a test case 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, good idea
2c613a5
to
8489600
Compare
@jseyfried, thanks for the latest round of feedback. I removed |
Alright, this look good to me -- thanks @VladUreche! @nikomatsakis We decided to report all items from the current crate (ignoring re-exports) and all accessible items from external crates. |
This commit adds functionality that allows the name resolution pass to search for entities (traits/types/enums/structs) by name, in order to show recommendations along with the errors. For now, only E0405 and E0412 have suggestions attached, as per the request in bug rust-lang#21221, but it's likely other errors can also benefit from the ability to generate suggestions.
8489600
to
88af8fa
Compare
The last commit adds a test case which checks the re-exports from outside crates. Just for the record, there are five possible extensions I'm aware of:
|
@bors r+ |
📌 Commit 88af8fa has been approved by |
@VladUreche thanks for sticking with it :) |
⌛ Testing commit 88af8fa with merge cfabd17... |
This commit adds functionality that allows the name resolution pass to search for entities (traits/types/enums/structs) by name, in order to show recommendations along with the errors. For now, only E0405 and E0412 have suggestions attached, as per the request in bug #21221, but it's likely other errors can also benefit from the ability to generate suggestions.
This commit adds functionality that allows the name resolution pass
to search for entities (traits/types/enums/structs) by name, in
order to show recommendations along with the errors.
For now, only E0405 and E0412 have suggestions attached, as per the
request in bug #21221, but it's likely other errors can also benefit
from the ability to generate suggestions.