Skip to content

Commit 9add632

Browse files
committed
Auto merge of #96353 - estebank:issue-95413, r=compiler-errors
When suggesting to import an item, also suggest changing the path if appropriate When we don't find an item we search all of them for an appropriate import and suggest `use`ing it. This is sometimes done for expressions that have paths with more than one segment. We now also suggest changing that path to work with the `use`. Fix #95413
2 parents 1b2e0b6 + 4934a9e commit 9add632

14 files changed

+132
-1
lines changed

compiler/rustc_resolve/src/diagnostics.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl<'a> Resolver<'a> {
117117
}
118118

119119
fn report_with_use_injections(&mut self, krate: &Crate) {
120-
for UseError { mut err, candidates, def_id, instead, suggestion } in
120+
for UseError { mut err, candidates, def_id, instead, suggestion, path } in
121121
self.use_injections.drain(..)
122122
{
123123
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
@@ -135,6 +135,7 @@ impl<'a> Resolver<'a> {
135135
if instead { Instead::Yes } else { Instead::No },
136136
found_use,
137137
IsPattern::No,
138+
path,
138139
);
139140
} else if let Some((span, msg, sugg, appl)) = suggestion {
140141
err.span_suggestion(span, msg, sugg, appl);
@@ -702,6 +703,7 @@ impl<'a> Resolver<'a> {
702703
Instead::No,
703704
FoundUse::Yes,
704705
IsPattern::Yes,
706+
vec![],
705707
);
706708
}
707709
err
@@ -1482,6 +1484,7 @@ impl<'a> Resolver<'a> {
14821484
Instead::No,
14831485
FoundUse::Yes,
14841486
IsPattern::No,
1487+
vec![],
14851488
);
14861489

14871490
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
@@ -2448,6 +2451,7 @@ fn show_candidates(
24482451
instead: Instead,
24492452
found_use: FoundUse,
24502453
is_pattern: IsPattern,
2454+
path: Vec<Segment>,
24512455
) {
24522456
if candidates.is_empty() {
24532457
return;
@@ -2515,6 +2519,14 @@ fn show_candidates(
25152519
accessible_path_strings.into_iter().map(|a| a.0),
25162520
Applicability::MaybeIncorrect,
25172521
);
2522+
if let [first, .., last] = &path[..] {
2523+
err.span_suggestion_verbose(
2524+
first.ident.span.until(last.ident.span),
2525+
&format!("if you import `{}`, refer to it directly", last.ident),
2526+
String::new(),
2527+
Applicability::Unspecified,
2528+
);
2529+
}
25182530
} else {
25192531
msg.push(':');
25202532

compiler/rustc_resolve/src/late.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2693,6 +2693,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
26932693
def_id,
26942694
instead,
26952695
suggestion,
2696+
path: path.into(),
26962697
});
26972698
}
26982699

