Skip to content

Commit

Permalink
Tweak output of import suggestions
Browse files Browse the repository at this point in the history
When both `std::` and `core::` items are available, only suggest the
`std::` ones. We ensure that in `no_std` crates we suggest `core::`
items.

Ensure that the list of items suggested to be imported are always in the
order of local crate items, `std`/`core` items and finally foreign crate
items.

Tweak wording of import suggestion: if there are multiple items but they
are all of the same kind, we use the kind name and not the generic "items".

Fix #83564.
  • Loading branch information
estebank committed Jun 13, 2024
1 parent f158600 commit c88548b
Show file tree
Hide file tree
Showing 30 changed files with 159 additions and 89 deletions.
55 changes: 39 additions & 16 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2783,33 +2783,56 @@ fn show_candidates(
// by iterating through a hash map, so make sure they are ordered:
for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
path_strings.sort_by(|a, b| a.0.cmp(&b.0));
path_strings.dedup_by(|a, b| a.0 == b.0);
let core_path_strings =
path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
path_strings.extend(core_path_strings);
path_strings.dedup_by(|a, b| a.0 == b.0);
let std_path_strings =
path_strings.extract_if(|p| p.0.starts_with("std::")).collect::<Vec<_>>();
let foreign_crate_path_strings =
path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::<Vec<_>>();

// We list the `crate` local paths first.
// Then we list the `std`/`core` paths.
if std_path_strings.len() == core_path_strings.len() {
// Do not list `core::` paths if we are already listing the `std::` ones.
path_strings.extend(std_path_strings);
} else {
path_strings.extend(std_path_strings);
path_strings.extend(core_path_strings);
}
// List all paths from foreign crates last.
path_strings.extend(foreign_crate_path_strings);
}
accessible_path_strings.sort();

if !accessible_path_strings.is_empty() {
let (determiner, kind, name, through) =
if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
(
"this",
*descr,
format!(" `{name}`"),
if *via_import { " through its public re-export" } else { "" },
)
} else {
("one of these", "items", String::new(), "")
};
let (determiner, kind, s, name, through) = if let [(name, descr, _, _, via_import)] =
&accessible_path_strings[..]
{
(
"this",
*descr,
"",
format!(" `{name}`"),
if *via_import { " through its public re-export" } else { "" },
)
} else {
let descr_set: FxHashSet<&str> =
accessible_path_strings.iter().map(|(_, descr, _, _, _)| *descr).collect();
let items =
if descr_set.len() == 1 { descr_set.into_iter().next().unwrap() } else { "item" };
let s = if items.ends_with('s') { "es" } else { "s" };

("one of these", items, s, String::new(), "")
};

let instead = if let Instead::Yes = instead { " instead" } else { "" };
let mut msg = if let DiagMode::Pattern = mode {
format!(
"if you meant to match on {kind}{instead}{name}, use the full path in the pattern",
"if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
pattern",
)
} else {
format!("consider importing {determiner} {kind}{through}{instead}")
format!("consider importing {determiner} {kind}{s}{through}{instead}")
};

for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
Expand Down
4 changes: 1 addition & 3 deletions src/tools/clippy/tests/ui/crashes/ice-6252.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ error[E0412]: cannot find type `PhantomData` in this scope
LL | _n: PhantomData,
| ^^^^^^^^^^^ not found in this scope
|
help: consider importing one of these items
|
LL + use core::marker::PhantomData;
help: consider importing this struct
|
LL + use std::marker::PhantomData;
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/const-generics/issues/issue-82956.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter`
LL | let mut iter = IntoIter::new(self);
| ^^^^^^^^ use of undeclared type `IntoIter`
|
help: consider importing one of these items
help: consider importing one of these structs
|
LL + use std::array::IntoIter;
|
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/consts/const_refs_to_static-ice-121413.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
// ignore-tidy-linelength
#![feature(const_refs_to_static)]
const REF_INTERIOR_MUT: &usize = {
//~^ HELP consider importing this struct
static FOO: Sync = AtomicUsize::new(0);
//~^ ERROR failed to resolve: use of undeclared type `AtomicUsize`
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//~| HELP if this is an object-safe trait, use `dyn`
//~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
//~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
unsafe { &*(&FOO as *const _ as *const usize) }
};
pub fn main() {}
8 changes: 4 additions & 4 deletions tests/ui/consts/const_refs_to_static-ice-121413.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0433]: failed to resolve: use of undeclared type `AtomicUsize`
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
--> $DIR/const_refs_to_static-ice-121413.rs:9:24
|
LL | static FOO: Sync = AtomicUsize::new(0);
| ^^^^^^^^^^^ use of undeclared type `AtomicUsize`
Expand All @@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize;
|

warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
--> $DIR/const_refs_to_static-ice-121413.rs:9:17
|
LL | static FOO: Sync = AtomicUsize::new(0);
| ^^^^
Expand All @@ -24,15 +24,15 @@ LL | static FOO: dyn Sync = AtomicUsize::new(0);
| +++

error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
--> $DIR/const_refs_to_static-ice-121413.rs:9:17
|
LL | static FOO: Sync = AtomicUsize::new(0);
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`

error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
--> $DIR/const_refs_to_static-ice-121413.rs:9:24
|
LL | static FOO: Sync = AtomicUsize::new(0);
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ error[E0425]: cannot find value `Set` in this scope
LL | fn setup() -> Set { Set }
| ^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these unit variants
|
LL + use AffixHeart::Set;
|
Expand Down
7 changes: 2 additions & 5 deletions tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ LL | fn f() { my_core::mem::drop(0); }
LL | a!();
| ---- in this macro invocation
|
= help: consider importing one of these items:
core::mem
= help: consider importing this module:
std::mem
= note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)

