diff options
| author | bors <bors@rust-lang.org> | 2023-06-07 17:38:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-06-07 17:38:57 +0000 |
| commit | a97c36dd2e6f711949fc9b790476e93bd9e6d1f4 (patch) | |
| tree | 396855263c5ba620f0e10489717dbfd2f09febb2 /compiler/rustc_expand/src | |
| parent | b2807b2bf3be9fbed9a0aadc97841c20a1ab5f79 (diff) | |
| parent | a647ba250a65b44574830cb71aab5c0403adf31b (diff) | |
| download | rust-a97c36dd2e6f711949fc9b790476e93bd9e6d1f4.tar.gz rust-a97c36dd2e6f711949fc9b790476e93bd9e6d1f4.zip | |
Auto merge of #109005 - Nilstrieb:dont-forgor-too-much-from-cfg, r=petrochenkov
Remember names of `cfg`-ed out items to mention them in diagnostics
# Examples
## `serde::Deserialize` without the `derive` feature (a classic beginner mistake)
I had to slightly modify serde so that it uses explicit re-exports instead of a glob re-export. (Update: a serde PR was merged that adds the manual re-exports)
```
error[E0433]: failed to resolve: could not find `Serialize` in `serde`
--> src/main.rs:1:17
|
1 | #[derive(serde::Serialize)]
| ^^^^^^^^^ could not find `Serialize` in `serde`
|
note: crate `serde` has an item named `Serialize` but it is inactive because its cfg predicate evaluated to false
--> /home/gh-Nilstrieb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/src/lib.rs:343:1
|
343 | #[cfg(feature = "serde_derive")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
344 | pub use serde_derive::{Deserialize, Serialize};
| ^^^^^^^^^
= note: the item is gated behind the `serde_derive` feature
= note: see https://doc.rust-lang.org/cargo/reference/features.html for how to activate a crate's feature
```
(the suggestion is not ideal but that's serde's fault)
I already tested the metadata size impact locally by compiling the `windows` crate without any features. `800k` -> `809k`
r? `@ghost`
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 49 |
3 files changed, 61 insertions, 12 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0d43b30474b..b7c30841983 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -947,6 +947,8 @@ 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, name: Ident, cfg: ast::MetaItem); + /// Tools registered with `#![register_tool]` and used by tool attributes and lints. fn registered_tools(&self) -> &RegisteredTools; } @@ -965,7 +967,7 @@ pub trait LintStoreExpand { type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>; -#[derive(Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct ModuleData { /// Path to the module starting from the crate name, like `my_crate::foo::bar`. pub mod_path: Vec<Ident>, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 4ff8e409d88..690f80f6876 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -416,20 +416,28 @@ 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)) + attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr).0) } - pub(crate) fn cfg_true(&self, attr: &Attribute) -> bool { + pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) { let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) { Ok(meta_item) => meta_item, Err(mut err) => { err.emit(); - return true; + return (true, None); } }; - parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| { - attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features) - }) + ( + parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| { + attr::cfg_matches( + &meta_item, + &self.sess.parse_sess, + self.lint_node_id, + self.features, + ) + }), + Some(meta_item), + ) } /// If attributes are not allowed on expressions, emit an error for `attr` diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ce0093c7d4c..dd8863df195 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1042,6 +1042,12 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, span: Span) { collector.cx.emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); } + + /// All of the names (items) declared by this node. + /// This is an approximation and should only be used for diagnostics. + fn declared_names(&self) -> Vec<Ident> { + vec![] + } } impl InvocationCollectorNode for P<ast::Item> { @@ -1148,6 +1154,27 @@ impl InvocationCollectorNode for P<ast::Item> { collector.cx.current_expansion.module = orig_module; res } + fn declared_names(&self) -> Vec<Ident> { + if let ItemKind::Use(ut) = &self.kind { + fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) { + match &ut.kind { + ast::UseTreeKind::Glob => {} + ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), + ast::UseTreeKind::Nested(nested) => { + for (ut, _) in nested { + collect_use_tree_leaves(&ut, idents); + } + } + } + } + + let mut idents = Vec::new(); + collect_use_tree_leaves(&ut, &mut idents); + return idents; + } + + vec![self.ident] + } } struct TraitItemTag; @@ -1685,8 +1712,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize, - ) -> bool { - let res = self.cfg().cfg_true(&attr); + ) -> (bool, Option<ast::MetaItem>) { + let (res, meta_item) = self.cfg().cfg_true(&attr); if res { // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion, // and some tools like rustdoc and clippy rely on that. Find a way to remove them @@ -1694,7 +1721,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.cx.expanded_inert_attrs.mark(&attr); node.visit_attrs(|attrs| attrs.insert(pos, attr)); } - res + + (res, meta_item) } fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) { @@ -1715,9 +1743,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { return match self.take_first_attr(&mut node) { Some((attr, pos, derives)) => match attr.name_or_empty() { sym::cfg => { - if self.expand_cfg_true(&mut node, attr, pos) { + let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos); + if res { continue; } + + if let Some(meta_item) = meta_item { + for name in node.declared_names() { + self.cx.resolver.append_stripped_cfg_item( + self.cx.current_expansion.lint_node_id, + name, + meta_item.clone(), + ) + } + } Default::default() } sym::cfg_attr => { @@ -1761,7 +1800,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { Some((attr, pos, derives)) => match attr.name_or_empty() { sym::cfg => { let span = attr.span; - if self.expand_cfg_true(node, attr, pos) { + if self.expand_cfg_true(node, attr, pos).0 { continue; } |
