diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index 377d43dec21a2..4b7f1e9a4d833 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -2,6 +2,7 @@ use super::{Parser, PathStyle, TokenType}; use rustc_errors::PResult; use syntax::ast; use syntax::attr; +use syntax::print::pprust; use syntax::token::{self, Nonterminal}; use syntax::util::comments; use syntax_pos::{Span, Symbol}; @@ -154,7 +155,7 @@ impl<'a> Parser<'a> { (attr_sp, item, style) } _ => { - let token_str = self.this_token_to_string(); + let token_str = pprust::token_to_string(&self.token); return Err(self.fatal(&format!("expected `#`, found `{}`", token_str))); } }; @@ -329,7 +330,7 @@ impl<'a> Parser<'a> { Err(ref mut err) => err.cancel(), } - let found = self.this_token_to_string(); + let found = pprust::token_to_string(&self.token); let msg = format!("expected unsuffixed literal or identifier, found `{}`", found); Err(self.diagnostic().struct_span_err(self.token.span, &msg)) } diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index f58b9a4c14441..578f816be58c8 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -200,7 +200,7 @@ impl<'a> Parser<'a> { pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { let mut err = self.struct_span_err( self.token.span, - &format!("expected identifier, found {}", self.this_token_descr()), + &format!("expected identifier, found {}", super::token_descr(&self.token)), ); let valid_follow = &[ TokenKind::Eq, @@ -225,7 +225,7 @@ impl<'a> Parser<'a> { ); } } - if let Some(token_descr) = self.token_descr() { + if let Some(token_descr) = super::token_descr_opt(&self.token) { err.span_label(self.token.span, format!("expected identifier, found {}", token_descr)); } else { err.span_label(self.token.span, "expected identifier"); @@ -272,7 +272,7 @@ impl<'a> Parser<'a> { expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); let expect = tokens_to_string(&expected[..]); - let actual = self.this_token_descr(); + let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { let short_expect = if expected.len() > 6 { format!("{} possible tokens", expected.len()) @@ -815,7 +815,7 @@ impl<'a> Parser<'a> { t: &TokenKind, ) -> PResult<'a, bool /* recovered */> { let token_str = pprust::token_kind_to_string(t); - let this_token_str = self.this_token_descr(); + let this_token_str = super::token_descr(&self.token); let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) { // Point at the end of the macro call when reaching end of macro arguments. (token::Eof, Some(_)) => { @@ -862,7 +862,7 @@ impl<'a> Parser<'a> { return Ok(()); } let sm = self.sess.source_map(); - let msg = format!("expected `;`, found `{}`", self.this_token_descr()); + let msg = format!("expected `;`, found `{}`", super::token_descr(&self.token)); let appl = Applicability::MachineApplicable; if self.token.span == DUMMY_SP || self.prev_span == DUMMY_SP { // Likely inside a macro, can't provide meaninful suggestions. @@ -1270,7 +1270,7 @@ impl<'a> Parser<'a> { } pub(super) fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> { - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str)); err.span_label(self.token.span, "expected `;` or `{`"); Err(err) @@ -1447,7 +1447,7 @@ impl<'a> Parser<'a> { } _ => ( self.token.span, - format!("expected expression, found {}", self.this_token_descr(),), + format!("expected expression, found {}", super::token_descr(&self.token),), ), }; let mut err = self.struct_span_err(span, &msg); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index e0eb841f2c0cf..b51a4465b159e 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -210,30 +210,12 @@ impl<'a> Parser<'a> { lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; continue; } else if op == AssocOp::Colon { - let maybe_path = self.could_ascription_be_path(&lhs.kind); - self.last_type_ascription = Some((self.prev_span, maybe_path)); - - lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; - self.sess.gated_spans.gate(sym::type_ascription, lhs.span); + lhs = self.parse_assoc_op_ascribe(lhs, lhs_span)?; continue; } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to // generalise it to the Fixity::None code. - // - // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other - // two variants are handled with `parse_prefix_range_expr` call above. - let rhs = if self.is_at_start_of_range_notation_rhs() { - Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?) - } else { - None - }; - let (lhs_span, rhs_span) = - (lhs.span, if let Some(ref x) = rhs { x.span } else { cur_op_span }); - let limits = - if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; - - let r = self.mk_range(Some(lhs), rhs, limits)?; - lhs = self.mk_expr(lhs_span.to(rhs_span), r, AttrVec::new()); + lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?; break; } @@ -395,6 +377,27 @@ impl<'a> Parser<'a> { && !classify::expr_requires_semi_to_be_stmt(e) } + /// Parses `x..y`, `x..=y`, and `x..`/`x..=`. + /// The other two variants are handled in `parse_prefix_range_expr` below. + fn parse_range_expr( + &mut self, + prec: usize, + lhs: P<Expr>, + op: AssocOp, + cur_op_span: Span, + ) -> PResult<'a, P<Expr>> { + let rhs = if self.is_at_start_of_range_notation_rhs() { + Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?) + } else { + None + }; + let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); + let span = lhs.span.to(rhs_span); + let limits = + if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; + Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new())) + } + fn is_at_start_of_range_notation_rhs(&self) -> bool { if self.token.can_begin_expr() { // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. @@ -408,10 +411,7 @@ impl<'a> Parser<'a> { } /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. - fn parse_prefix_range_expr( - &mut self, - already_parsed_attrs: Option<AttrVec>, - ) -> PResult<'a, P<Expr>> { + fn parse_prefix_range_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> { // Check for deprecated `...` syntax. if self.token == token::DotDotDot { self.err_dotdotdot_syntax(self.token.span); @@ -422,118 +422,107 @@ impl<'a> Parser<'a> { "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq", self.token ); - let tok = self.token.clone(); - let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; + + let limits = match self.token.kind { + token::DotDot => RangeLimits::HalfOpen, + _ => RangeLimits::Closed, + }; + let op = AssocOp::from_token(&self.token); + let attrs = self.parse_or_use_outer_attributes(attrs)?; let lo = self.token.span; - let mut hi = self.token.span; self.bump(); - let opt_end = if self.is_at_start_of_range_notation_rhs() { + let (span, opt_end) = if self.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. - let next_prec = AssocOp::from_token(&tok).unwrap().precedence() + 1; - Some(self.parse_assoc_expr_with(next_prec, LhsExpr::NotYetParsed).map(|x| { - hi = x.span; - x - })?) + self.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) + .map(|x| (lo.to(x.span), Some(x)))? } else { - None + (lo, None) }; - let limits = if tok == token::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; - - let r = self.mk_range(None, opt_end, limits)?; - Ok(self.mk_expr(lo.to(hi), r, attrs)) + Ok(self.mk_expr(span, self.mk_range(None, opt_end, limits)?, attrs)) } /// Parses a prefix-unary-operator expr. - fn parse_prefix_expr(&mut self, already_parsed_attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> { - let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; + fn parse_prefix_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> { + let attrs = self.parse_or_use_outer_attributes(attrs)?; let lo = self.token.span; // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() let (hi, ex) = match self.token.kind { - token::Not => { - self.bump(); - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - (lo.to(span), self.mk_unary(UnOp::Not, e)) - } - // Suggest `!` for bitwise negation when encountering a `~` - token::Tilde => { - self.bump(); - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - let span_of_tilde = lo; - self.struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator") - .span_suggestion_short( - span_of_tilde, - "use `!` to perform bitwise not", - "!".to_owned(), - Applicability::MachineApplicable, - ) - .emit(); - (lo.to(span), self.mk_unary(UnOp::Not, e)) - } - token::BinOp(token::Minus) => { - self.bump(); - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - (lo.to(span), self.mk_unary(UnOp::Neg, e)) - } - token::BinOp(token::Star) => { - self.bump(); - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - (lo.to(span), self.mk_unary(UnOp::Deref, e)) - } - token::BinOp(token::And) | token::AndAnd => self.parse_address_of(lo)?, - token::Ident(..) if self.token.is_keyword(kw::Box) => { - self.bump(); - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - let span = lo.to(span); - self.sess.gated_spans.gate(sym::box_syntax, span); - (span, ExprKind::Box(e)) - } - token::Ident(..) if self.token.is_ident_named(sym::not) => { - // `not` is just an ordinary identifier in Rust-the-language, - // but as `rustc`-the-compiler, we can issue clever diagnostics - // for confused users who really want to say `!` - let token_cannot_continue_expr = |t: &Token| match t.kind { - // These tokens can start an expression after `!`, but - // can't continue an expression after an ident - token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), - token::Literal(..) | token::Pound => true, - _ => t.is_whole_expr(), - }; - let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr); - if cannot_continue_expr { - self.bump(); - // Emit the error ... - self.struct_span_err( - self.token.span, - &format!("unexpected {} after identifier", self.this_token_descr()), - ) - .span_suggestion_short( - // Span the `not` plus trailing whitespace to avoid - // trailing whitespace after the `!` in our suggestion - self.sess.source_map().span_until_non_whitespace(lo.to(self.token.span)), - "use `!` to perform logical negation", - "!".to_owned(), - Applicability::MachineApplicable, - ) - .emit(); - // —and recover! (just as if we were in the block - // for the `token::Not` arm) - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - (lo.to(span), self.mk_unary(UnOp::Not, e)) - } else { - return self.parse_dot_or_call_expr(Some(attrs)); - } - } - _ => { - return self.parse_dot_or_call_expr(Some(attrs)); - } + token::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr` + token::Tilde => self.recover_tilde_expr(lo), // `~expr` + token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-expr` + token::BinOp(token::Star) => self.parse_unary_expr(lo, UnOp::Deref), // `*expr` + token::BinOp(token::And) | token::AndAnd => self.parse_borrow_expr(lo), + token::Ident(..) if self.token.is_keyword(kw::Box) => self.parse_box_expr(lo), + token::Ident(..) if self.is_mistaken_not_ident_negation() => self.recover_not_expr(lo), + _ => return self.parse_dot_or_call_expr(Some(attrs)), + }?; + Ok(self.mk_expr(lo.to(hi), ex, attrs)) + } + + fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> { + self.bump(); + let expr = self.parse_prefix_expr(None); + let (span, expr) = self.interpolated_or_expr_span(expr)?; + Ok((lo.to(span), expr)) + } + + fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> { + let (span, expr) = self.parse_prefix_expr_common(lo)?; + Ok((span, self.mk_unary(op, expr))) + } + + // Recover on `!` suggesting for bitwise negation instead. + fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { + self.struct_span_err(lo, "`~` cannot be used as a unary operator") + .span_suggestion_short( + lo, + "use `!` to perform bitwise not", + "!".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + + self.parse_unary_expr(lo, UnOp::Not) + } + + /// Parse `box expr`. + fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { + let (span, expr) = self.parse_prefix_expr_common(lo)?; + self.sess.gated_spans.gate(sym::box_syntax, span); + Ok((span, ExprKind::Box(expr))) + } + + fn is_mistaken_not_ident_negation(&self) -> bool { + let token_cannot_continue_expr = |t: &Token| match t.kind { + // These tokens can start an expression after `!`, but + // can't continue an expression after an ident + token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), + token::Literal(..) | token::Pound => true, + _ => t.is_whole_expr(), }; - return Ok(self.mk_expr(lo.to(hi), ex, attrs)); + self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) + } + + /// Recover on `not expr` in favor of `!expr`. + fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { + // Emit the error... + let not_token = self.look_ahead(1, |t| t.clone()); + self.struct_span_err( + not_token.span, + &format!("unexpected {} after identifier", super::token_descr(¬_token)), + ) + .span_suggestion_short( + // Span the `not` plus trailing whitespace to avoid + // trailing whitespace after the `!` in our suggestion + self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)), + "use `!` to perform logical negation", + "!".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + + // ...and recover! + self.parse_unary_expr(lo, UnOp::Not) } /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. @@ -598,14 +587,7 @@ impl<'a> Parser<'a> { op_noun, ); let span_after_type = parser_snapshot_after_type.token.span; - let expr = mk_expr( - self, - P(Ty { - span: path.span, - kind: TyKind::Path(None, path), - id: DUMMY_NODE_ID, - }), - ); + let expr = mk_expr(self, self.mk_ty(path.span, TyKind::Path(None, path))); let expr_str = self .span_to_snippet(expr.span) @@ -638,33 +620,44 @@ impl<'a> Parser<'a> { } } + fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> { + let maybe_path = self.could_ascription_be_path(&lhs.kind); + self.last_type_ascription = Some((self.prev_span, maybe_path)); + let lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; + self.sess.gated_spans.gate(sym::type_ascription, lhs.span); + Ok(lhs) + } + /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`. - fn parse_address_of(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { + fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { self.expect_and()?; - let (k, m) = if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { + let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo); + let expr = self.parse_prefix_expr(None); + let (span, expr) = self.interpolated_or_expr_span(expr)?; + Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr))) + } + + /// Parse `mut?` or `raw [ const | mut ]`. + fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) { + if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { + // `raw [ const | mut ]`. let found_raw = self.eat_keyword(kw::Raw); assert!(found_raw); let mutability = self.parse_const_or_mut().unwrap(); self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_span)); (ast::BorrowKind::Raw, mutability) } else { + // `mut?` (ast::BorrowKind::Ref, self.parse_mutability()) - }; - let e = self.parse_prefix_expr(None); - let (span, e) = self.interpolated_or_expr_span(e)?; - Ok((lo.to(span), ExprKind::AddrOf(k, m, e))) + } } /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. - fn parse_dot_or_call_expr( - &mut self, - already_parsed_attrs: Option<AttrVec>, - ) -> PResult<'a, P<Expr>> { - let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; - - let b = self.parse_bottom_expr(); - let (span, b) = self.interpolated_or_expr_span(b)?; - self.parse_dot_or_call_expr_with(b, span, attrs) + fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> { + let attrs = self.parse_or_use_outer_attributes(attrs)?; + let base = self.parse_bottom_expr(); + let (span, base) = self.interpolated_or_expr_span(base)?; + self.parse_dot_or_call_expr_with(base, span, attrs) } pub(super) fn parse_dot_or_call_expr_with( @@ -694,95 +687,120 @@ impl<'a> Parser<'a> { } } - fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { - let mut e = e0; - let mut hi; + fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { loop { - // expr? - while self.eat(&token::Question) { - let hi = self.prev_span; - e = self.mk_expr(lo.to(hi), ExprKind::Try(e), AttrVec::new()); + if self.eat(&token::Question) { + // `expr?` + e = self.mk_expr(lo.to(self.prev_span), ExprKind::Try(e), AttrVec::new()); + continue; } - - // expr.f if self.eat(&token::Dot) { - match self.token.kind { - token::Ident(..) => { - e = self.parse_dot_suffix(e, lo)?; - } - token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { - let span = self.token.span; - self.bump(); - let field = ExprKind::Field(e, Ident::new(symbol, span)); - e = self.mk_expr(lo.to(span), field, AttrVec::new()); - - self.expect_no_suffix(span, "a tuple index", suffix); - } - token::Literal(token::Lit { kind: token::Float, symbol, .. }) => { - self.bump(); - let fstr = symbol.as_str(); - let msg = format!("unexpected token: `{}`", symbol); - let mut err = self.diagnostic().struct_span_err(self.prev_span, &msg); - err.span_label(self.prev_span, "unexpected token"); - if fstr.chars().all(|x| "0123456789.".contains(x)) { - let float = match fstr.parse::<f64>().ok() { - Some(f) => f, - None => continue, - }; - let sugg = pprust::to_string(|s| { - s.popen(); - s.print_expr(&e); - s.s.word("."); - s.print_usize(float.trunc() as usize); - s.pclose(); - s.s.word("."); - s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) - }); - err.span_suggestion( - lo.to(self.prev_span), - "try parenthesizing the first index", - sugg, - Applicability::MachineApplicable, - ); - } - return Err(err); - } - _ => { - // FIXME Could factor this out into non_fatal_unexpected or something. - let actual = self.this_token_to_string(); - self.span_err(self.token.span, &format!("unexpected token: `{}`", actual)); - } - } + // expr.f + e = self.parse_dot_suffix_expr(lo, e)?; continue; } if self.expr_is_complete(&e) { - break; + return Ok(e); } - match self.token.kind { - // expr(...) - token::OpenDelim(token::Paren) => { - let seq = self.parse_paren_expr_seq().map(|es| { - let nd = self.mk_call(e, es); - let hi = self.prev_span; - self.mk_expr(lo.to(hi), nd, AttrVec::new()) - }); - e = self.recover_seq_parse_error(token::Paren, lo, seq); - } - - // expr[...] - // Could be either an index expression or a slicing expression. - token::OpenDelim(token::Bracket) => { - self.bump(); - let ix = self.parse_expr()?; - hi = self.token.span; - self.expect(&token::CloseDelim(token::Bracket))?; - let index = self.mk_index(e, ix); - e = self.mk_expr(lo.to(hi), index, AttrVec::new()) - } + e = match self.token.kind { + token::OpenDelim(token::Paren) => self.parse_fn_call_expr(lo, e), + token::OpenDelim(token::Bracket) => self.parse_index_expr(lo, e)?, _ => return Ok(e), } } - return Ok(e); + } + + fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> { + match self.token.kind { + token::Ident(..) => self.parse_dot_suffix(base, lo), + token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { + Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix)) + } + token::Literal(token::Lit { kind: token::Float, symbol, .. }) => { + self.recover_field_access_by_float_lit(lo, base, symbol) + } + _ => { + self.error_unexpected_after_dot(); + Ok(base) + } + } + } + + fn error_unexpected_after_dot(&self) { + // FIXME Could factor this out into non_fatal_unexpected or something. + let actual = pprust::token_to_string(&self.token); + self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit(); + } + + fn recover_field_access_by_float_lit( + &mut self, + lo: Span, + base: P<Expr>, + sym: Symbol, + ) -> PResult<'a, P<Expr>> { + self.bump(); + + let fstr = sym.as_str(); + let msg = format!("unexpected token: `{}`", sym); + + let mut err = self.struct_span_err(self.prev_span, &msg); + err.span_label(self.prev_span, "unexpected token"); + + if fstr.chars().all(|x| "0123456789.".contains(x)) { + let float = match fstr.parse::<f64>() { + Ok(f) => f, + Err(_) => { + err.emit(); + return Ok(base); + } + }; + let sugg = pprust::to_string(|s| { + s.popen(); + s.print_expr(&base); + s.s.word("."); + s.print_usize(float.trunc() as usize); + s.pclose(); + s.s.word("."); + s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) + }); + err.span_suggestion( + lo.to(self.prev_span), + "try parenthesizing the first index", + sugg, + Applicability::MachineApplicable, + ); + } + Err(err) + } + + fn parse_tuple_field_access_expr( + &mut self, + lo: Span, + base: P<Expr>, + field: Symbol, + suffix: Option<Symbol>, + ) -> P<Expr> { + let span = self.token.span; + self.bump(); + let field = ExprKind::Field(base, Ident::new(field, span)); + self.expect_no_suffix(span, "a tuple index", suffix); + self.mk_expr(lo.to(span), field, AttrVec::new()) + } + + /// Parse a function call expression, `expr(...)`. + fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> { + let seq = self.parse_paren_expr_seq().map(|args| { + self.mk_expr(lo.to(self.prev_span), self.mk_call(fun, args), AttrVec::new()) + }); + self.recover_seq_parse_error(token::Paren, lo, seq) + } + + /// Parse an indexing expression `expr[...]`. + fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> { + self.bump(); // `[` + let index = self.parse_expr()?; + self.expect(&token::CloseDelim(token::Bracket))?; + Ok(self.mk_expr(lo.to(self.prev_span), self.mk_index(base, index), AttrVec::new())) } /// Assuming we have just parsed `.`, continue parsing into an expression. @@ -794,25 +812,22 @@ impl<'a> Parser<'a> { let segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); - Ok(match self.token.kind { - token::OpenDelim(token::Paren) => { - // Method call `expr.f()` - let mut args = self.parse_paren_expr_seq()?; - args.insert(0, self_arg); + if self.check(&token::OpenDelim(token::Paren)) { + // Method call `expr.f()` + let mut args = self.parse_paren_expr_seq()?; + args.insert(0, self_arg); - let span = lo.to(self.prev_span); - self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new()) + let span = lo.to(self.prev_span); + Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new())) + } else { + // Field access `expr.f` + if let Some(args) = segment.args { + self.span_err(args.span(), "field expressions may not have generic arguments"); } - _ => { - // Field access `expr.f` - if let Some(args) = segment.args { - self.span_err(args.span(), "field expressions may not have generic arguments"); - } - let span = lo.to(self.prev_span); - self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new()) - } - }) + let span = lo.to(self.prev_span); + Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new())) + } } /// At the bottom (top?) of the precedence hierarchy, @@ -1117,7 +1132,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { self.parse_opt_lit().ok_or_else(|| { - let msg = format!("unexpected token: {}", self.this_token_descr()); + let msg = format!("unexpected token: {}", super::token_descr(&self.token)); self.span_fatal(self.token.span, &msg) }) } @@ -1143,14 +1158,7 @@ impl<'a> Parser<'a> { }); if let Some(token) = &recovered { self.bump(); - self.struct_span_err(token.span, "float literals must have an integer part") - .span_suggestion( - token.span, - "must have an integer part", - pprust::token_to_string(token), - Applicability::MachineApplicable, - ) - .emit(); + self.error_float_lits_must_have_int_part(&token); } } @@ -1179,6 +1187,17 @@ impl<'a> Parser<'a> { } } + fn error_float_lits_must_have_int_part(&self, token: &Token) { + self.struct_span_err(token.span, "float literals must have an integer part") + .span_suggestion( + token.span, + "must have an integer part", + pprust::token_to_string(token), + Applicability::MachineApplicable, + ) + .emit(); + } + fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { @@ -1282,17 +1301,13 @@ impl<'a> Parser<'a> { pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { maybe_whole_expr!(self); - let minus_lo = self.token.span; - let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.token.span; - let literal = self.parse_lit()?; - let hi = self.prev_span; - let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), AttrVec::new()); + let minus_present = self.eat(&token::BinOp(token::Minus)); + let lit = self.parse_lit()?; + let expr = self.mk_expr(lit.span, ExprKind::Lit(lit), AttrVec::new()); if minus_present { - let minus_hi = self.prev_span; - let unary = self.mk_unary(UnOp::Neg, expr); - Ok(self.mk_expr(minus_lo.to(minus_hi), unary, AttrVec::new())) + Ok(self.mk_expr(lo.to(self.prev_span), self.mk_unary(UnOp::Neg, expr), AttrVec::new())) } else { Ok(expr) } @@ -1362,26 +1377,24 @@ impl<'a> Parser<'a> { /// Parses the `|arg, arg|` header of a closure. fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> { - let inputs_captures = { - if self.eat(&token::OrOr) { - Vec::new() - } else { - self.expect(&token::BinOp(token::Or))?; - let args = self - .parse_seq_to_before_tokens( - &[&token::BinOp(token::Or), &token::OrOr], - SeqSep::trailing_allowed(token::Comma), - TokenExpectType::NoExpect, - |p| p.parse_fn_block_param(), - )? - .0; - self.expect_or()?; - args - } + let inputs = if self.eat(&token::OrOr) { + Vec::new() + } else { + self.expect(&token::BinOp(token::Or))?; + let args = self + .parse_seq_to_before_tokens( + &[&token::BinOp(token::Or), &token::OrOr], + SeqSep::trailing_allowed(token::Comma), + TokenExpectType::NoExpect, + |p| p.parse_fn_block_param(), + )? + .0; + self.expect_or()?; + args }; let output = self.parse_ret_ty(true, true)?; - Ok(P(FnDecl { inputs: inputs_captures, output })) + Ok(P(FnDecl { inputs, output })) } /// Parses a parameter in a closure header (e.g., `|arg, arg|`). @@ -1389,17 +1402,16 @@ impl<'a> Parser<'a> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; let pat = self.parse_pat(PARAM_EXPECTED)?; - let t = if self.eat(&token::Colon) { + let ty = if self.eat(&token::Colon) { self.parse_ty()? } else { - P(Ty { id: DUMMY_NODE_ID, kind: TyKind::Infer, span: self.prev_span }) + self.mk_ty(self.prev_span, TyKind::Infer) }; - let span = lo.to(self.token.span); Ok(Param { attrs: attrs.into(), - ty: t, + ty, pat, - span, + span: lo.to(self.token.span), id: DUMMY_NODE_ID, is_placeholder: false, }) @@ -1414,28 +1426,29 @@ impl<'a> Parser<'a> { // verify that the last statement is either an implicit return (no `;`) or an explicit // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. - if self.eat_keyword(kw::Else) || !cond.returns() { - let sp = self.sess.source_map().next_point(lo); - let mut err = - self.diagnostic().struct_span_err(sp, "missing condition for `if` expression"); - err.span_label(sp, "expected if condition here"); - return Err(err); - } - let not_block = self.token != token::OpenDelim(token::Brace); - let thn = self.parse_block().map_err(|mut err| { - if not_block { - err.span_label(lo, "this `if` statement has a condition, but no block"); - } - err - })?; - let mut els: Option<P<Expr>> = None; - let mut hi = thn.span; - if self.eat_keyword(kw::Else) { - let elexpr = self.parse_else_expr()?; - hi = elexpr.span; - els = Some(elexpr); - } - Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) + let thn = if self.eat_keyword(kw::Else) || !cond.returns() { + self.error_missing_if_cond(lo, cond.span) + } else { + let not_block = self.token != token::OpenDelim(token::Brace); + self.parse_block().map_err(|mut err| { + if not_block { + err.span_label(lo, "this `if` expression has a condition, but no block"); + } + err + })? + }; + let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None }; + Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::If(cond, thn, els), attrs)) + } + + fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> { + let sp = self.sess.source_map().next_point(lo); + self.struct_span_err(sp, "missing condition for `if` expression") + .span_label(sp, "expected if condition here") + .emit(); + let expr = self.mk_expr_err(span); + let stmt = self.mk_stmt(span, ast::StmtKind::Expr(expr)); + self.mk_block(vec![stmt], BlockCheckMode::Default, span) } /// Parses the condition of a `if` or `while` expression. @@ -1467,22 +1480,20 @@ impl<'a> Parser<'a> { /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { if self.eat_keyword(kw::If) { - return self.parse_if_expr(AttrVec::new()); + self.parse_if_expr(AttrVec::new()) } else { let blk = self.parse_block()?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())); + Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())) } } - /// Parses a `for ... in` expression (`for` token already eaten). + /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). fn parse_for_expr( &mut self, opt_label: Option<Label>, - span_lo: Span, + lo: Span, mut attrs: AttrVec, ) -> PResult<'a, P<Expr>> { - // Parse: `for <src_pat> in <src_expr> <src_loop_block>` - // Record whether we are about to parse `for (`. // This is used below for recovery in case of `for ( $stuff ) $block` // in which case we will suggest `for $stuff $block`. @@ -1493,19 +1504,9 @@ impl<'a> Parser<'a> { let pat = self.parse_top_pat(GateOr::Yes)?; if !self.eat_keyword(kw::In) { - let in_span = self.prev_span.between(self.token.span); - self.struct_span_err(in_span, "missing `in` in `for` loop") - .span_suggestion_short( - in_span, - "try adding `in` here", - " in ".into(), - // has been misleading, at least in the past (closed Issue #48492) - Applicability::MaybeIncorrect, - ) - .emit(); + self.error_missing_in_for_loop(); } - let in_span = self.prev_span; - self.check_for_for_in_in_typo(in_span); + self.check_for_for_in_in_typo(self.prev_span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); @@ -1513,52 +1514,61 @@ impl<'a> Parser<'a> { let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - let hi = self.prev_span; - Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs)) + let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); + Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs)) + } + + fn error_missing_in_for_loop(&self) { + let in_span = self.prev_span.between(self.token.span); + self.struct_span_err(in_span, "missing `in` in `for` loop") + .span_suggestion_short( + in_span, + "try adding `in` here", + " in ".into(), + // Has been misleading, at least in the past (closed Issue #48492). + Applicability::MaybeIncorrect, + ) + .emit(); } /// Parses a `while` or `while let` expression (`while` token already eaten). fn parse_while_expr( &mut self, opt_label: Option<Label>, - span_lo: Span, + lo: Span, mut attrs: AttrVec, ) -> PResult<'a, P<Expr>> { let cond = self.parse_cond_expr()?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - let span = span_lo.to(body.span); - Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs)) + Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::While(cond, body, opt_label), attrs)) } /// Parses `loop { ... }` (`loop` token already eaten). fn parse_loop_expr( &mut self, opt_label: Option<Label>, - span_lo: Span, + lo: Span, mut attrs: AttrVec, ) -> PResult<'a, P<Expr>> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - let span = span_lo.to(body.span); - Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs)) + Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::Loop(body, opt_label), attrs)) } fn eat_label(&mut self) -> Option<Label> { - if let Some(ident) = self.token.lifetime() { + self.token.lifetime().map(|ident| { let span = self.token.span; self.bump(); - Some(Label { ident: Ident::new(ident.name, span) }) - } else { - None - } + Label { ident: Ident::new(ident.name, span) } + }) } /// Parses a `match ... { ... }` expression (`match` token already eaten). fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> { let match_span = self.prev_span; let lo = self.prev_span; - let discriminant = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; + let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { if self.token == token::Semi { e.span_suggestion_short( @@ -1584,13 +1594,13 @@ impl<'a> Parser<'a> { if self.token == token::CloseDelim(token::Brace) { self.bump(); } - return Ok(self.mk_expr(span, ExprKind::Match(discriminant, arms), attrs)); + return Ok(self.mk_expr(span, ExprKind::Match(scrutinee, arms), attrs)); } } } let hi = self.token.span; self.bump(); - return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(discriminant, arms), attrs)); + return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)); } pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { @@ -1699,16 +1709,13 @@ impl<'a> Parser<'a> { /// Parses an `async move? {...}` expression. fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> { - let span_lo = self.token.span; + let lo = self.token.span; self.expect_keyword(kw::Async)?; let capture_clause = self.parse_capture_clause(); let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - Ok(self.mk_expr( - span_lo.to(body.span), - ExprKind::Async(capture_clause, DUMMY_NODE_ID, body), - attrs, - )) + let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body); + Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs)) } fn is_async_block(&self) -> bool { @@ -1723,6 +1730,21 @@ impl<'a> Parser<'a> { )) } + fn is_certainly_not_a_block(&self) -> bool { + self.look_ahead(1, |t| t.is_ident()) + && ( + // `{ ident, ` cannot start a block. + self.look_ahead(2, |t| t == &token::Comma) + || self.look_ahead(2, |t| t == &token::Colon) + && ( + // `{ ident: token, ` cannot start a block. + self.look_ahead(4, |t| t == &token::Comma) || + // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`. + self.look_ahead(3, |t| !t.can_begin_type()) + ) + ) + } + fn maybe_parse_struct_expr( &mut self, lo: Span, @@ -1730,41 +1752,27 @@ impl<'a> Parser<'a> { attrs: &AttrVec, ) -> Option<PResult<'a, P<Expr>>> { let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); - let certainly_not_a_block = || { - self.look_ahead(1, |t| t.is_ident()) - && ( - // `{ ident, ` cannot start a block. - self.look_ahead(2, |t| t == &token::Comma) - || self.look_ahead(2, |t| t == &token::Colon) - && ( - // `{ ident: token, ` cannot start a block. - self.look_ahead(4, |t| t == &token::Comma) || - // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`. - self.look_ahead(3, |t| !t.can_begin_type()) - ) - ) - }; - - if struct_allowed || certainly_not_a_block() { + if struct_allowed || self.is_certainly_not_a_block() { // This is a struct literal, but we don't can't accept them here. let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone()); if let (Ok(expr), false) = (&expr, struct_allowed) { - self.struct_span_err(expr.span, "struct literals are not allowed here") - .multipart_suggestion( - "surround the struct literal with parentheses", - vec![ - (lo.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); + self.error_struct_lit_not_allowed_here(lo, expr.span); } return Some(expr); } None } + fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) { + self.struct_span_err(sp, "struct literals are not allowed here") + .multipart_suggestion( + "surround the struct literal with parentheses", + vec![(lo.shrink_to_lo(), "(".to_string()), (sp.shrink_to_hi(), ")".to_string())], + Applicability::MachineApplicable, + ) + .emit(); + } + pub(super) fn parse_struct_expr( &mut self, lo: Span, @@ -1782,50 +1790,19 @@ impl<'a> Parser<'a> { if self.eat(&token::DotDot) { let exp_span = self.prev_span; match self.parse_expr() { - Ok(e) => { - base = Some(e); - } + Ok(e) => base = Some(e), Err(mut e) => { e.emit(); self.recover_stmt(); } } - if self.token == token::Comma { - self.struct_span_err( - exp_span.to(self.prev_span), - "cannot use a comma after the base struct", - ) - .span_suggestion_short( - self.token.span, - "remove this comma", - String::new(), - Applicability::MachineApplicable, - ) - .note("the base struct must always be the last field") - .emit(); - self.recover_stmt(); - } + self.recover_struct_comma_after_dotdot(exp_span); break; } - let mut recovery_field = None; - if let token::Ident(name, _) = self.token.kind { - if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) { - // Use in case of error after field-looking code: `S { foo: () with a }`. - recovery_field = Some(ast::Field { - ident: Ident::new(name, self.token.span), - span: self.token.span, - expr: self.mk_expr(self.token.span, ExprKind::Err, AttrVec::new()), - is_shorthand: false, - attrs: AttrVec::new(), - id: DUMMY_NODE_ID, - is_placeholder: false, - }); - } - } - let mut parsed_field = None; - match self.parse_field() { - Ok(f) => parsed_field = Some(f), + let recovery_field = self.find_struct_error_after_field_looking_code(); + let parsed_field = match self.parse_field() { + Ok(f) => Some(f), Err(mut e) => { e.span_label(struct_sp, "while parsing this struct"); e.emit(); @@ -1839,8 +1816,9 @@ impl<'a> Parser<'a> { break; } } + None } - } + }; match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) { Ok(_) => { @@ -1863,53 +1841,91 @@ impl<'a> Parser<'a> { let span = lo.to(self.token.span); self.expect(&token::CloseDelim(token::Brace))?; - return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs)); + Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs)) + } + + /// Use in case of error after field-looking code: `S { foo: () with a }`. + fn find_struct_error_after_field_looking_code(&self) -> Option<Field> { + if let token::Ident(name, _) = self.token.kind { + if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) { + let span = self.token.span; + return Some(ast::Field { + ident: Ident::new(name, span), + span, + expr: self.mk_expr_err(span), + is_shorthand: false, + attrs: AttrVec::new(), + id: DUMMY_NODE_ID, + is_placeholder: false, + }); + } + } + None + } + + fn recover_struct_comma_after_dotdot(&mut self, span: Span) { + if self.token != token::Comma { + return; + } + self.struct_span_err(span.to(self.prev_span), "cannot use a comma after the base struct") + .span_suggestion_short( + self.token.span, + "remove this comma", + String::new(), + Applicability::MachineApplicable, + ) + .note("the base struct must always be the last field") + .emit(); + self.recover_stmt(); } /// Parses `ident (COLON expr)?`. fn parse_field(&mut self) -> PResult<'a, Field> { - let attrs = self.parse_outer_attributes()?; + let attrs = self.parse_outer_attributes()?.into(); let lo = self.token.span; // Check if a colon exists one ahead. This means we're parsing a fieldname. - let (fieldname, expr, is_shorthand) = - if self.look_ahead(1, |t| t == &token::Colon || t == &token::Eq) { - let fieldname = self.parse_field_name()?; - - // Check for an equals token. This means the source incorrectly attempts to - // initialize a field with an eq rather than a colon. - if self.token == token::Eq { - self.diagnostic() - .struct_span_err(self.token.span, "expected `:`, found `=`") - .span_suggestion( - fieldname.span.shrink_to_hi().to(self.token.span), - "replace equals symbol with a colon", - ":".to_string(), - Applicability::MachineApplicable, - ) - .emit(); - } - self.bump(); // `:` - (fieldname, self.parse_expr()?, false) - } else { - let fieldname = self.parse_ident_common(false)?; - - // Mimic `x: x` for the `x` field shorthand. - let path = ast::Path::from_ident(fieldname); - let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), AttrVec::new()); - (fieldname, expr, true) - }; + let is_shorthand = !self.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); + let (ident, expr) = if is_shorthand { + // Mimic `x: x` for the `x` field shorthand. + let ident = self.parse_ident_common(false)?; + let path = ast::Path::from_ident(ident); + (ident, self.mk_expr(ident.span, ExprKind::Path(None, path), AttrVec::new())) + } else { + let ident = self.parse_field_name()?; + self.error_on_eq_field_init(ident); + self.bump(); // `:` + (ident, self.parse_expr()?) + }; Ok(ast::Field { - ident: fieldname, + ident, span: lo.to(expr.span), expr, is_shorthand, - attrs: attrs.into(), + attrs, id: DUMMY_NODE_ID, is_placeholder: false, }) } + /// Check for `=`. This means the source incorrectly attempts to + /// initialize a field with an eq rather than a colon. + fn error_on_eq_field_init(&self, field_name: Ident) { + if self.token != token::Eq { + return; + } + + self.diagnostic() + .struct_span_err(self.token.span, "expected `:`, found `=`") + .span_suggestion( + field_name.span.shrink_to_hi().to(self.token.span), + "replace equals symbol with a colon", + ":".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + } + fn err_dotdotdot_syntax(&self, span: Span) { self.struct_span_err(span, "unexpected token: `...`") .span_suggestion( diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 8f8e5fbb78765..343c6667d47d5 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1348,7 +1348,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; body } else { - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); let mut err = self.fatal(&format!( "expected `where`, `{{`, `(`, or `;` after struct name, found {}", token_str @@ -1374,7 +1374,7 @@ impl<'a> Parser<'a> { let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) } else { - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); let mut err = self .fatal(&format!("expected `where` or `{{` after union name, found {}", token_str)); err.span_label(self.token.span, "expected `where` or `{` after union name"); @@ -1411,7 +1411,7 @@ impl<'a> Parser<'a> { } self.eat(&token::CloseDelim(token::Brace)); } else { - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); let mut err = self.fatal(&format!( "expected `where`, or `{{` after struct name, found {}", token_str @@ -1498,7 +1498,7 @@ impl<'a> Parser<'a> { let sp = self.sess.source_map().next_point(self.prev_span); let mut err = self.struct_span_err( sp, - &format!("expected `,`, or `}}`, found {}", self.this_token_descr()), + &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), ); if self.token.is_ident() { // This is likely another field; emit the diagnostic and keep going diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 97084482025bb..103bbe5dd763e 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -354,6 +354,24 @@ pub enum FollowedByType { No, } +fn token_descr_opt(token: &Token) -> Option<&'static str> { + Some(match token.kind { + _ if token.is_special_ident() => "reserved identifier", + _ if token.is_used_keyword() => "keyword", + _ if token.is_unused_keyword() => "reserved keyword", + token::DocComment(..) => "doc comment", + _ => return None, + }) +} + +pub(super) fn token_descr(token: &Token) -> String { + let token_str = pprust::token_to_string(token); + match token_descr_opt(token) { + Some(prefix) => format!("{} `{}`", prefix, token_str), + _ => format!("`{}`", token_str), + } +} + impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, @@ -422,29 +440,6 @@ impl<'a> Parser<'a> { next } - /// Converts the current token to a string using `self`'s reader. - pub fn this_token_to_string(&self) -> String { - pprust::token_to_string(&self.token) - } - - fn token_descr(&self) -> Option<&'static str> { - Some(match &self.token.kind { - _ if self.token.is_special_ident() => "reserved identifier", - _ if self.token.is_used_keyword() => "keyword", - _ if self.token.is_unused_keyword() => "reserved keyword", - token::DocComment(..) => "doc comment", - _ => return None, - }) - } - - pub(super) fn this_token_descr(&self) -> String { - if let Some(prefix) = self.token_descr() { - format!("{} `{}`", prefix, self.this_token_to_string()) - } else { - format!("`{}`", self.this_token_to_string()) - } - } - crate fn unexpected<T>(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index eaeb3af4ca2a2..3f54e0b6de031 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -79,7 +79,7 @@ impl<'a> Parser<'a> { } if !self.eat(term) { - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); if !self.maybe_consume_incorrect_semicolon(&items) { let mut err = self.fatal(&format!("expected item, found {}", token_str)); err.span_label(self.token.span, "expected item"); diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 1540e6d7c053f..d2288b27a0c40 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -671,7 +671,7 @@ impl<'a> Parser<'a> { err.cancel(); let expected = expected.unwrap_or("pattern"); - let msg = format!("expected {}, found {}", expected, self.this_token_descr()); + let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token)); let mut err = self.fatal(&msg); err.span_label(self.token.span, format!("expected {}", expected)); @@ -876,7 +876,7 @@ impl<'a> Parser<'a> { etc_span = Some(etc_sp); break; } - let token_str = self.this_token_descr(); + let token_str = super::token_descr(&self.token); let mut err = self.fatal(&format!("expected `}}`, found {}", token_str)); err.span_label(self.token.span, "expected `}`"); diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index ed5649310e3fd..8270da6c0234f 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -323,7 +323,7 @@ impl<'a> Parser<'a> { fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> { let sp = self.token.span; - let tok = self.this_token_descr(); + let tok = super::token_descr(&self.token); let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok)); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; @@ -411,7 +411,7 @@ impl<'a> Parser<'a> { continue; }; } - Ok(P(ast::Block { stmts, id: DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span) })) + Ok(self.mk_block(stmts, s, lo.to(self.prev_span))) } /// Parses a statement, including the trailing semicolon. @@ -463,7 +463,7 @@ impl<'a> Parser<'a> { fn warn_missing_semicolon(&self) { self.diagnostic() .struct_span_warn(self.token.span, { - &format!("expected `;`, found {}", self.this_token_descr()) + &format!("expected `;`, found {}", super::token_descr(&self.token)) }) .note({ "this was erroneously allowed and will become a hard error in a future release" @@ -471,7 +471,11 @@ impl<'a> Parser<'a> { .emit(); } - fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { + pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> { + P(Block { stmts, id: DUMMY_NODE_ID, rules, span }) + } + + pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { Stmt { id: DUMMY_NODE_ID, kind, span } } } diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index fe3db358accde..049c077c3cea3 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -135,7 +135,7 @@ impl<'a> Parser<'a> { TyKind::Err } } else { - let msg = format!("expected type, found {}", self.this_token_descr()); + let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.struct_span_err(self.token.span, &msg); err.span_label(self.token.span, "expected type"); self.maybe_annotate_with_ascription(&mut err, true); diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index b9b449d177915..4df51ff41f3f6 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -904,10 +904,8 @@ pub fn ensure_complete_parse<'a>( span: Span, ) { if this.token != token::Eof { - let msg = format!( - "macro expansion ignores token `{}` and any following", - this.this_token_to_string() - ); + let token = pprust::token_to_string(&this.token); + let msg = format!("macro expansion ignores token `{}` and any following", token); // Avoid emitting backtrace info twice. let def_site_span = this.token.span.with_ctxt(SyntaxContext::root()); let mut err = this.struct_span_err(def_site_span, &msg); diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 4f46252f8be61..fccc36e2ea809 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -133,15 +133,17 @@ pub fn expand_include<'cx>( while self.p.token != token::Eof { match panictry!(self.p.parse_item()) { Some(item) => ret.push(item), - None => self - .p - .sess - .span_diagnostic - .span_fatal( - self.p.token.span, - &format!("expected item, found `{}`", self.p.this_token_to_string()), - ) - .raise(), + None => { + let token = pprust::token_to_string(&self.p.token); + self.p + .sess + .span_diagnostic + .span_fatal( + self.p.token.span, + &format!("expected item, found `{}`", token), + ) + .raise(); + } } } Some(ret) diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index f5edbe2a3af53..8025886a9eb46 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -26,7 +26,7 @@ error: expected `{`, found `;` --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31 | LL | if not // lack of braces is [sic] - | -- this `if` statement has a condition, but no block + | -- this `if` expression has a condition, but no block LL | println!("Then when?"); | ^ | | diff --git a/src/test/ui/if/if-let.stderr b/src/test/ui/if/if-let.stderr index 83ab234cf04ea..570a64e999cd0 100644 --- a/src/test/ui/if/if-let.stderr +++ b/src/test/ui/if/if-let.stderr @@ -2,7 +2,7 @@ warning: irrefutable if-let pattern --> $DIR/if-let.rs:6:13 | LL | if let $p = $e $b - | ^^ + | ^^^^^^^^^^^^^^^^^ ... LL | / foo!(a, 1, { LL | | println!("irrefutable pattern"); @@ -15,7 +15,7 @@ warning: irrefutable if-let pattern --> $DIR/if-let.rs:6:13 | LL | if let $p = $e $b - | ^^ + | ^^^^^^^^^^^^^^^^^ ... LL | / bar!(a, 1, { LL | | println!("irrefutable pattern"); diff --git a/src/test/ui/if/if-without-block.rs b/src/test/ui/if/if-without-block.rs index 3dde0ed7c7188..8a4c59f32613d 100644 --- a/src/test/ui/if/if-without-block.rs +++ b/src/test/ui/if/if-without-block.rs @@ -1,7 +1,7 @@ fn main() { let n = 1; if 5 == { - //~^ NOTE this `if` statement has a condition, but no block + //~^ NOTE this `if` expression has a condition, but no block println!("five"); } } diff --git a/src/test/ui/if/if-without-block.stderr b/src/test/ui/if/if-without-block.stderr index 1e45045adece8..34df8e3d77946 100644 --- a/src/test/ui/if/if-without-block.stderr +++ b/src/test/ui/if/if-without-block.stderr @@ -2,7 +2,7 @@ error: expected `{`, found `}` --> $DIR/if-without-block.rs:7:1 | LL | if 5 == { - | -- this `if` statement has a condition, but no block + | -- this `if` expression has a condition, but no block ... LL | } | ^ expected `{` diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/issues/issue-13483.rs index cb53523b3b04d..a2fd9264b1530 100644 --- a/src/test/ui/issues/issue-13483.rs +++ b/src/test/ui/issues/issue-13483.rs @@ -1,6 +1,7 @@ fn main() { if true { } else if { //~ ERROR missing condition + //~^ ERROR mismatched types } else { } } @@ -8,6 +9,7 @@ fn main() { fn foo() { if true { } else if { //~ ERROR missing condition + //~^ ERROR mismatched types } bar(); } diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr index df9f1dd0115db..5fd05b18ce06e 100644 --- a/src/test/ui/issues/issue-13483.stderr +++ b/src/test/ui/issues/issue-13483.stderr @@ -5,10 +5,29 @@ LL | } else if { | ^ expected if condition here error: missing condition for `if` expression - --> $DIR/issue-13483.rs:10:14 + --> $DIR/issue-13483.rs:11:14 | LL | } else if { | ^ expected if condition here -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-13483.rs:3:15 + | +LL | } else if { + | _______________^ +LL | | +LL | | } else { + | |_____^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/issue-13483.rs:11:15 + | +LL | } else if { + | _______________^ +LL | | +LL | | } + | |_____^ expected `bool`, found `()` + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr index 47aa8e17a304b..11b145d6e0dc9 100644 --- a/src/test/ui/issues/issue-39848.stderr +++ b/src/test/ui/issues/issue-39848.stderr @@ -4,7 +4,7 @@ error: expected `{`, found `foo` LL | if $tgt.has_$field() {} | -- -- help: try placing this code inside a block: `{ () }` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block ... LL | get_opt!(bar, foo); | ^^^ expected `{` diff --git a/src/test/ui/issues/issue-51602.stderr b/src/test/ui/issues/issue-51602.stderr index 1ad69c0191b53..d800890bca38d 100644 --- a/src/test/ui/issues/issue-51602.stderr +++ b/src/test/ui/issues/issue-51602.stderr @@ -4,7 +4,7 @@ error: expected `{`, found keyword `in` LL | if i in 1..10 { | -- ^^ expected `{` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: aborting due to previous error diff --git a/src/test/ui/issues/issue-61858.stderr b/src/test/ui/issues/issue-61858.stderr index ea2ec3d013f59..8b95d9c6ae48b 100644 --- a/src/test/ui/issues/issue-61858.stderr +++ b/src/test/ui/issues/issue-61858.stderr @@ -4,7 +4,7 @@ error: expected `{`, found `)` LL | (if foobar) | -- ^ expected `{` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: aborting due to previous error diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/issues/issue-62554.stderr index 87aaa03661321..d59546e23839a 100644 --- a/src/test/ui/issues/issue-62554.stderr +++ b/src/test/ui/issues/issue-62554.stderr @@ -17,7 +17,7 @@ error: expected `{`, found `macro_rules` LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { | -- ^^^^^^^^^^^ expected `{` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block | help: try placing this code inside a block | diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr index 0036f0f1db0fb..46b53c65b4817 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.stderr +++ b/src/test/ui/label/label_break_value_illegal_uses.stderr @@ -12,7 +12,7 @@ LL | if true 'b: {} | | | | | expected `{` | | help: try placing this code inside a block: `{ 'b: {} }` - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: expected `{`, found `'b` --> $DIR/label_break_value_illegal_uses.rs:14:21 diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr index ee86a3241e822..0f635817bf462 100644 --- a/src/test/ui/missing/missing-block-hint.stderr +++ b/src/test/ui/missing/missing-block-hint.stderr @@ -4,13 +4,13 @@ error: expected `{`, found `=>` LL | if (foo) => {} | -- ^^ expected `{` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: expected `{`, found `bar` --> $DIR/missing-block-hint.rs:7:13 | LL | if (foo) - | -- this `if` statement has a condition, but no block + | -- this `if` expression has a condition, but no block LL | bar; | ^^^- | | diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs deleted file mode 100644 index e5ac59ae46301..0000000000000 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } -//~^ ERROR unexpected token: `#` diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr deleted file mode 100644 index ca1043250ba78..0000000000000 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad-2.rs:1:34 - | -LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs deleted file mode 100644 index 7dc71af52f4d9..0000000000000 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } -//~^ ERROR unexpected token: `#` diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr deleted file mode 100644 index ab9366d042a2c..0000000000000 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad-3.rs:1:34 - | -LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs index ef10010ed0e61..6e1d72cd2f6e2 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs @@ -101,6 +101,13 @@ fn main() {} //~^ ERROR `X..=` range patterns are not supported //~| ERROR expected one of `=>`, `if`, or `|`, found `#` +#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } +//~^ ERROR unexpected token: `#` +//~| ERROR expected one of `.` +#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } +//~^ ERROR unexpected token: `#` +//~| ERROR expected one of `.` + // make sure we don't catch this bug again... #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } //~^ ERROR expected statement after outer attribute diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index 9a0d3176714fa..371d3f575a418 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -149,7 +149,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` | | | | | expected `{` - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:43:38 @@ -202,7 +202,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` | | | | | expected `{` - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:56:51 @@ -225,7 +225,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` | | | | | expected `{` - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:62:46 @@ -278,7 +278,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {} | -- ^ --- help: try placing this code inside a block: `{ {}; }` | | | | | expected `{` - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:75:67 @@ -380,11 +380,35 @@ error: expected one of `=>`, `if`, or `|`, found `#` LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^ expected one of `=>`, `if`, or `|` +error: unexpected token: `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:104:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } + | ^ + +error: expected one of `.`, `;`, `?`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:104:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } + | ^ expected one of `.`, `;`, `?`, or an operator + +error: unexpected token: `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:107:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } + | ^ + +error: expected one of `.`, `;`, `?`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:107:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } + | ^ expected one of `.`, `;`, `?`, or an operator + error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:105:44 + --> $DIR/attr-stmt-expr-attr-bad.rs:112:44 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } | ^ -error: aborting due to 52 previous errors +error: aborting due to 56 previous errors diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr index 6bcb77385d7d5..a720dd68bd037 100644 --- a/src/test/ui/parser/doc-comment-in-if-statement.stderr +++ b/src/test/ui/parser/doc-comment-in-if-statement.stderr @@ -4,7 +4,7 @@ error: expected `{`, found doc comment `/*!*/` LL | if true /*!*/ {} | -- ^^^^^ expected `{` | | - | this `if` statement has a condition, but no block + | this `if` expression has a condition, but no block error: aborting due to previous error diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr index 172874ad5fc5c..09f0d641de060 100644 --- a/src/test/ui/while-let.stderr +++ b/src/test/ui/while-let.stderr @@ -2,7 +2,7 @@ warning: irrefutable while-let pattern --> $DIR/while-let.rs:7:13 | LL | while let $p = $e $b - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ ... LL | / foo!(_a, 1, { LL | | println!("irrefutable pattern"); @@ -15,7 +15,7 @@ warning: irrefutable while-let pattern --> $DIR/while-let.rs:7:13 | LL | while let $p = $e $b - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ ... LL | / bar!(_a, 1, { LL | | println!("irrefutable pattern");