+use super::diagnostics::SnapshotParser;
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
- AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
+ SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
use crate::maybe_recover_from_interpolated_ty_qpath;
use ast::token::DelimToken;
&mut self,
cast_expr: P<Expr>,
) -> PResult<'a, P<Expr>> {
+ let span = cast_expr.span;
+ let maybe_ascription_span = if let ExprKind::Type(ascripted_expr, _) = &cast_expr.kind {
+ Some(ascripted_expr.span.shrink_to_hi().with_hi(span.hi()))
+ } else {
+ None
+ };
+
// Save the memory location of expr before parsing any following postfix operators.
// This will be compared with the memory location of the output expression.
// If they different we can assume we parsed another expression because the existing expression is not reallocated.
let addr_before = &*cast_expr as *const _ as usize;
- let span = cast_expr.span;
let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
let changed = addr_before != &*with_postfix as *const _ as usize;
}
);
let mut err = self.struct_span_err(span, &msg);
- // If type ascription is "likely an error", the user will already be getting a useful
- // help message, and doesn't need a second.
- if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) {
- self.maybe_annotate_with_ascription(&mut err, false);
- } else {
+
+ let suggest_parens = |err: &mut DiagnosticBuilder<'_, _>| {
let suggestions = vec![
(span.shrink_to_lo(), "(".to_string()),
(span.shrink_to_hi(), ")".to_string()),
suggestions,
Applicability::MachineApplicable,
);
+ };
+
+ // If type ascription is "likely an error", the user will already be getting a useful
+ // help message, and doesn't need a second.
+ if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) {
+ self.maybe_annotate_with_ascription(&mut err, false);
+ } else if let Some(ascription_span) = maybe_ascription_span {
+ let is_nightly = self.sess.unstable_features.is_nightly_build();
+ if is_nightly {
+ suggest_parens(&mut err);
+ }
+ err.span_suggestion(
+ ascription_span,
+ &format!(
+ "{}remove the type ascription",
+ if is_nightly { "alternatively, " } else { "" }
+ ),
+ String::new(),
+ if is_nightly {
+ Applicability::MaybeIncorrect
+ } else {
+ Applicability::MachineApplicable
+ },
+ );
+ } else {
+ suggest_parens(&mut err);
}
err.emit();
};
let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
&& self.look_ahead_type_ascription_as_field()
{
- Some((self.clone(), fun.kind.clone()))
+ Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
} else {
None
};
lo: Span,
open_paren: Span,
seq: &mut PResult<'a, P<Expr>>,
- snapshot: Option<(Self, ExprKind)>,
+ snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
) -> Option<P<Expr>> {
match (seq.as_mut(), snapshot) {
(Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
// We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
// `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
- *self = snapshot;
+ self.restore_snapshot(snapshot);
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {