diff options
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 38 | 
3 files changed, 66 insertions, 34 deletions
| diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 757a7e1c8e7..ce3006c2604 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -11,7 +11,7 @@ use rustc_ast::token::MetaVarKind; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; -use rustc_attr_data_structures::{AttributeKind, Deprecation, Stability, find_attr}; +use rustc_attr_data_structures::{AttributeKind, CfgEntry, Deprecation, Stability, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sync; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult}; @@ -1128,7 +1128,13 @@ pub trait ResolverExpand { /// HIR proc macros items back to their harness items. fn declare_proc_macro(&mut self, id: NodeId); - fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem); + fn append_stripped_cfg_item( + &mut self, + parent_node: NodeId, + ident: Ident, + cfg: CfgEntry, + cfg_span: Span, + ); /// Tools registered with `#![register_tool]` and used by tool attributes and lints. fn registered_tools(&self) -> &RegisteredTools; diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 170ac39d1ec..6922ddfd6bd 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -11,6 +11,9 @@ use rustc_ast::{ NodeId, NormalAttr, }; use rustc_attr_parsing as attr; +use rustc_attr_parsing::{ + AttributeParser, CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr, +}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features, @@ -18,6 +21,7 @@ use rustc_feature::{ }; use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::validate_attr; +use rustc_parse::validate_attr::deny_builtin_meta_unsafety; use rustc_session::Session; use rustc_session::parse::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; @@ -161,7 +165,10 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec attrs .iter() .flat_map(|attr| strip_unconfigured.process_cfg_attr(attr)) - .take_while(|attr| !is_cfg(attr) || strip_unconfigured.cfg_true(attr).0) + .take_while(|attr| { + !is_cfg(attr) + || strip_unconfigured.cfg_true(attr, strip_unconfigured.lint_node_id).as_bool() + }) .collect() } @@ -394,26 +401,42 @@ impl<'a> StripUnconfigured<'a> { /// Determines if a node with the given attributes should be included in this configuration. fn in_cfg(&self, attrs: &[Attribute]) -> bool { - attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr).0) + attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr, self.lint_node_id).as_bool()) } - pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) { - let meta_item = match validate_attr::parse_meta(&self.sess.psess, attr) { - Ok(meta_item) => meta_item, + pub(crate) fn cfg_true(&self, attr: &Attribute, node: NodeId) -> EvalConfigResult { + // We need to run this to do basic validation of the attribute, such as that lits are valid, etc + // FIXME(jdonszelmann) this should not be necessary in the future + match validate_attr::parse_meta(&self.sess.psess, attr) { + Ok(_) => {} Err(err) => { err.emit(); - return (true, None); + return EvalConfigResult::True; } - }; + } - validate_attr::deny_builtin_meta_unsafety(&self.sess.psess, &meta_item); + // Unsafety check needs to be done explicitly here because this attribute will be removed before the normal check + deny_builtin_meta_unsafety( + self.sess.dcx(), + attr.get_normal_item().unsafety, + &rustc_ast::Path::from_ident(attr.ident().unwrap()), + ); + + let Some(cfg) = AttributeParser::parse_single( + self.sess, + attr, + attr.span, + node, + self.features, + true, + parse_cfg_attr, + &CFG_TEMPLATE, + ) else { + // Cfg attribute was not parsable, give up + return EvalConfigResult::True; + }; - ( - parse_cfg(&meta_item, self.sess).is_none_or(|meta_item| { - attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features) - }), - Some(meta_item), - ) + eval_config_entry(self.sess, &cfg, self.lint_node_id, self.features) } /// If attributes are not allowed on expressions, emit an error for `attr` @@ -465,6 +488,7 @@ impl<'a> StripUnconfigured<'a> { } } +/// FIXME: Still used by Rustdoc, should be removed after pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> { let span = meta_item.span; match meta_item.meta_item_list() { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 2de09aa1a28..f99060e9a21 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -13,6 +13,7 @@ use rustc_ast::{ MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; +use rustc_attr_parsing::EvalConfigResult; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::PResult; use rustc_feature::Features; @@ -2166,19 +2167,19 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn expand_cfg_true( &mut self, - node: &mut impl HasAttrs, + node: &mut (impl HasAttrs + HasNodeId), attr: ast::Attribute, pos: usize, - ) -> (bool, Option<ast::MetaItem>) { - let (res, meta_item) = self.cfg().cfg_true(&attr); - if res { + ) -> EvalConfigResult { + let res = self.cfg().cfg_true(&attr, node.node_id()); + if res.as_bool() { // A trace attribute left in AST in place of the original `cfg` attribute. // It can later be used by lints or other diagnostics. let trace_attr = attr_into_trace(attr, sym::cfg_trace); node.visit_attrs(|attrs| attrs.insert(pos, trace_attr)); } - (res, meta_item) + res } fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) { @@ -2199,20 +2200,21 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { return match self.take_first_attr(&mut node) { Some((attr, pos, derives)) => match attr.name() { Some(sym::cfg) => { - let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos); - if res { - continue; - } - - if let Some(meta_item) = meta_item { - for ident in node.declared_idents() { - self.cx.resolver.append_stripped_cfg_item( - self.cx.current_expansion.lint_node_id, - ident, - meta_item.clone(), - ) + let res = self.expand_cfg_true(&mut node, attr, pos); + match res { + EvalConfigResult::True => continue, + EvalConfigResult::False { reason, reason_span } => { + for ident in node.declared_idents() { + self.cx.resolver.append_stripped_cfg_item( + self.cx.current_expansion.lint_node_id, + ident, + reason.clone(), + reason_span, + ) + } } } + Default::default() } Some(sym::cfg_attr) => { @@ -2291,7 +2293,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { Some((attr, pos, derives)) => match attr.name() { Some(sym::cfg) => { let span = attr.span; - if self.expand_cfg_true(node, attr, pos).0 { + if self.expand_cfg_true(node, attr, pos).as_bool() { continue; } | 
