rustc_builtin_macros/
cfg.rs
1use rustc_ast::token;
6use rustc_ast::tokenstream::TokenStream;
7use rustc_errors::PResult;
8use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
9use rustc_parse::exp;
10use rustc_span::Span;
11use {rustc_ast as ast, rustc_attr_parsing as attr};
12
13use crate::errors;
14
15pub(crate) fn expand_cfg(
16 cx: &mut ExtCtxt<'_>,
17 sp: Span,
18 tts: TokenStream,
19) -> MacroExpanderResult<'static> {
20 let sp = cx.with_def_site_ctxt(sp);
21
22 ExpandResult::Ready(match parse_cfg(cx, sp, tts) {
23 Ok(cfg) => {
24 let matches_cfg = attr::cfg_matches(
25 &cfg,
26 &cx.sess,
27 cx.current_expansion.lint_node_id,
28 Some(cx.ecfg.features),
29 );
30 MacEager::expr(cx.expr_bool(sp, matches_cfg))
31 }
32 Err(err) => {
33 let guar = err.emit();
34 DummyResult::any(sp, guar)
35 }
36 })
37}
38
39fn parse_cfg<'a>(
40 cx: &ExtCtxt<'a>,
41 span: Span,
42 tts: TokenStream,
43) -> PResult<'a, ast::MetaItemInner> {
44 let mut p = cx.new_parser_from_tts(tts);
45
46 if p.token == token::Eof {
47 return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
48 }
49
50 let cfg = p.parse_meta_item_inner()?;
51
52 let _ = p.eat(exp!(Comma));
53
54 if !p.eat(exp!(Eof)) {
55 return Err(cx.dcx().create_err(errors::OneCfgPattern { span }));
56 }
57
58 Ok(cfg)
59}