diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index def23005fbe11..3d382e598fb21 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, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
     TokenExpectType, TokenType,
@@ -1037,9 +1037,9 @@ impl<'a> Parser<'a> {
     pub(super) fn maybe_recover_from_question_mark(
         &mut self,
         ty: P<Ty>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> P<Ty> {
-        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 72e6f8a1bc857..d9ec6184032f3 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -140,7 +140,7 @@ impl<'a> Parser<'a> {
             }
 
             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 566b77a5e9e55..89595c3f6241a 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 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -119,7 +119,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             Some(ty_params),
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -133,7 +133,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -150,7 +150,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -163,9 +163,21 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             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>`
     pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
@@ -174,7 +186,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::OnlyFatArrow,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -193,7 +205,7 @@ impl<'a> Parser<'a> {
                 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 @@ impl<'a> Parser<'a> {
                 recover_qpath,
                 recover_return_sign,
                 None,
-                IsAsCast::No,
+                RecoverQuestionMark::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else {
@@ -229,7 +241,7 @@ impl<'a> Parser<'a> {
         recover_qpath: RecoverQPath,
         recover_return_sign: RecoverReturnSign,
         ty_generics: Option<&Generics>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         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.
         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 0000000000000..e2a681ddd1115
--- /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 0000000000000..c096ae04fbbb6
--- /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`.