let mut i = tokens.iter();
// This might be a sign we need a connect method on Iterator.
let b = i.next()
- .map_or("".to_string(), |t| t.to_string());
+ .map_or(String::new(), |t| t.to_string());
i.enumerate().fold(b, |mut b, (i, a)| {
if tokens.len() > 2 && i == tokens.len() - 2 {
b.push_str(", or ");
} else {
err.span_label(self.span, "expected identifier");
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
- err.span_suggestion(self.span, "remove this comma", "".into());
+ err.span_suggestion_with_applicability(
+ self.span,
+ "remove this comma",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
}
}
err
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
}
- fn parse_seq_to_before_tokens<T, F>(&mut self,
- kets: &[&token::Token],
- sep: SeqSep,
- expect: TokenExpectType,
- mut f: F)
- -> PResult<'a, Vec<T>>
+ fn parse_seq_to_before_tokens<T, F>(
+ &mut self,
+ kets: &[&token::Token],
+ sep: SeqSep,
+ expect: TokenExpectType,
+ mut f: F,
+ ) -> PResult<'a, Vec<T>>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
{
let mut first: bool = true;
// This is somewhat dubious; We don't want to allow
// argument names to be left off if there is a
// definition...
- p.parse_arg_general(false)
+
+ // We don't allow argument names to be left off in edition 2018.
+ if p.span.edition() >= Edition::Edition2018 {
+ p.parse_arg_general(true)
+ } else {
+ p.parse_arg_general(false)
+ }
})?;
generics.where_clause = self.parse_where_clause()?;
let parser_snapshot_before_pat = self.clone();
+ // Once we can use edition 2018 in the compiler,
+ // replace this with real try blocks.
+ macro_rules! try_block {
+ ($($inside:tt)*) => (
+ (||{ ::std::ops::Try::from_ok({ $($inside)* }) })()
+ )
+ }
+
// We're going to try parsing the argument as a pattern (even though it's not
// allowed). This way we can provide better errors to the user.
- let pat_arg: PResult<'a, _> = do catch {
+ let pat_arg: PResult<'a, _> = try_block! {
let pat = self.parse_pat()?;
self.expect(&token::Colon)?;
(pat, self.parse_ty()?)
TokenExpectType::Expect,
|p| p.parse_ty())?;
self.bump(); // `)`
+ let span = lo.to(self.prev_span);
let output = if self.eat(&token::RArrow) {
Some(self.parse_ty_common(false, false)?)
} else {
None
};
- let span = lo.to(self.prev_span);
ParenthesisedArgs { inputs, output, span }.into()
};
BlockCheckMode::Unsafe(ast::UserProvided),
attrs);
}
- if self.is_catch_expr() {
+ if self.is_do_catch_block() {
+ let mut db = self.fatal("found removed `do catch` syntax");
+ db.help("Following RFC #2388, the new non-placeholder syntax is `try`");
+ return Err(db);
+ }
+ if self.is_try_block() {
let lo = self.span;
- assert!(self.eat_keyword(keywords::Do));
- assert!(self.eat_keyword(keywords::Catch));
- return self.parse_catch_expr(lo, attrs);
+ assert!(self.eat_keyword(keywords::Try));
+ return self.parse_try_block(lo, attrs);
}
if self.eat_keyword(keywords::Return) {
if self.token.can_begin_expr() {
err.span_suggestion_short_with_applicability(
self.span,
"remove this comma",
- "".to_owned(),
+ String::new(),
Applicability::MachineApplicable
);
err.note("the base struct must always be the last field");
ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
}
- /// Parse a `do catch {...}` expression (`do catch` token already eaten)
- fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
+ /// Parse a `try {...}` expression (`try` token already eaten)
+ fn parse_try_block(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>>
{
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
- Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
+ Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
}
// `match` token already eaten
e.span_suggestion_short_with_applicability(
match_span,
"try removing this `match`",
- "".to_owned(),
+ String::new(),
Applicability::MaybeIncorrect // speculative
);
}
if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
&& expr_lines.lines.len() == 2
&& self.token == token::FatArrow => {
- // We check wether there's any trailing code in the parse span, if there
- // isn't, we very likely have the following:
+ // We check whether there's any trailing code in the parse span,
+ // if there isn't, we very likely have the following:
//
// X | &Y => "y"
// | -- - missing comma
if self.token == token::CloseDelim(token::Brace) {
// If the struct looks otherwise well formed, recover and continue.
if let Some(sp) = comma_sp {
- err.span_suggestion_short(sp, "remove this comma", "".into());
+ err.span_suggestion_short(sp, "remove this comma", String::new());
}
err.emit();
break;
err.multipart_suggestion(
"move the `..` to the end of the field list",
vec![
- (etc_span, "".into()),
+ (etc_span, String::new()),
(self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
],
);
}
/// A wrapper around `parse_pat` with some special error handling for the
- /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contast
+ /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast
/// to subpatterns within such).
fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
let pat = self.parse_pat()?;
// If `break_on_semi` is `Break`, then we will stop consuming tokens after
// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
// approximate - it can mean we break too early due to macros, but that
- // shoud only lead to sub-optimal recovery, not inaccurate parsing).
+ // should only lead to sub-optimal recovery, not inaccurate parsing).
//
// If `break_on_block` is `Break`, then we will stop consuming tokens
// after finding (and consuming) a brace-delimited block.
)
}
- fn is_catch_expr(&mut self) -> bool {
+ fn is_do_catch_block(&mut self) -> bool {
self.token.is_keyword(keywords::Do) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
+ !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
+ }
+
+ fn is_try_block(&mut self) -> bool {
+ self.token.is_keyword(keywords::Try) &&
+ self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
- // prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
+ self.span.edition() >= Edition::Edition2018 &&
+
+ // prevent `while try {} {}`, `if try {} {} else {}`, etc.
!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
}
fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> {
let mut bounds = Vec::new();
loop {
- // This needs to be syncronized with `Token::can_begin_bound`.
+ // This needs to be synchronized with `Token::can_begin_bound`.
let is_bound_start = self.check_path() || self.check_lifetime() ||
self.check(&token::Question) ||
self.check_keyword(keywords::For) ||
self.this_token_to_string()));
if self.token.is_ident() {
// This is likely another field; emit the diagnostic and keep going
- err.span_suggestion(sp, "try adding a comma", ",".into());
+ err.span_suggestion_with_applicability(
+ sp,
+ "try adding a comma",
+ ",".into(),
+ Applicability::MachineApplicable,
+ );
err.emit();
} else {
return Err(err)
if token_str == ";" {
let msg = "consider removing this semicolon";
err.span_suggestion_short_with_applicability(
- self.span, msg, "".to_string(), Applicability::MachineApplicable
+ self.span, msg, String::new(), Applicability::MachineApplicable
);
if !items.is_empty() { // Issue #51603
let previous_item = &items[items.len()-1];
}
/// Parse one of the items allowed by the flags.
- /// NB: this function no longer parses the items inside an
- /// extern crate.
fn parse_item_implementation(
&mut self,
attrs: Vec<Attribute>,