Skip to content

Commit a97c36d

Browse files
committed
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`
2 parents b2807b2 + a647ba2 commit a97c36d

30 files changed

+599
-84
lines changed

compiler/rustc_ast/src/expand/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
11
//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`.
22
3+
use rustc_span::{def_id::DefId, symbol::Ident};
4+
5+
use crate::MetaItem;
6+
37
pub mod allocator;
8+
9+
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
10+
pub struct StrippedCfgItem<ModId = DefId> {
11+
pub parent_module: ModId,
12+
pub name: Ident,
13+
pub cfg: MetaItem,
14+
}
15+
16+
impl<ModId> StrippedCfgItem<ModId> {
17+
pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
18+
StrippedCfgItem { parent_module: f(self.parent_module), name: self.name, cfg: self.cfg }
19+
}
20+
}

compiler/rustc_expand/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,8 @@ pub trait ResolverExpand {
947947
/// HIR proc macros items back to their harness items.
948948
fn declare_proc_macro(&mut self, id: NodeId);
949949

950+
fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem);
951+
950952
/// Tools registered with `#![register_tool]` and used by tool attributes and lints.
951953
fn registered_tools(&self) -> &RegisteredTools;
952954
}
@@ -965,7 +967,7 @@ pub trait LintStoreExpand {
965967

966968
type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>;
967969

968-
#[derive(Clone, Default)]
970+
#[derive(Debug, Clone, Default)]
969971
pub struct ModuleData {
970972
/// Path to the module starting from the crate name, like `my_crate::foo::bar`.
971973
pub mod_path: Vec<Ident>,

compiler/rustc_expand/src/config.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -416,20 +416,28 @@ impl<'a> StripUnconfigured<'a> {
416416

417417
/// Determines if a node with the given attributes should be included in this configuration.
418418
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
419-
attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr))
419+
attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr).0)
420420
}
421421

422-
pub(crate) fn cfg_true(&self, attr: &Attribute) -> bool {
422+
pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) {
423423
let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
424424
Ok(meta_item) => meta_item,
425425
Err(mut err) => {
426426
err.emit();
427-
return true;
427+
return (true, None);
428428
}
429429
};
430-
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
431-
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features)
432-
})
430+
(
431+
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
432+
attr::cfg_matches(
433+
&meta_item,
434+
&self.sess.parse_sess,
435+
self.lint_node_id,
436+
self.features,
437+
)
438+
}),
439+
Some(meta_item),
440+
)
433441
}
434442

435443
/// If attributes are not allowed on expressions, emit an error for `attr`

compiler/rustc_expand/src/expand.rs

+44-5
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,12 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
10421042
fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, span: Span) {
10431043
collector.cx.emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });
10441044
}
1045+
1046+
/// All of the names (items) declared by this node.
1047+
/// This is an approximation and should only be used for diagnostics.
1048+
fn declared_names(&self) -> Vec<Ident> {
1049+
vec![]
1050+
}
10451051
}
10461052

10471053
impl InvocationCollectorNode for P<ast::Item> {
@@ -1148,6 +1154,27 @@ impl InvocationCollectorNode for P<ast::Item> {
11481154
collector.cx.current_expansion.module = orig_module;
11491155
res
11501156
}
1157+
fn declared_names(&self) -> Vec<Ident> {
1158+
if let ItemKind::Use(ut) = &self.kind {
1159+
fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
1160+
match &ut.kind {
1161+
ast::UseTreeKind::Glob => {}
1162+
ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
1163+
ast::UseTreeKind::Nested(nested) => {
1164+
for (ut, _) in nested {
1165+
collect_use_tree_leaves(&ut, idents);
1166+
}
1167+
}
1168+
}
1169+
}
1170+
1171+
let mut idents = Vec::new();
1172+
collect_use_tree_leaves(&ut, &mut idents);
1173+
return idents;
1174+
}
1175+
1176+
vec![self.ident]
1177+
}
11511178
}
11521179

11531180
struct TraitItemTag;
@@ -1685,16 +1712,17 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
16851712
node: &mut impl HasAttrs,
16861713
attr: ast::Attribute,
16871714
pos: usize,
1688-
) -> bool {
1689-
let res = self.cfg().cfg_true(&attr);
1715+
) -> (bool, Option<ast::MetaItem>) {
1716+
let (res, meta_item) = self.cfg().cfg_true(&attr);
16901717
if res {
16911718
// FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
16921719
// and some tools like rustdoc and clippy rely on that. Find a way to remove them
16931720
// while keeping the tools working.
16941721
self.cx.expanded_inert_attrs.mark(&attr);
16951722
node.visit_attrs(|attrs| attrs.insert(pos, attr));
16961723
}
1697-
res
1724+
1725+
(res, meta_item)
16981726
}
16991727

17001728
fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) {
@@ -1715,9 +1743,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
17151743
return match self.take_first_attr(&mut node) {
17161744
Some((attr, pos, derives)) => match attr.name_or_empty() {
17171745
sym::cfg => {
1718-
if self.expand_cfg_true(&mut node, attr, pos) {
1746+
let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
1747+
if res {
17191748
continue;
17201749
}
1750+
1751+
if let Some(meta_item) = meta_item {
1752+
for name in node.declared_names() {
1753+
self.cx.resolver.append_stripped_cfg_item(
1754+
self.cx.current_expansion.lint_node_id,
1755+
name,
1756+
meta_item.clone(),
1757+
)
1758+
}
1759+
}
17211760
Default::default()
17221761
}
17231762
sym::cfg_attr => {
@@ -1761,7 +1800,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
17611800
Some((attr, pos, derives)) => match attr.name_or_empty() {
17621801
sym::cfg => {
17631802
let span = attr.span;
1764-
if self.expand_cfg_true(node, attr, pos) {
1803+
if self.expand_cfg_true(node, attr, pos).0 {
17651804
continue;
17661805
}
17671806

compiler/rustc_metadata/src/rmeta/decoder.rs

+9
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
995995
)
996996
}
997997

998+
fn get_stripped_cfg_items(self, cnum: CrateNum, tcx: TyCtxt<'tcx>) -> &'tcx [StrippedCfgItem] {
999+
let item_names = self
1000+
.root
1001+
.stripped_cfg_items
1002+
.decode((self, tcx))
1003+
.map(|item| item.map_mod_id(|index| DefId { krate: cnum, index }));
1004+
tcx.arena.alloc_from_iter(item_names)
1005+
}
1006+
9981007
/// Iterates over the diagnostic items in the given crate.
9991008
fn get_diagnostic_items(self) -> DiagnosticItems {
10001009
let mut id_to_name = FxHashMap::default();

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ provide! { tcx, def_id, other, cdata,
345345
stability_implications => {
346346
cdata.get_stability_implications(tcx).iter().copied().collect()
347347
}
348+
stripped_cfg_items => { cdata.get_stripped_cfg_items(cdata.cnum, tcx) }
348349
is_intrinsic => { cdata.get_is_intrinsic(def_id.index) }
349350
defined_lang_items => { cdata.get_lang_items(tcx) }
350351
diagnostic_items => { cdata.get_diagnostic_items() }

compiler/rustc_metadata/src/rmeta/encoder.rs

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
33
use crate::rmeta::table::TableBuilder;
44
use crate::rmeta::*;
55

6+
use rustc_ast::expand::StrippedCfgItem;
67
use rustc_ast::Attribute;
78
use rustc_data_structures::fingerprint::Fingerprint;
89
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@@ -584,6 +585,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
584585
(self.encode_lang_items(), self.encode_lang_items_missing())
585586
});
586587

588+
let stripped_cfg_items = stat!("stripped-cfg-items", || self.encode_stripped_cfg_items());
589+
587590
let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
588591

589592
let native_libraries = stat!("native-libs", || self.encode_native_libraries());
@@ -694,6 +697,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
694697
lang_items,
695698
diagnostic_items,
696699
lang_items_missing,
700+
stripped_cfg_items,
697701
native_libraries,
698702
foreign_modules,
699703
source_map,
@@ -1939,6 +1943,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19391943
self.lazy_array(&tcx.lang_items().missing)
19401944
}
19411945

1946+
fn encode_stripped_cfg_items(&mut self) -> LazyArray<StrippedCfgItem<DefIndex>> {
1947+
self.lazy_array(
1948+
self.tcx
1949+
.stripped_cfg_items(LOCAL_CRATE)
1950+
.into_iter()
1951+
.map(|item| item.clone().map_mod_id(|def_id| def_id.index)),
1952+
)
1953+
}
1954+
19421955
fn encode_traits(&mut self) -> LazyArray<DefIndex> {
19431956
empty_proc_macro!(self);
19441957
self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index))

compiler/rustc_metadata/src/rmeta/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
66
use table::TableBuilder;
77

88
use rustc_ast as ast;
9+
use rustc_ast::expand::StrippedCfgItem;
910
use rustc_attr as attr;
1011
use rustc_data_structures::svh::Svh;
1112
use rustc_hir as hir;
@@ -256,6 +257,7 @@ pub(crate) struct CrateRoot {
256257
stability_implications: LazyArray<(Symbol, Symbol)>,
257258
lang_items: LazyArray<(DefIndex, LangItem)>,
258259
lang_items_missing: LazyArray<LangItem>,
260+
stripped_cfg_items: LazyArray<StrippedCfgItem<DefIndex>>,
259261
diagnostic_items: LazyArray<(Symbol, DefIndex)>,
260262
native_libraries: LazyArray<NativeLib>,
261263
foreign_modules: LazyArray<ForeignModule>,

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ macro_rules! arena_types {
124124
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
125125
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
126126
[] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
127+
[] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
127128
[] mod_child: rustc_middle::metadata::ModChild,
128129
]);
129130
)

compiler/rustc_middle/src/query/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use crate::ty::{
5454
};
5555
use rustc_arena::TypedArena;
5656
use rustc_ast as ast;
57-
use rustc_ast::expand::allocator::AllocatorKind;
57+
use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem};
5858
use rustc_attr as attr;
5959
use rustc_data_structures::fingerprint::Fingerprint;
6060
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
@@ -2174,6 +2174,15 @@ rustc_queries! {
21742174
query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> {
21752175
desc { "check whether two const param are definitely not equal to eachother"}
21762176
}
2177+
2178+
/// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
2179+
/// Should not be called for the local crate before the resolver outputs are created, as it
2180+
/// is only fed there.
2181+
query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] {
2182+
feedable
2183+
desc { "getting cfg-ed out item names" }
2184+
separate_provide_extern
2185+
}
21772186
}
21782187

21792188
rustc_query_append! { define_callbacks! }

compiler/rustc_middle/src/ty/parameterized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ trivially_parameterized_over_tcx! {
7373
ty::fast_reject::SimplifiedType,
7474
rustc_ast::Attribute,
7575
rustc_ast::DelimArgs,
76+
rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,
7677
rustc_attr::ConstStability,
7778
rustc_attr::DefaultBodyStability,
7879
rustc_attr::Deprecation,

0 commit comments

Comments
 (0)