Skip to content

Commit

Permalink
Rollup merge of rust-lang#71863 - mibac138:self-import, r=estebank
Browse files Browse the repository at this point in the history
Suggest fixes and add error recovery for `use foo::self`

Fixes rust-lang#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](rust-lang#63741 (comment)) by @comex.

I believe r? @estebank deals with diagnostics.
  • Loading branch information
Dylan-DPC committed May 20, 2020
2 parents f182c4a + aaeea7f commit 38c63c9
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 23 deletions.
29 changes: 26 additions & 3 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
return;
}

// Replace `use foo::self;` with `use foo;`
// Replace `use foo::{ self };` with `use foo;`
source = module_path.pop().unwrap();
if rename.is_none() {
ident = source.ident;
Expand All @@ -435,10 +435,33 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
} else {
// Disallow `self`
if source.ident.name == kw::SelfLower {
let parent = module_path.last();

let span = match parent {
// only `::self` from `use foo::self as bar`
Some(seg) => seg.ident.span.shrink_to_hi().to(source.ident.span),
None => source.ident.span,
};
let span_with_rename = match rename {
// only `self as bar` from `use foo::self as bar`
Some(rename) => source.ident.span.to(rename.span),
None => source.ident.span,
};
self.r.report_error(
use_tree.span,
ResolutionError::SelfImportsOnlyAllowedWithin,
span,
ResolutionError::SelfImportsOnlyAllowedWithin {
root: parent.is_none(),
span_with_rename,
},
);

// Error recovery: replace `use foo::self;` with `use foo;`
if let Some(parent) = module_path.pop() {
source = parent;
if rename.is_none() {
ident = source.ident;
}
}
}

// Disallow `use $crate;`
Expand Down
41 changes: 34 additions & 7 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,40 @@ impl<'a> Resolver<'a> {
}
err
}
ResolutionError::SelfImportsOnlyAllowedWithin => struct_span_err!(
self.session,
span,
E0429,
"{}",
"`self` imports are only allowed within a { } list"
),
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
let mut err = struct_span_err!(
self.session,
span,
E0429,
"{}",
"`self` imports are only allowed within a { } list"
);

// None of the suggestions below would help with a case like `use self`.
if !root {
// use foo::bar::self -> foo::bar
// use foo::bar::self as abc -> foo::bar as abc
err.span_suggestion(
span,
"consider importing the module directly",
"".to_string(),
Applicability::MachineApplicable,
);

// use foo::bar::self -> foo::bar::{self}
// use foo::bar::self as abc -> foo::bar::{self as abc}
let braces = vec![
(span_with_rename.shrink_to_lo(), "{".to_string()),
(span_with_rename.shrink_to_hi(), "}".to_string()),
];
err.multipart_suggestion(
"alternatively, use the multi-path `use` syntax to import `self`",
braces,
Applicability::MachineApplicable,
);
}
err
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
let mut err = struct_span_err!(
self.session,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ enum ResolutionError<'a> {
/// Error E0426: use of undeclared label.
UndeclaredLabel(&'a str, Option<Symbol>),
/// Error E0429: `self` imports are only allowed within a `{ }` list.
SelfImportsOnlyAllowedWithin,
SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span },
/// Error E0430: `self` import can only appear once in the list.
SelfImportCanOnlyAppearOnceInTheList,
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
Expand Down
13 changes: 11 additions & 2 deletions src/test/ui/error-codes/E0429.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/E0429.rs:1:5
--> $DIR/E0429.rs:1:13
|
LL | use std::fmt::self;
| ^^^^^^^^^^^^^^
| ^^^^^^
|
help: consider importing the module directly
|
LL | use std::fmt;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use std::fmt::{self};
| ^ ^

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-45829/import-self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use foo::{self};
use foo as self;
//~^ ERROR expected identifier

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

use foo::A;
Expand Down
30 changes: 27 additions & 3 deletions src/test/ui/issues/issue-45829/import-self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@ LL | use foo as self;
| ^^^^ expected identifier, found keyword

error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/import-self.rs:12:5
--> $DIR/import-self.rs:12:8
|
LL | use foo::self;
| ^^^^^^^^^
| ^^^^^^
|
help: consider importing the module directly
|
LL | use foo;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use foo::{self};
| ^ ^

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

error[E0255]: the name `foo` is defined multiple times
--> $DIR/import-self.rs:12:5
|
LL | mod foo {
| ------- previous definition of the module `foo` here
...
LL | use foo::self;
| ^^^^^^^^^ `foo` reimported here
|
= note: `foo` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use foo as other_foo;
| ^^^^^^^^^^^^^^^^

error[E0252]: the name `A` is defined multiple times
--> $DIR/import-self.rs:16:11
|
Expand All @@ -39,7 +63,7 @@ help: you can use `as` to change the binding name of the import
LL | use foo::{self as OtherA};
| ^^^^^^^^^^^^^^

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0252, E0255, E0429.
For more information about an error, try `rustc --explain E0252`.
2 changes: 1 addition & 1 deletion src/test/ui/use/use-keyword.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/use-keyword.rs:6:13
|
LL | use self as A;
| ^^^^^^^^^
| ^^^^

error[E0432]: unresolved import `super`
--> $DIR/use-keyword.rs:8:13
Expand Down
28 changes: 23 additions & 5 deletions src/test/ui/use/use-mod/use-mod-4.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/use-mod-4.rs:1:5
--> $DIR/use-mod-4.rs:1:8
|
LL | use foo::self;
| ^^^^^^^^^
| ^^^^^^
|
help: consider importing the module directly
|
LL | use foo;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use foo::{self};
| ^ ^

error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/use-mod-4.rs:4:5
--> $DIR/use-mod-4.rs:4:13
|
LL | use std::mem::self;
| ^^^^^^^^^^^^^^
| ^^^^^^
|
help: consider importing the module directly
|
LL | use std::mem;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use std::mem::{self};
| ^ ^

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

error: aborting due to 3 previous errors

Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/use/use-mod/use-mod-5.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod foo {
pub mod bar {
pub fn drop() {}
}
}

use foo::bar::self;
//~^ ERROR `self` imports are only allowed within a { } list

fn main() {
// Because of error recovery this shouldn't error
bar::drop();
}
18 changes: 18 additions & 0 deletions src/test/ui/use/use-mod/use-mod-5.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/use-mod-5.rs:7:13
|
LL | use foo::bar::self;
| ^^^^^^
|
help: consider importing the module directly
|
LL | use foo::bar;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use foo::bar::{self};
| ^ ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0429`.
13 changes: 13 additions & 0 deletions src/test/ui/use/use-mod/use-mod-6.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod foo {
pub mod bar {
pub fn drop() {}
}
}

use foo::bar::self as abc;
//~^ ERROR `self` imports are only allowed within a { } list

fn main() {
// Because of error recovery this shouldn't error
abc::drop();
}
18 changes: 18 additions & 0 deletions src/test/ui/use/use-mod/use-mod-6.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0429]: `self` imports are only allowed within a { } list
--> $DIR/use-mod-6.rs:7:13
|
LL | use foo::bar::self as abc;
| ^^^^^^
|
help: consider importing the module directly
|
LL | use foo::bar as abc;
| --
help: alternatively, use the multi-path `use` syntax to import `self`
|
LL | use foo::bar::{self as abc};
| ^ ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0429`.

0 comments on commit 38c63c9

Please sign in to comment.