Rollup merge of #97819 - compiler-errors:use-import, r=wesleywiser
Recover `import` instead of `use` in item When we definitely don't have a macro invocation (i.e. when we don't have `import ::`), then it's more productive to parse `import` as if it was incorrectly mistaken for `use`. Not sure if this needs to be a verbose suggestion, but it renders strangely when it's not verbose: ``` error: expected item, found `import` --> /home/michael/test.rs:1:1 | 1 | import std::{io::{self, Write}, rc::Rc}; | ^^^^^^ help: items are imported using the `use` keyword: `use` ``` Happy to change it to `span_suggestion` instead of `span_suggestion_verbose` though. Fixes #97788
This commit is contained in:
commit
a64a9829c8
@ -204,25 +204,7 @@ fn parse_item_kind(
|
||||
let mut def = || mem::replace(def, Defaultness::Final);
|
||||
|
||||
let info = if self.eat_keyword(kw::Use) {
|
||||
// USE ITEM
|
||||
let tree = self.parse_use_tree()?;
|
||||
|
||||
// If wildcard or glob-like brace syntax doesn't have `;`,
|
||||
// the user may not know `*` or `{}` should be the last.
|
||||
if let Err(mut e) = self.expect_semi() {
|
||||
match tree.kind {
|
||||
UseTreeKind::Glob => {
|
||||
e.note("the wildcard token must be last on the path");
|
||||
}
|
||||
UseTreeKind::Nested(..) => {
|
||||
e.note("glob-like brace syntax must be last on the path");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
(Ident::empty(), ItemKind::Use(tree))
|
||||
self.parse_use_item()?
|
||||
} else if self.check_fn_front_matter(def_final) {
|
||||
// FUNCTION ITEM
|
||||
let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?;
|
||||
@ -288,7 +270,12 @@ fn parse_item_kind(
|
||||
} else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
|
||||
// MACRO_RULES ITEM
|
||||
self.parse_item_macro_rules(vis, has_bang)?
|
||||
} else if vis.kind.is_pub() && self.isnt_macro_invocation() {
|
||||
} else if self.isnt_macro_invocation()
|
||||
&& (self.token.is_ident_named(Symbol::intern("import"))
|
||||
|| self.token.is_ident_named(Symbol::intern("using")))
|
||||
{
|
||||
return self.recover_import_as_use();
|
||||
} else if self.isnt_macro_invocation() && vis.kind.is_pub() {
|
||||
self.recover_missing_kw_before_item()?;
|
||||
return Ok(None);
|
||||
} else if macros_allowed && self.check_path() {
|
||||
@ -300,6 +287,48 @@ fn parse_item_kind(
|
||||
Ok(Some(info))
|
||||
}
|
||||
|
||||
fn recover_import_as_use(&mut self) -> PResult<'a, Option<(Ident, ItemKind)>> {
|
||||
let span = self.token.span;
|
||||
let token_name = super::token_descr(&self.token);
|
||||
let snapshot = self.create_snapshot_for_diagnostic();
|
||||
self.bump();
|
||||
match self.parse_use_item() {
|
||||
Ok(u) => {
|
||||
self.struct_span_err(span, format!("expected item, found {token_name}"))
|
||||
.span_suggestion_short(
|
||||
span,
|
||||
"items are imported using the `use` keyword",
|
||||
"use".to_owned(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
Ok(Some(u))
|
||||
}
|
||||
Err(e) => {
|
||||
e.cancel();
|
||||
self.restore_snapshot(snapshot);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_use_item(&mut self) -> PResult<'a, (Ident, ItemKind)> {
|
||||
let tree = self.parse_use_tree()?;
|
||||
if let Err(mut e) = self.expect_semi() {
|
||||
match tree.kind {
|
||||
UseTreeKind::Glob => {
|
||||
e.note("the wildcard token must be last on the path");
|
||||
}
|
||||
UseTreeKind::Nested(..) => {
|
||||
e.note("glob-like brace syntax must be last on the path");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
Ok((Ident::empty(), ItemKind::Use(tree)))
|
||||
}
|
||||
|
||||
/// When parsing a statement, would the start of a path be an item?
|
||||
pub(super) fn is_path_start_item(&mut self) -> bool {
|
||||
self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`
|
||||
|
15
src/test/ui/did_you_mean/use_instead_of_import.fixed
Normal file
15
src/test/ui/did_you_mean/use_instead_of_import.fixed
Normal file
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
|
||||
use std::{
|
||||
//~^ ERROR expected item, found `import`
|
||||
io::Write,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub use std::io;
|
||||
//~^ ERROR expected item, found `using`
|
||||
|
||||
fn main() {
|
||||
let x = Rc::new(1);
|
||||
let _ = write!(io::stdout(), "{:?}", x);
|
||||
}
|
15
src/test/ui/did_you_mean/use_instead_of_import.rs
Normal file
15
src/test/ui/did_you_mean/use_instead_of_import.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
|
||||
import std::{
|
||||
//~^ ERROR expected item, found `import`
|
||||
io::Write,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub using std::io;
|
||||
//~^ ERROR expected item, found `using`
|
||||
|
||||
fn main() {
|
||||
let x = Rc::new(1);
|
||||
let _ = write!(io::stdout(), "{:?}", x);
|
||||
}
|
14
src/test/ui/did_you_mean/use_instead_of_import.stderr
Normal file
14
src/test/ui/did_you_mean/use_instead_of_import.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: expected item, found `import`
|
||||
--> $DIR/use_instead_of_import.rs:3:1
|
||||
|
|
||||
LL | import std::{
|
||||
| ^^^^^^ help: items are imported using the `use` keyword
|
||||
|
||||
error: expected item, found `using`
|
||||
--> $DIR/use_instead_of_import.rs:9:5
|
||||
|
|
||||
LL | pub using std::io;
|
||||
| ^^^^^ help: items are imported using the `use` keyword
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user