Rollup merge of #71243 - Duddino:Fix2, r=estebank

Account for use of `try!()` in 2018 edition and guide users in the right direction

fixes #71155
This commit is contained in:
Dylan DPC 2020-04-17 23:56:04 +02:00 committed by GitHub
commit 4b9eeca5c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 1 deletions

View File

@ -1054,6 +1054,39 @@ impl<'a> Parser<'a> {
}
}
pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
let is_try = self.token.is_keyword(kw::Try);
let is_questionmark = self.look_ahead(1, |t| t == &token::Not); //check for !
let is_open = self.look_ahead(2, |t| t == &token::OpenDelim(token::Paren)); //check for (
if is_try && is_questionmark && is_open {
let lo = self.token.span;
self.bump(); //remove try
self.bump(); //remove !
let try_span = lo.to(self.token.span); //we take the try!( span
self.bump(); //remove (
let is_empty = self.token == token::CloseDelim(token::Paren); //check if the block is empty
self.consume_block(token::Paren, ConsumeClosingDelim::No); //eat the block
let hi = self.token.span;
self.bump(); //remove )
let mut err = self.struct_span_err(lo.to(hi), "use of deprecated `try` macro");
err.note("in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated");
let prefix = if is_empty { "" } else { "alternatively, " };
if !is_empty {
err.multipart_suggestion(
"you can use the `?` operator instead",
vec![(try_span, "".to_owned()), (hi, "?".to_owned())],
Applicability::MachineApplicable,
);
}
err.span_suggestion(lo.shrink_to_lo(), &format!("{}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax", prefix), "r#".to_string(), Applicability::MachineApplicable);
err.emit();
Ok(self.mk_expr_err(lo.to(hi)))
} else {
Err(self.expected_expression_found()) // The user isn't trying to invoke the try! macro
}
}
/// Recovers a situation like `for ( $pat in $expr )`
/// and suggest writing `for $pat in $expr` instead.
///

View File

@ -1006,7 +1006,7 @@ impl<'a> Parser<'a> {
let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs);
self.maybe_recover_from_bad_qpath(expr, true)
}
None => Err(self.expected_expression_found()),
None => self.try_macro_suggestion(),
}
}

View File

@ -0,0 +1,9 @@
// compile-flags: --edition 2018
fn foo() -> Result<(), ()> {
Ok(try!()); //~ ERROR use of deprecated `try` macro
Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
}
fn main() {
let _ = foo();
}

View File

@ -0,0 +1,30 @@
error: use of deprecated `try` macro
--> $DIR/try-macro-suggestion.rs:3:8
|
LL | Ok(try!());
| ^^^^^^
|
= note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
|
LL | Ok(r#try!());
| ^^
error: use of deprecated `try` macro
--> $DIR/try-macro-suggestion.rs:4:8
|
LL | Ok(try!(Ok(())))
| ^^^^^^^^^^^^
|
= note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
help: you can use the `?` operator instead
|
LL | Ok(Ok(())?)
| -- ^
help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
|
LL | Ok(r#try!(Ok(())))
| ^^
error: aborting due to 2 previous errors