Suggest case insensitive import suggestions - #156239
Conversation
36cee45 to
a23f444
Compare
|
I see from the 247 failed tests that 1-edit difference is too big for small names. 'net' should probably NOT be suggested to replace 'new'... Edit: i have now switched to case insensitive match only. |
This comment has been minimized.
This comment has been minimized.
fdc8fcc to
2893b67
Compare
|
r? @TaKO8Ki rustbot has assigned @TaKO8Ki. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
|
upstream change #157991 contains commit cd2d10a and 4f6a600 from #157974 which do some weird file swapping instead of renamings that completely confuses and breaks my rebase attempts. If this is not a skill issue on my part, maybe avoiding this kind of file swapping and splitting this in multiple rename commits would help git not getting confused ? |
1bcb37c to
981c290
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
65853f4 to
1fdd975
Compare
|
For anyone having trouble with the file swap, my cleanest solution is:
# make patches out of my commits
git format-patch HEAD~7..HEAD
# edit the patch files to change the file path
sed -i 's|a/compiler/rustc_resolve/src/diagnostics.rs|a/compiler/rustc_resolve/src/error_helper.rs|g; s|b/compiler/rustc_resolve/src/diagnostics.rs|b/compiler/rustc
_resolve/src/error_helper.rs|g' *.patch
# create new 'fix-swapped-files' branch from upstream latest
git checkout -b fix-swapped-files <upstream>/main
# apply updated patches
git am --committer-date-is-author-date *.patch |
1fdd975 to
9f894a0
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@rustbot reroll |
There was a problem hiding this comment.
During this PR, I ended up adding two other things which could arguably be two separate PRs
I think it would be good to extract them as separate PRs. Let's keep this PR only related to case-insensitive import suggestions.
And, please squash the commits to three commits, which would be helpful to review:
- Adding tests and make a snapshot of current compiler behavior
- The new implementation
- Bless tests
@rustbot author
|
Reminder, once the PR becomes ready for a review, use |
9f894a0 to
6122965
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
stdlib case insensitive tests Co-authored-by: Chris Simpkins <git.simpkins@gmail.com> additional insensitive import test
adds a is_exact_match field to ImportSuggestion use is_exact_match field to customize help message suggest imports with different casing only suggest modules if the following segment matches something in scope of the suggestion rebase: fix compilation error after rebase fix: use error code const directly
6122965 to
c051a58
Compare
Done, I extracted them as #161180 and #161182
Done :) @rustbot ready |
| fn shutdown_not_in_scope()->Shutdown{ //~ ERROR | ||
| unimplemented!() | ||
| } | ||
| fn both_not_in_scope_and_capitalization()->both{ //~ ERROR | ||
| unimplemented!() | ||
| } | ||
| fn shutdown_both_not_in_scope_and_capitalization()->shutdown{ //~ ERROR | ||
| both //~ ERROR | ||
| } | ||
| fn both_missing_std()->std::net::Shutdown{ | ||
| net::shutdown::Both //~ ERROR | ||
| } | ||
| fn shutdown_capitalization()->std::net::Shutdown{ | ||
| std::net::shutdown::Both //~ ERROR | ||
| } | ||
| fn shutdown_and_both_missing_capitalization()->std::net::Shutdown{ | ||
| std::net::shutdown::both //~ ERROR | ||
| } |
There was a problem hiding this comment.
I think these could be moved into the part of std::net in file tests/ui/imports/case-insensitive/libstd.rs.
| help: consider importing this module | ||
| | | ||
| LL + use crate::bar; | ||
| | | ||
|
|
There was a problem hiding this comment.
And this suggestion
| help: consider importing this module | ||
| | | ||
| LL + use foo; | ||
| | |
There was a problem hiding this comment.
Also this suggestion
| help: consider importing this module | ||
| | | ||
| LL + use crate::foo; | ||
| | |
There was a problem hiding this comment.
Are this suggestion expected?
| } | ||
|
|
||
| type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool); | ||
| type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool, bool); |
There was a problem hiding this comment.
Could you convert this tuple to a struct with named fields? Because it has six fields for now.
There was a problem hiding this comment.
Could you add tests like let _ = Hashmap::new();?
We have suggested the following:
error[E0433]: cannot find type `HashMap` in this scope
--> src/main.rs:2:13
|
2 | let x = HashMap::new();
| ^^^^^^^ use of undeclared type `HashMap`
|
help: consider importing this struct
|
1 + use std::collections::HashMap;
|
Although I think it is not easy to support this.
| if let Some(E0425) = err.code | ||
| && candidates.is_empty() | ||
| && no_suggestion | ||
| { |
There was a problem hiding this comment.
I'm afraid this is not enough. Because the code of err may be changed to the parent err's code. And other suggestions may also be added later. And this is why we emit some (unexpected) suggestions in tests/ui/resolve/export-fully-qualified.rs and tests/ui/suggestions/crate-or-module-typo.rs.
So I think a better way is to share most logic between the two branches in try_lookup_name_relaxed, like what I commented. And we could return an additional candidates_case_insensitive in this function.
And finnaly, we could use candidates_case_insensitive only if candidates is empty and the final err.code is Some(E0425) when constructing UseError in fn smart_resolve_path_fragment.
| let is_expected = &|res| { | ||
| if case_sensitive { | ||
| source.is_expected(res) | ||
| } else { | ||
| if following_seg.is_none() { | ||
| source.is_expected(res) | ||
| } else { | ||
| matches!(res, Res::Def(DefKind::Mod, _)) //fixme(GTimothy):check that this is | ||
| // necessary/correct | ||
| } | ||
| } | ||
| }; |
There was a problem hiding this comment.
Keep let is_expected = &|res| source.is_expected(res); here.
| if !case_sensitive { | ||
| // If there's a following segment, only keep modules that contain it | ||
| if let Some(following) = following_seg { | ||
| let Some(did) = did else { return false }; | ||
| let Some(module) = self.r.get_module(*did) else { return false }; | ||
| let mut found = false; | ||
| module.for_each_child(self.r, |_, ident, _, _, _| { | ||
| if ident.name == following.ident.name { | ||
| found = true; | ||
| } | ||
| }); | ||
| if !found { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| // Filter out items that are in the prelude | ||
| if let Some(prelude) = self.r.prelude { | ||
| if let Some(suggestion_did) = did { | ||
| let mut is_in_prelude = false; | ||
| prelude.for_each_child(self.r, |_, _, _, _, decl| { | ||
| if decl.res().opt_def_id() == Some(*suggestion_did) { | ||
| is_in_prelude = true; | ||
| } | ||
| }); | ||
| if is_in_prelude { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
This is also unnecessary.
| if !case_sensitive { | ||
| return (false, suggested_candidates, candidates); | ||
| } |
There was a problem hiding this comment.
This is also unneeded.
View all comments
Fixes #72641
This PR proposes case insensitive import suggestions.
Previous discussion of this topic here: #72641 and in this PR: #72988
If that is still of interest, a discussion may be needed to limit or expand the included list.
I initially followed the suggestions in #72988.
The tests are based on the tests by @chrissimpkins in #72988.
I added a
is_exact_matchfield toImportSuggestionto modify the suggestion text accordingly.Only when no other suggestion is made, do I check for case insensitive import suggestion.
for a more complex case:
SystemTimeexists in the stdlib, but I only suggest case insensitive import when nothing else is suggestedDuring this PR, I ended up adding two other things which could arguably be two separate PRs:
filtering out typos suggestions that do not have parameters when the typo has some
motivation: It suggested Clone (no parameter) for the std
cloned<(),()>test when I expectedCloned<(),()>to be suggested.when suggesting that a missing binding is available in a pattern but not used because behind a
.., suggest a MaybeIncorrect fix.motivation: this way, I can avoid looking for imports if there is a suggestion.
custom import message for case insensitive suggestion.
only suggest case insensitive when no other suggestion is made
check for enum variant match before suggesting an enum
check for enum variant parameter requirement before suggesting an enum
check with reviewers where to place the test, and whether to rename them
separate PRs for:
Let's keep this PR only related to case-insensitive import suggestions.
squash the commits to three commits, easier to review