Expand All @@ -35,9 +34,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
LL | fn f() { my_core::mem::drop(0); }
| ^^^^^^^ use of undeclared crate or module `my_core`
|
help: consider importing one of these items
|
LL + use core::mem;
help: consider importing this module
|
LL + use std::mem;
|
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/imports/cycle-import-in-std-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
LL | use ops::{self as std};
| ^^^^^^^^^^^ no external crate `ops`
|
= help: consider importing one of these items instead:
core::ops
= help: consider importing this module instead:
std::ops

error: aborting due to 1 previous error
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/imports/cycle-import-in-std-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
LL | use ops::{self as std};
| ^^^^^^^^^^^ no external crate `ops`
|
= help: consider importing one of these items instead:
core::ops
= help: consider importing this module instead:
std::ops

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
LL | let _: Foo<i32> = todo!();
| ^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these structs
|
LL + use crate::nice_crate_name::Foo;
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
LL | let _: Foo<i32> = todo!();
| ^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these structs
|
LL + use crate::nice_crate_name::Foo;
|
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/imports/issue-56125.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ error[E0432]: unresolved import `empty::issue_56125`
LL | use empty::issue_56125;
| ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
|
help: consider importing one of these items instead
help: consider importing one of these modules instead
|
LL | use crate::m3::last_segment::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | use crate::m3::non_last_segment::non_last_segment::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | use ::issue_56125::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | use ::issue_56125::last_segment::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | use ::issue_56125::non_last_segment::non_last_segment::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | use crate::m3::last_segment::issue_56125;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
and 1 other candidate

error[E0659]: `issue_56125` is ambiguous
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lint/use_suggestion_json.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ mod foo {
],
"children": [
{
"message": "consider importing one of these items",
"message": "consider importing one of these structs",
"code": null,
"level": "help",
"spans": [
Expand Down Expand Up @@ -386,7 +386,7 @@ mod foo {
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let x: Iter;\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m
\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these structs\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::binary_heap::Iter;\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/namespace/namespace-mix.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ help: a tuple struct with a similar name exists
|
LL | check(m1::TS);
| ~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use m2::S;
|
Expand Down Expand Up @@ -40,7 +40,7 @@ help: a tuple struct with a similar name exists
|
LL | check(xm1::TS);
| ~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use m2::S;
|
Expand All @@ -66,7 +66,7 @@ help: a tuple variant with a similar name exists
|
LL | check(m7::TV);
| ~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use m8::V;
|
Expand Down Expand Up @@ -94,7 +94,7 @@ help: a tuple variant with a similar name exists
|
LL | check(xm7::TV);
| ~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use m8::V;
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/resolve/issue-16058.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
LL | Result {
| ^^^^^^ not a struct, variant or union type
|
help: consider importing one of these items instead
help: consider importing one of these type aliases instead
|
LL + use std::fmt::Result;
|
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/resolve/issue-21221-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ error[E0405]: cannot find trait `Mul` in this scope
LL | impl Mul for Foo {
| ^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these traits
|
LL + use std::ops::Mul;
|
LL + use mul1::Mul;
|
LL + use mul2::Mul;
|
LL + use std::ops::Mul;
|

error[E0412]: cannot find type `Mul` in this scope
--> $DIR/issue-21221-1.rs:58:16
|
LL | fn getMul() -> Mul {
| ^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these traits
|
LL + use std::ops::Mul;
|
LL + use mul1::Mul;
|
LL + use mul2::Mul;
|
LL + use std::ops::Mul;
|

error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
--> $DIR/issue-21221-1.rs:63:6
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/resolve/issue-21221-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope
LL | impl T for Foo { }
| ^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these traits
|
LL + use baz::T;
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/resolve/issue-50599.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64`
LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
| ^^^^^^^ not found in `std::f64`
|
help: consider importing one of these items
help: consider importing one of these constants
|
LL + use std::f128::consts::LOG10_2;
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/resolve/issue-73427.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ help: the following enum variant is available
|
LL | (E::TupleWithFields(/* fields */)).foo();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use std::f128::consts::E;
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/resolve/privacy-enum-ctor.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ help: a function with a similar name exists
|
LL | let _: E = m::f;
| ~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use std::f128::consts::E;
|
Expand Down Expand Up @@ -123,7 +123,7 @@ help: alternatively, the following enum variant is available
|
LL | let _: E = (E::Fn(/* fields */));
| ~~~~~~~~~~~~~~~~~~~~~
help: consider importing one of these items instead
help: consider importing one of these constants instead
|
LL + use std::f128::consts::E;
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ error[E0432]: unresolved import `alloc`
LL | use alloc;
| ^^^^^ no external crate `alloc`
|
help: consider importing one of these items instead
help: consider importing this module instead
|
LL | use core::alloc;
| ~~~~~~~~~~~
LL | use std::alloc;
| ~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/rust-2018/issue-52202-use-suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope
LL | let _d = Drain {};
| ^^^^^ not found in this scope
|
help: consider importing one of these items
help: consider importing one of these structs
|
LL + use crate::plumbing::Drain;
|
Expand Down
Loading

0 comments on commit c88548b

Please sign in to comment.