@@ -2756,6 +2757,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
27562757
def_id,
27572758
instead: false,
27582759
suggestion: None,
2760+
path: path.into(),
27592761
});
27602762
} else {
27612763
err.cancel();

compiler/rustc_resolve/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,9 @@ struct UseError<'a> {
696696
instead: bool,
697697
/// Extra free-form suggestion.
698698
suggestion: Option<(Span, &'static str, String, Applicability)>,
699+
/// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling
700+
/// the user to import the item directly.
701+
path: Vec<Segment>,
699702
}
700703

701704
#[derive(Clone, Copy, PartialEq, Debug)]

src/test/ui/macros/macro-outer-attributes.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ help: consider importing this function
88
|
99
LL | use b::bar;
1010
|
11+
help: if you import `bar`, refer to it directly
12+
|
13+
LL - a::bar();
14+
LL + bar();
15+
|
1116

1217
error: aborting due to previous error
1318

src/test/ui/namespace/namespace-mix.stderr

+20
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ LL | use m2::S;
1818
|
1919
LL | use xm2::S;
2020
|
21+
help: if you import `S`, refer to it directly
22+
|
23+
LL - check(m1::S);
24+
LL + check(S);
25+
|
2126

2227
error[E0423]: expected value, found type alias `xm1::S`
2328
--> $DIR/namespace-mix.rs:40:11
@@ -41,6 +46,11 @@ LL | use m2::S;
4146
|
4247
LL | use xm2::S;
4348
|
49+
help: if you import `S`, refer to it directly
50+
|
51+
LL - check(xm1::S);
52+
LL + check(S);
53+
|
4454

4555
error[E0423]: expected value, found struct variant `m7::V`
4656
--> $DIR/namespace-mix.rs:100:11
@@ -67,6 +77,11 @@ LL | use m8::V;
6777
|
6878
LL | use xm8::V;
6979
|
80+
help: if you import `V`, refer to it directly
81+
|
82+
LL - check(m7::V);
83+
LL + check(V);
84+
|
7085

7186
error[E0423]: expected value, found struct variant `xm7::V`
7287
--> $DIR/namespace-mix.rs:106:11
@@ -95,6 +110,11 @@ LL | use m8::V;
95110
|
96111
LL | use xm8::V;
97112
|
113+
help: if you import `V`, refer to it directly
114+
|
115+
LL - check(xm7::V);
116+
LL + check(V);
117+
|
98118

99119
error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
100120
--> $DIR/namespace-mix.rs:33:11

src/test/ui/parser/circular_modules_main.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ help: consider importing this function
1414
|
1515
LL | use hi_str;
1616
|
17+
help: if you import `hi_str`, refer to it directly
18+
|
19+
LL - println!("{}", circular_modules_main::hi_str());
20+
LL + println!("{}", hi_str());
21+
|
1722

1823
error: aborting due to 2 previous errors
1924

src/test/ui/resolve/enums-are-namespaced-xc.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ help: consider importing this unit variant
88
|
99
LL | use namespaced_enums::Foo::A;
1010
|
11+
help: if you import `A`, refer to it directly
12+
|
13+
LL - let _ = namespaced_enums::A;
14+
LL + let _ = A;
15+
|
1116

1217
error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `namespaced_enums`
1318
--> $DIR/enums-are-namespaced-xc.rs:7:31
@@ -19,6 +24,11 @@ help: consider importing this tuple variant
1924
|
2025
LL | use namespaced_enums::Foo::B;
2126
|
27+
help: if you import `B`, refer to it directly
28+
|
29+
LL - let _ = namespaced_enums::B(10);
30+
LL + let _ = B(10);
31+
|
2232

2333
error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced_enums`
2434
--> $DIR/enums-are-namespaced-xc.rs:9:31
@@ -30,6 +40,11 @@ help: consider importing this variant
3040
|
3141
LL | use namespaced_enums::Foo::C;
3242
|
43+
help: if you import `C`, refer to it directly
44+
|
45+
LL - let _ = namespaced_enums::C { a: 10 };
46+
LL + let _ = C { a: 10 };
47+
|
3348

3449
error: aborting due to 3 previous errors
3550

src/test/ui/resolve/issue-50599.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ LL | use std::f32::consts::LOG10_2;
1010
|
1111
LL | use std::f64::consts::LOG10_2;
1212
|
13+
help: if you import `LOG10_2`, refer to it directly
14+
|
15+
LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
16+
LL + const M: usize = (f64::from(N) * LOG10_2) as usize;
17+
|
1318

1419
error: aborting due to previous error
1520

src/test/ui/resolve/missing-in-namespace.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ help: consider importing this struct
88
|
99
LL | use std::collections::HashMap;
1010
|
11+
help: if you import `HashMap`, refer to it directly
12+
|
13+
LL - let _map = std::hahmap::HashMap::new();
14+
LL + let _map = HashMap::new();
15+
|
1116

1217
error: aborting due to previous error
1318

src/test/ui/resolve/privacy-enum-ctor.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ LL | use std::f32::consts::E;
105105
|
106106
LL | use std::f64::consts::E;
107107
|
108+
help: if you import `E`, refer to it directly
109+
|
110+
LL - let _: E = m::E;
111+
LL + let _: E = E;
112+
|
108113

109114
error[E0423]: expected value, found struct variant `m::E::Struct`
110115
--> $DIR/privacy-enum-ctor.rs:45:16

src/test/ui/resolve/resolve-primitive-fallback.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ help: consider importing this builtin type
1414
|
1515
LL | use std::primitive::u8;
1616
|
17+
help: if you import `u8`, refer to it directly
18+
|
19+
LL - let _: ::u8;
20+
LL + let _: u8;
21+
|
1722

1823
error[E0061]: this function takes 0 arguments but 1 argument was supplied
1924
--> $DIR/resolve-primitive-fallback.rs:3:5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
#![allow(non_snake_case)]
3+
mod A {
4+
pub trait Trait {}
5+
impl Trait for i32 {}
6+
}
7+
8+
mod B {
9+
use A::Trait;
10+
11+
pub struct A<H: Trait>(pub H); //~ ERROR cannot find trait
12+
}
13+
14+
fn main() {
15+
let _ = B::A(42);
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-rustfix
2+
#![allow(non_snake_case)]
3+
mod A {
4+
pub trait Trait {}
5+
impl Trait for i32 {}
6+
}
7+
8+
mod B {
9+
pub struct A<H: A::Trait>(pub H); //~ ERROR cannot find trait
10+
}
11+
12+
fn main() {
13+
let _ = B::A(42);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0405]: cannot find trait `Trait` in `A`
2+
--> $DIR/shadowed-path-in-trait-bound-suggestion.rs:9:24
3+
|
4+
LL | pub struct A<H: A::Trait>(pub H);
5+
| ^^^^^ not found in `A`
6+
|
7+
help: consider importing this trait
8+
|
9+
LL | use A::Trait;
10+
|
11+
help: if you import `Trait`, refer to it directly
12+
|
13+
LL - pub struct A<H: A::Trait>(pub H);
14+
LL + pub struct A<H: Trait>(pub H);
15+
|
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0405`.

0 commit comments

Comments
 (0)