1
Fork 0

Rollup merge of #94593 - estebank:issue-94510, r=davidtwco

Do not recover from `Ty?` in macro parsing

Follow up to #92746. Address #94510.
This commit is contained in:
Matthias Krüger 2022-03-04 17:31:08 +01:00 committed by GitHub
commit f9b4976d60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 15 deletions

View file

@ -1,5 +1,5 @@
use super::pat::Expected; use super::pat::Expected;
use super::ty::{AllowPlus, IsAsCast}; use super::ty::{AllowPlus, RecoverQuestionMark};
use super::{ use super::{
BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, SemiColonMode, SeqSep, TokenExpectType, TokenType,
@ -1049,9 +1049,9 @@ impl<'a> Parser<'a> {
pub(super) fn maybe_recover_from_question_mark( pub(super) fn maybe_recover_from_question_mark(
&mut self, &mut self,
ty: P<Ty>, ty: P<Ty>,
is_as_cast: IsAsCast, recover_question_mark: RecoverQuestionMark,
) -> P<Ty> { ) -> P<Ty> {
if let IsAsCast::Yes = is_as_cast { if let RecoverQuestionMark::No = recover_question_mark {
return ty; return ty;
} }
if self.token == token::Question { if self.token == token::Question {

View file

@ -140,7 +140,7 @@ impl<'a> Parser<'a> {
} }
NonterminalKind::Ty => { 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 // this could be handled like a token, since it is one
NonterminalKind::Ident NonterminalKind::Ident

View file

@ -44,7 +44,7 @@ pub(super) enum RecoverQPath {
No, No,
} }
pub(super) enum IsAsCast { pub(super) enum RecoverQuestionMark {
Yes, Yes,
No, No,
} }
@ -105,7 +105,7 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::Yes, RecoverReturnSign::Yes,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
) )
} }
@ -119,7 +119,7 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::Yes, RecoverReturnSign::Yes,
Some(ty_params), Some(ty_params),
IsAsCast::No, RecoverQuestionMark::Yes,
) )
} }
@ -133,7 +133,7 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::Yes, RecoverReturnSign::Yes,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
) )
} }
@ -150,7 +150,7 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::Yes, RecoverReturnSign::Yes,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
) )
} }
@ -163,9 +163,21 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::Yes, RecoverReturnSign::Yes,
None, None,
IsAsCast::Yes, RecoverQuestionMark::No,
) )
} }
pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
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>` /// 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<Ty>> { pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
self.parse_ty_common( self.parse_ty_common(
@ -174,7 +186,7 @@ impl<'a> Parser<'a> {
RecoverQPath::Yes, RecoverQPath::Yes,
RecoverReturnSign::OnlyFatArrow, RecoverReturnSign::OnlyFatArrow,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
) )
} }
@ -193,7 +205,7 @@ impl<'a> Parser<'a> {
recover_qpath, recover_qpath,
recover_return_sign, recover_return_sign,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
)?; )?;
FnRetTy::Ty(ty) FnRetTy::Ty(ty)
} else if recover_return_sign.can_recover(&self.token.kind) { } else if recover_return_sign.can_recover(&self.token.kind) {
@ -214,7 +226,7 @@ impl<'a> Parser<'a> {
recover_qpath, recover_qpath,
recover_return_sign, recover_return_sign,
None, None,
IsAsCast::No, RecoverQuestionMark::Yes,
)?; )?;
FnRetTy::Ty(ty) FnRetTy::Ty(ty)
} else { } else {
@ -229,7 +241,7 @@ impl<'a> Parser<'a> {
recover_qpath: RecoverQPath, recover_qpath: RecoverQPath,
recover_return_sign: RecoverReturnSign, recover_return_sign: RecoverReturnSign,
ty_generics: Option<&Generics>, ty_generics: Option<&Generics>,
is_as_cast: IsAsCast, recover_question_mark: RecoverQuestionMark,
) -> PResult<'a, P<Ty>> { ) -> PResult<'a, P<Ty>> {
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@ -305,7 +317,7 @@ impl<'a> Parser<'a> {
// Try to recover from use of `+` with incorrect priority. // Try to recover from use of `+` with incorrect priority.
self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
self.maybe_recover_from_bad_type_plus(allow_plus, &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) self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
} }

View file

@ -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
}

View file

@ -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`.