diff options
Diffstat (limited to 'compiler/rustc_builtin_macros')
| -rw-r--r-- | compiler/rustc_builtin_macros/messages.ftl | 6 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/cfg_select.rs | 63 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/source_util.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 9 | 
7 files changed, 94 insertions, 10 deletions
| diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 3594c7ec210..ae186d744c4 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -81,6 +81,12 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified +builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true + +builtin_macros_cfg_select_unreachable = unreachable predicate + .label = always matches + .label2 = this predicate is never reached + builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized` builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs new file mode 100644 index 00000000000..f22d5f255c2 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -0,0 +1,63 @@ +use rustc_ast::tokenstream::TokenStream; +use rustc_attr_parsing as attr; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; +use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select}; +use rustc_span::{Ident, Span, sym}; + +use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; + +/// Selects the first arm whose predicate evaluates to true. +fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> { + for (cfg, tt, arm_span) in branches.reachable { + if attr::cfg_matches( + &cfg, + &ecx.sess, + ecx.current_expansion.lint_node_id, + Some(ecx.ecfg.features), + ) { + return Some((tt, arm_span)); + } + } + + branches.wildcard.map(|(_, tt, span)| (tt, span)) +} + +pub(super) fn expand_cfg_select<'cx>( + ecx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) { + Ok(branches) => { + if let Some((underscore, _, _)) = branches.wildcard { + // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. + for (predicate, _, _) in &branches.unreachable { + let span = match predicate { + CfgSelectPredicate::Wildcard(underscore) => underscore.span, + CfgSelectPredicate::Cfg(cfg) => cfg.span(), + }; + let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; + ecx.dcx().emit_warn(err); + } + } + + if let Some((tts, arm_span)) = select_arm(ecx, branches) { + return ExpandResult::from_tts( + ecx, + tts, + sp, + arm_span, + Ident::with_dummy_span(sym::cfg_select), + ); + } else { + // Emit a compiler error when none of the predicates matched. + let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); + DummyResult::any(sp, guar) + } + } + Err(err) => { + let guar = err.emit(); + DummyResult::any(sp, guar) + } + }) +} diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8c3093acea4..c55a9e73e38 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -484,7 +484,7 @@ impl<'a> TraitDef<'a> { match item { Annotatable::Item(item) => { let is_packed = matches!( - AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id), + AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id, None), Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) ); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index a5ee7349fc6..6bcf4d3e0a2 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -954,3 +954,21 @@ pub(crate) struct AsmExpectedOther { pub(crate) span: Span, pub(crate) is_inline_asm: bool, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_cfg_select_no_matches)] +pub(crate) struct CfgSelectNoMatches { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_cfg_select_unreachable)] +pub(crate) struct CfgSelectUnreachable { + #[primary_span] + #[label(builtin_macros_label2)] + pub span: Span, + + #[label] + pub wildcard_span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 6bf590df5c9..7bc448a9acb 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -33,6 +33,7 @@ mod autodiff; mod cfg; mod cfg_accessible; mod cfg_eval; +mod cfg_select; mod compile_error; mod concat; mod concat_bytes; @@ -79,6 +80,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { asm: asm::expand_asm, assert: assert::expand_assert, cfg: cfg::expand_cfg, + cfg_select: cfg_select::expand_cfg_select, column: source_util::expand_column, compile_error: compile_error::expand_compile_error, concat: concat::expand_concat, diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index cebfffa1e16..ecfd46a84ec 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{join_path_idents, token}; use rustc_ast_pretty::pprust; use rustc_expand::base::{ DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path, @@ -100,7 +100,7 @@ pub(crate) fn expand_mod( let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; - let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::"); + let string = join_path_idents(mod_path); ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index b067578794b..ba3d8368b2a 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -5,7 +5,7 @@ use std::assert_matches::assert_matches; use std::iter; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, GenericParamKind, attr}; +use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, Level}; use rustc_expand::base::*; @@ -446,12 +446,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, } fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String { - mod_path - .iter() - .chain(iter::once(item_ident)) - .map(|x| x.to_string()) - .collect::<Vec<String>>() - .join("::") + join_path_idents(mod_path.iter().chain(iter::once(item_ident))) } enum ShouldPanic { | 
