diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c7aa9ffc793..40daf4eb28f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1,5 +1,5 @@ use super::pat::Expected; -use super::ty::{AllowPlus, IsAsCast}; +use super::ty::{AllowPlus, RecoverQuestionMark}; use super::{ BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep, TokenExpectType, TokenType, @@ -1049,9 +1049,9 @@ pub(super) fn maybe_report_ambiguous_plus( pub(super) fn maybe_recover_from_question_mark( &mut self, ty: P, - is_as_cast: IsAsCast, + recover_question_mark: RecoverQuestionMark, ) -> P { - if let IsAsCast::Yes = is_as_cast { + if let RecoverQuestionMark::No = recover_question_mark { return ty; } if self.token == token::Question { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 83e0a4997ad..40902fa1833 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -140,7 +140,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter } NonterminalKind::Ty => { - token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty())?) + token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?) } // this could be handled like a token, since it is one NonterminalKind::Ident diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 0b01f9e927f..436c5bd4fca 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -44,7 +44,7 @@ pub(super) enum RecoverQPath { No, } -pub(super) enum IsAsCast { +pub(super) enum RecoverQuestionMark { Yes, No, } @@ -105,7 +105,7 @@ pub fn parse_ty(&mut self) -> PResult<'a, P> { RecoverQPath::Yes, RecoverReturnSign::Yes, None, - IsAsCast::No, + RecoverQuestionMark::Yes, ) } @@ -119,7 +119,7 @@ pub(super) fn parse_ty_with_generics_recovery( RecoverQPath::Yes, RecoverReturnSign::Yes, Some(ty_params), - IsAsCast::No, + RecoverQuestionMark::Yes, ) } @@ -133,7 +133,7 @@ pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P> { RecoverQPath::Yes, RecoverReturnSign::Yes, None, - IsAsCast::No, + RecoverQuestionMark::Yes, ) } @@ -150,7 +150,7 @@ pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P> { RecoverQPath::Yes, RecoverReturnSign::Yes, None, - IsAsCast::No, + RecoverQuestionMark::Yes, ) } @@ -163,9 +163,21 @@ pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P> { RecoverQPath::Yes, RecoverReturnSign::Yes, None, - IsAsCast::Yes, + RecoverQuestionMark::No, ) } + + pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P> { + self.parse_ty_common( + AllowPlus::Yes, + AllowCVariadic::No, + RecoverQPath::Yes, + RecoverReturnSign::Yes, + None, + RecoverQuestionMark::No, + ) + } + /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>` pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> { self.parse_ty_common( @@ -174,7 +186,7 @@ pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> { RecoverQPath::Yes, RecoverReturnSign::OnlyFatArrow, None, - IsAsCast::No, + RecoverQuestionMark::Yes, ) } @@ -193,7 +205,7 @@ pub(super) fn parse_ret_ty( recover_qpath, recover_return_sign, None, - IsAsCast::No, + RecoverQuestionMark::Yes, )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -214,7 +226,7 @@ pub(super) fn parse_ret_ty( recover_qpath, recover_return_sign, None, - IsAsCast::No, + RecoverQuestionMark::Yes, )?; FnRetTy::Ty(ty) } else { @@ -229,7 +241,7 @@ fn parse_ty_common( recover_qpath: RecoverQPath, recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, - is_as_cast: IsAsCast, + recover_question_mark: RecoverQuestionMark, ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -305,7 +317,7 @@ fn parse_ty_common( // Try to recover from use of `+` with incorrect priority. self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?; - let ty = self.maybe_recover_from_question_mark(ty, is_as_cast); + let ty = self.maybe_recover_from_question_mark(ty, recover_question_mark); self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery) } diff --git a/src/test/ui/parser/trailing-question-in-macro-type.rs b/src/test/ui/parser/trailing-question-in-macro-type.rs new file mode 100644 index 00000000000..e2a681ddd11 --- /dev/null +++ b/src/test/ui/parser/trailing-question-in-macro-type.rs @@ -0,0 +1,14 @@ +macro_rules! fn_expr { + ($return_type:ty : $body:expr) => { + (|| -> $return_type { $body })() + }; + ($body:expr) => { + (|| $body)() + }; +} + + +fn main() { + fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) }; + //~^ ERROR cannot find value `o` in this scope +} diff --git a/src/test/ui/parser/trailing-question-in-macro-type.stderr b/src/test/ui/parser/trailing-question-in-macro-type.stderr new file mode 100644 index 00000000000..c096ae04fbb --- /dev/null +++ b/src/test/ui/parser/trailing-question-in-macro-type.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `o` in this scope + --> $DIR/trailing-question-in-macro-type.rs:12:15 + | +LL | fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) }; + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`.