rustc_builtin_macros/
pattern_type.rs1use rustc_ast::ptr::P;
2use rustc_ast::tokenstream::TokenStream;
3use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
4use rustc_errors::PResult;
5use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
6use rustc_parse::exp;
7use rustc_parse::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
8use rustc_span::Span;
9
10pub(crate) fn expand<'cx>(
11 cx: &'cx mut ExtCtxt<'_>,
12 sp: Span,
13 tts: TokenStream,
14) -> MacroExpanderResult<'cx> {
15 let (ty, pat) = match parse_pat_ty(cx, tts) {
16 Ok(parsed) => parsed,
17 Err(err) => {
18 return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
19 }
20 };
21
22 ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
23}
24
25fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
26 let mut parser = cx.new_parser_from_tts(stream);
27
28 let ty = parser.parse_ty()?;
29 parser.expect_keyword(exp!(Is))?;
30
31 let pat = pat_to_ty_pat(
32 cx,
33 parser
34 .parse_pat_no_top_guard(
35 None,
36 RecoverComma::No,
37 RecoverColon::No,
38 CommaRecoveryMode::EitherTupleOrPipe,
39 )?
40 .into_inner(),
41 );
42
43 if parser.token != token::Eof {
44 parser.unexpected()?;
45 }
46
47 Ok((ty, pat))
48}
49
50fn ty_pat(kind: TyPatKind, span: Span) -> P<TyPat> {
51 P(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
52}
53
54fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> P<TyPat> {
55 let kind = match pat.kind {
56 ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
57 start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
58 end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
59 include_end,
60 ),
61 ast::PatKind::Or(variants) => TyPatKind::Or(
62 variants.into_iter().map(|pat| pat_to_ty_pat(cx, pat.into_inner())).collect(),
63 ),
64 ast::PatKind::Err(guar) => TyPatKind::Err(guar),
65 _ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
66 };
67 ty_pat(kind, pat.span)
68}