Skip to content

Commit 14c4391

Browse files
authored
Rollup merge of #71863 - mibac138:self-import, r=estebank
Suggest fixes and add error recovery for `use foo::self` Fixes #63741. I have implemented 2 suggestions on how to fix a `use foo::self` import, however I feel like showing them both might be too verbose. Additionally, I have also implemented error recovery as [menitoned](#63741 (comment)) by @comex. I believe r? @estebank deals with diagnostics.
2 parents 64ad709 + aaeea7f commit 14c4391

File tree

12 files changed

+186
-23
lines changed

12 files changed

+186
-23
lines changed

src/librustc_resolve/build_reduced_graph.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
426426
return;
427427
}
428428

429-
// Replace `use foo::self;` with `use foo;`
429+
// Replace `use foo::{ self };` with `use foo;`
430430
source = module_path.pop().unwrap();
431431
if rename.is_none() {
432432
ident = source.ident;
@@ -435,10 +435,33 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
435435
} else {
436436
// Disallow `self`
437437
if source.ident.name == kw::SelfLower {
438+
let parent = module_path.last();
439+
440+
let span = match parent {
441+
// only `::self` from `use foo::self as bar`
442+
Some(seg) => seg.ident.span.shrink_to_hi().to(source.ident.span),
443+
None => source.ident.span,
444+
};
445+
let span_with_rename = match rename {
446+
// only `self as bar` from `use foo::self as bar`
447+
Some(rename) => source.ident.span.to(rename.span),
448+
None => source.ident.span,
449+
};
438450
self.r.report_error(
439-
use_tree.span,
440-
ResolutionError::SelfImportsOnlyAllowedWithin,
451+
span,
452+
ResolutionError::SelfImportsOnlyAllowedWithin {
453+
root: parent.is_none(),
454+
span_with_rename,
455+
},
441456
);
457+
458+
// Error recovery: replace `use foo::self;` with `use foo;`
459+
if let Some(parent) = module_path.pop() {
460+
source = parent;
461+
if rename.is_none() {
462+
ident = source.ident;
463+
}
464+
}
442465
}
443466

444467
// Disallow `use $crate;`

src/librustc_resolve/diagnostics.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,40 @@ impl<'a> Resolver<'a> {
301301
}
302302
err
303303
}
304-
ResolutionError::SelfImportsOnlyAllowedWithin => struct_span_err!(
305-
self.session,
306-
span,
307-
E0429,
308-
"{}",
309-
"`self` imports are only allowed within a { } list"
310-
),
304+
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
305+
let mut err = struct_span_err!(
306+
self.session,
307+
span,
308+
E0429,
309+
"{}",
310+
"`self` imports are only allowed within a { } list"
311+
);
312+
313+
// None of the suggestions below would help with a case like `use self`.
314+
if !root {
315+
// use foo::bar::self -> foo::bar
316+
// use foo::bar::self as abc -> foo::bar as abc
317+
err.span_suggestion(
318+
span,
319+
"consider importing the module directly",
320+
"".to_string(),
321+
Applicability::MachineApplicable,
322+
);
323+
324+
// use foo::bar::self -> foo::bar::{self}
325+
// use foo::bar::self as abc -> foo::bar::{self as abc}
326+
let braces = vec![
327+
(span_with_rename.shrink_to_lo(), "{".to_string()),
328+
(span_with_rename.shrink_to_hi(), "}".to_string()),
329+
];
330+
err.multipart_suggestion(
331+
"alternatively, use the multi-path `use` syntax to import `self`",
332+
braces,
333+
Applicability::MachineApplicable,
334+
);
335+
}
336+
err
337+
}
311338
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
312339
let mut err = struct_span_err!(
313340
self.session,

src/librustc_resolve/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ enum ResolutionError<'a> {
194194
/// Error E0426: use of undeclared label.
195195
UndeclaredLabel(&'a str, Option<Symbol>),
196196
/// Error E0429: `self` imports are only allowed within a `{ }` list.
197-
SelfImportsOnlyAllowedWithin,
197+
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
198198
/// Error E0430: `self` import can only appear once in the list.
199199
SelfImportCanOnlyAppearOnceInTheList,
200200
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.

src/test/ui/error-codes/E0429.stderr

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
error[E0429]: `self` imports are only allowed within a { } list
2-
--> $DIR/E0429.rs:1:5
2+
--> $DIR/E0429.rs:1:13
33
|
44
LL | use std::fmt::self;
5-
| ^^^^^^^^^^^^^^
5+
| ^^^^^^
6+
|
7+
help: consider importing the module directly
8+
|
9+
LL | use std::fmt;
10+
| --
11+
help: alternatively, use the multi-path `use` syntax to import `self`
12+
|
13+
LL | use std::fmt::{self};
14+
| ^ ^
615

716
error: aborting due to previous error
817

src/test/ui/issues/issue-45829/import-self.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use foo::{self};
99
use foo as self;
1010
//~^ ERROR expected identifier
1111

12-
use foo::self;
12+
use foo::self; //~ ERROR is defined multiple times
1313
//~^ ERROR `self` imports are only allowed within a { } list
1414

1515
use foo::A;

src/test/ui/issues/issue-45829/import-self.stderr

+27-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@ LL | use foo as self;
55
| ^^^^ expected identifier, found keyword
66

77
error[E0429]: `self` imports are only allowed within a { } list
8-
--> $DIR/import-self.rs:12:5
8+
--> $DIR/import-self.rs:12:8
99
|
1010
LL | use foo::self;
11-
| ^^^^^^^^^
11+
| ^^^^^^
12+
|
13+
help: consider importing the module directly
14+
|
15+
LL | use foo;
16+
| --
17+
help: alternatively, use the multi-path `use` syntax to import `self`
18+
|
19+
LL | use foo::{self};
20+
| ^ ^
1221

1322
error[E0255]: the name `foo` is defined multiple times
1423
--> $DIR/import-self.rs:6:11
@@ -25,6 +34,21 @@ help: you can use `as` to change the binding name of the import
2534
LL | use foo::{self as other_foo};
2635
| ^^^^^^^^^^^^^^^^^
2736

37+
error[E0255]: the name `foo` is defined multiple times
38+
--> $DIR/import-self.rs:12:5
39+
|
40+
LL | mod foo {
41+
| ------- previous definition of the module `foo` here
42+
...
43+
LL | use foo::self;
44+
| ^^^^^^^^^ `foo` reimported here
45+
|
46+
= note: `foo` must be defined only once in the type namespace of this module
47+
help: you can use `as` to change the binding name of the import
48+
|
49+
LL | use foo as other_foo;
50+
| ^^^^^^^^^^^^^^^^
51+
2852
error[E0252]: the name `A` is defined multiple times
2953
--> $DIR/import-self.rs:16:11
3054
|
@@ -39,7 +63,7 @@ help: you can use `as` to change the binding name of the import
3963
LL | use foo::{self as OtherA};
4064
| ^^^^^^^^^^^^^^
4165

42-
error: aborting due to 4 previous errors
66+
error: aborting due to 5 previous errors
4367

4468
Some errors have detailed explanations: E0252, E0255, E0429.
4569
For more information about an error, try `rustc --explain E0252`.

src/test/ui/use/use-keyword.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0429]: `self` imports are only allowed within a { } list
22
--> $DIR/use-keyword.rs:6:13
33
|
44
LL | use self as A;
5-
| ^^^^^^^^^
5+
| ^^^^
66

77
error[E0432]: unresolved import `super`
88
--> $DIR/use-keyword.rs:8:13

src/test/ui/use/use-mod/use-mod-4.stderr

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
error[E0429]: `self` imports are only allowed within a { } list
2-
--> $DIR/use-mod-4.rs:1:5
2+
--> $DIR/use-mod-4.rs:1:8
33
|
44
LL | use foo::self;
5-
| ^^^^^^^^^
5+
| ^^^^^^
6+
|
7+
help: consider importing the module directly
8+
|
9+
LL | use foo;
10+
| --
11+
help: alternatively, use the multi-path `use` syntax to import `self`
12+
|
13+
LL | use foo::{self};
14+
| ^ ^
615

716
error[E0429]: `self` imports are only allowed within a { } list
8-
--> $DIR/use-mod-4.rs:4:5
17+
--> $DIR/use-mod-4.rs:4:13
918
|
1019
LL | use std::mem::self;
11-
| ^^^^^^^^^^^^^^
20+
| ^^^^^^
21+
|
22+
help: consider importing the module directly
23+
|
24+
LL | use std::mem;
25+
| --
26+
help: alternatively, use the multi-path `use` syntax to import `self`
27+
|
28+
LL | use std::mem::{self};
29+
| ^ ^
1230

1331
error[E0432]: unresolved import `foo`
1432
--> $DIR/use-mod-4.rs:1:5
1533
|
1634
LL | use foo::self;
17-
| ^^^ maybe a missing crate `foo`?
35+
| ^^^^^^^^^ no `foo` in the root
1836

1937
error: aborting due to 3 previous errors
2038

src/test/ui/use/use-mod/use-mod-5.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod foo {
2+
pub mod bar {
3+
pub fn drop() {}
4+
}
5+
}
6+
7+
use foo::bar::self;
8+
//~^ ERROR `self` imports are only allowed within a { } list
9+
10+
fn main() {
11+
// Because of error recovery this shouldn't error
12+
bar::drop();
13+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0429]: `self` imports are only allowed within a { } list
2+
--> $DIR/use-mod-5.rs:7:13
3+
|
4+
LL | use foo::bar::self;
5+
| ^^^^^^
6+
|
7+
help: consider importing the module directly
8+
|
9+
LL | use foo::bar;
10+
| --
11+
help: alternatively, use the multi-path `use` syntax to import `self`
12+
|
13+
LL | use foo::bar::{self};
14+
| ^ ^
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0429`.

src/test/ui/use/use-mod/use-mod-6.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod foo {
2+
pub mod bar {
3+
pub fn drop() {}
4+
}
5+
}
6+
7+
use foo::bar::self as abc;
8+
//~^ ERROR `self` imports are only allowed within a { } list
9+
10+
fn main() {
11+
// Because of error recovery this shouldn't error
12+
abc::drop();
13+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0429]: `self` imports are only allowed within a { } list
2+
--> $DIR/use-mod-6.rs:7:13
3+
|
4+
LL | use foo::bar::self as abc;
5+
| ^^^^^^
6+
|
7+
help: consider importing the module directly
8+
|
9+
LL | use foo::bar as abc;
10+
| --
11+
help: alternatively, use the multi-path `use` syntax to import `self`
12+
|
13+
LL | use foo::bar::{self as abc};
14+
| ^ ^
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0429`.

0 commit comments

Comments
 (0)