Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest fixes and add error recovery for use foo::self #71863

Merged
merged 3 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.