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](https://github.com/rust-lang/rust/issues/63741#issuecomment-602391091) by @comex. I believe r? @estebank deals with diagnostics.
This commit is contained in:
commit
14c439177b
@ -426,7 +426,7 @@ fn build_reduced_graph_for_use_tree(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace `use foo::self;` with `use foo;`
|
// Replace `use foo::{ self };` with `use foo;`
|
||||||
source = module_path.pop().unwrap();
|
source = module_path.pop().unwrap();
|
||||||
if rename.is_none() {
|
if rename.is_none() {
|
||||||
ident = source.ident;
|
ident = source.ident;
|
||||||
@ -435,10 +435,33 @@ fn build_reduced_graph_for_use_tree(
|
|||||||
} else {
|
} else {
|
||||||
// Disallow `self`
|
// Disallow `self`
|
||||||
if source.ident.name == kw::SelfLower {
|
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(
|
self.r.report_error(
|
||||||
use_tree.span,
|
span,
|
||||||
ResolutionError::SelfImportsOnlyAllowedWithin,
|
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;`
|
// Disallow `use $crate;`
|
||||||
|
@ -301,13 +301,40 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
ResolutionError::SelfImportsOnlyAllowedWithin => struct_span_err!(
|
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
|
||||||
self.session,
|
let mut err = struct_span_err!(
|
||||||
span,
|
self.session,
|
||||||
E0429,
|
span,
|
||||||
"{}",
|
E0429,
|
||||||
"`self` imports are only allowed within a { } list"
|
"{}",
|
||||||
),
|
"`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 => {
|
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.session,
|
self.session,
|
||||||
|
@ -194,7 +194,7 @@ enum ResolutionError<'a> {
|
|||||||
/// Error E0426: use of undeclared label.
|
/// Error E0426: use of undeclared label.
|
||||||
UndeclaredLabel(&'a str, Option<Symbol>),
|
UndeclaredLabel(&'a str, Option<Symbol>),
|
||||||
/// Error E0429: `self` imports are only allowed within a `{ }` list.
|
/// 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.
|
/// Error E0430: `self` import can only appear once in the list.
|
||||||
SelfImportCanOnlyAppearOnceInTheList,
|
SelfImportCanOnlyAppearOnceInTheList,
|
||||||
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
|
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
error[E0429]: `self` imports are only allowed within a { } list
|
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;
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ mod foo {
|
|||||||
use foo as self;
|
use foo as self;
|
||||||
//~^ ERROR expected identifier
|
//~^ ERROR expected identifier
|
||||||
|
|
||||||
use foo::self;
|
use foo::self; //~ ERROR is defined multiple times
|
||||||
//~^ ERROR `self` imports are only allowed within a { } list
|
//~^ ERROR `self` imports are only allowed within a { } list
|
||||||
|
|
||||||
use foo::A;
|
use foo::A;
|
||||||
|
@ -5,10 +5,19 @@ LL | use foo as self;
|
|||||||
| ^^^^ expected identifier, found keyword
|
| ^^^^ expected identifier, found keyword
|
||||||
|
|
||||||
error[E0429]: `self` imports are only allowed within a { } list
|
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;
|
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
|
error[E0255]: the name `foo` is defined multiple times
|
||||||
--> $DIR/import-self.rs:6:11
|
--> $DIR/import-self.rs:6:11
|
||||||
@ -25,6 +34,21 @@ help: you can use `as` to change the binding name of the import
|
|||||||
LL | use foo::{self as other_foo};
|
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
|
error[E0252]: the name `A` is defined multiple times
|
||||||
--> $DIR/import-self.rs:16:11
|
--> $DIR/import-self.rs:16:11
|
||||||
|
|
|
|
||||||
@ -39,7 +63,7 @@ help: you can use `as` to change the binding name of the import
|
|||||||
LL | use foo::{self as OtherA};
|
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.
|
Some errors have detailed explanations: E0252, E0255, E0429.
|
||||||
For more information about an error, try `rustc --explain E0252`.
|
For more information about an error, try `rustc --explain E0252`.
|
||||||
|
@ -2,7 +2,7 @@ error[E0429]: `self` imports are only allowed within a { } list
|
|||||||
--> $DIR/use-keyword.rs:6:13
|
--> $DIR/use-keyword.rs:6:13
|
||||||
|
|
|
|
||||||
LL | use self as A;
|
LL | use self as A;
|
||||||
| ^^^^^^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0432]: unresolved import `super`
|
error[E0432]: unresolved import `super`
|
||||||
--> $DIR/use-keyword.rs:8:13
|
--> $DIR/use-keyword.rs:8:13
|
||||||
|
@ -1,20 +1,38 @@
|
|||||||
error[E0429]: `self` imports are only allowed within a { } list
|
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;
|
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
|
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;
|
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`
|
error[E0432]: unresolved import `foo`
|
||||||
--> $DIR/use-mod-4.rs:1:5
|
--> $DIR/use-mod-4.rs:1:5
|
||||||
|
|
|
|
||||||
LL | use foo::self;
|
LL | use foo::self;
|
||||||
| ^^^ maybe a missing crate `foo`?
|
| ^^^^^^^^^ no `foo` in the root
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
13
src/test/ui/use/use-mod/use-mod-5.rs
Normal file
13
src/test/ui/use/use-mod/use-mod-5.rs
Normal file
@ -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
src/test/ui/use/use-mod/use-mod-5.stderr
Normal file
18
src/test/ui/use/use-mod/use-mod-5.stderr
Normal file
@ -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
src/test/ui/use/use-mod/use-mod-6.rs
Normal file
13
src/test/ui/use/use-mod/use-mod-6.rs
Normal file
@ -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
src/test/ui/use/use-mod/use-mod-6.stderr
Normal file
18
src/test/ui/use/use-mod/use-mod-6.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user