rustc_builtin_macros/
pattern_type.rs
1use rustc_ast::ptr::P;
2use rustc_ast::tokenstream::TokenStream;
3use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast};
4use rustc_errors::PResult;
5use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
6use rustc_parse::exp;
7use rustc_span::Span;
8
9pub(crate) fn expand<'cx>(
10 cx: &'cx mut ExtCtxt<'_>,
11 sp: Span,
12 tts: TokenStream,
13) -> MacroExpanderResult<'cx> {
14 let (ty, pat) = match parse_pat_ty(cx, tts) {
15 Ok(parsed) => parsed,
16 Err(err) => {
17 return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
18 }
19 };
20
21 ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
22}
23
24fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
25 let mut parser = cx.new_parser_from_tts(stream);
26
27 let ty = parser.parse_ty()?;
28 parser.expect_keyword(exp!(Is))?;
29 let pat = parser.parse_pat_no_top_alt(None, None)?.into_inner();
30
31 let kind = match pat.kind {
32 ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
33 start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
34 end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
35 include_end,
36 ),
37 ast::PatKind::Err(guar) => TyPatKind::Err(guar),
38 _ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
39 };
40
41 let pat = P(TyPat { id: pat.id, kind, span: pat.span, tokens: pat.tokens });
42
43 Ok((ty, pat))
44}