Skip to main content

rustc_builtin_macros/
view_type.rs

1use rustc_ast::token::TokenKind;
2use rustc_ast::tokenstream::TokenStream;
3use rustc_ast::{Ty, ast};
4use rustc_errors::PResult;
5use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
6use rustc_parse::parser::{ExpTokenPair, TokenType};
7use rustc_span::{Ident, Span};
8use thin_vec::ThinVec;
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_view_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::View(ty, pat))))
23}
24
25fn parse_view_ty<'a>(
26    cx: &mut ExtCtxt<'a>,
27    stream: TokenStream,
28) -> PResult<'a, (Box<Ty>, ThinVec<Ident>)> {
29    let mut parser = cx.new_parser_from_tts(stream);
30
31    let ty = parser.parse_ty()?;
32
33    parser.expect(ExpTokenPair { tok: TokenKind::Dot, token_type: TokenType::Dot })?;
34
35    let fields = match parser.parse_delim_comma_seq(
36        ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
37        ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
38        |p| p.parse_field_name(),
39    ) {
40        Ok((fields, _)) => fields,
41        Err(diag) => {
42            return Err(diag);
43        }
44    };
45
46    Ok((ty, fields))
47}