]> git.lizzy.rs Git - rust.git/blob - src/librustc_builtin_macros/concat_idents.rs
Rollup merge of #68374 - gitletH:patch-1, r=nikomatsakis
[rust.git] / src / librustc_builtin_macros / concat_idents.rs
1 use rustc_expand::base::{self, *};
2 use rustc_span::symbol::Symbol;
3 use rustc_span::Span;
4 use syntax::ast;
5 use syntax::ptr::P;
6 use syntax::token::{self, Token};
7 use syntax::tokenstream::{TokenStream, TokenTree};
8
9 pub fn expand_concat_idents<'cx>(
10     cx: &'cx mut ExtCtxt<'_>,
11     sp: Span,
12     tts: TokenStream,
13 ) -> Box<dyn base::MacResult + 'cx> {
14     if tts.is_empty() {
15         cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
16         return DummyResult::any(sp);
17     }
18
19     let mut res_str = String::new();
20     for (i, e) in tts.into_trees().enumerate() {
21         if i & 1 == 1 {
22             match e {
23                 TokenTree::Token(Token { kind: token::Comma, .. }) => {}
24                 _ => {
25                     cx.span_err(sp, "concat_idents! expecting comma.");
26                     return DummyResult::any(sp);
27                 }
28             }
29         } else {
30             match e {
31                 TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => {
32                     res_str.push_str(&name.as_str())
33                 }
34                 _ => {
35                     cx.span_err(sp, "concat_idents! requires ident args.");
36                     return DummyResult::any(sp);
37                 }
38             }
39         }
40     }
41
42     let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp));
43
44     struct ConcatIdentsResult {
45         ident: ast::Ident,
46     }
47
48     impl base::MacResult for ConcatIdentsResult {
49         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
50             Some(P(ast::Expr {
51                 id: ast::DUMMY_NODE_ID,
52                 kind: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
53                 span: self.ident.span,
54                 attrs: ast::AttrVec::new(),
55             }))
56         }
57
58         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
59             Some(P(ast::Ty {
60                 id: ast::DUMMY_NODE_ID,
61                 kind: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
62                 span: self.ident.span,
63             }))
64         }
65     }
66
67     Box::new(ConcatIdentsResult { ident })
68 }