Skip to content

Commit 8534923

Browse files
committed
Auto merge of rust-lang#116092 - compiler-errors:features-query, r=cjgillot
Unify `defined_lib_features` and `lib_features` queries Extracts part of rust-lang#115623 (comment) I went with also introducing a `FeatureStability` enum, instead of using `Some(span)` to mean stable and `None` to mean unstable. r? `@cjgillot`
2 parents 3a85a5c + 2d187d5 commit 8534923

File tree

9 files changed

+87
-82
lines changed

9 files changed

+87
-82
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_index::{Idx, IndexVec};
2121
use rustc_middle::metadata::ModChild;
2222
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
2323
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
24+
use rustc_middle::middle::lib_features::LibFeatures;
2425
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
2526
use rustc_middle::ty::codec::TyDecoder;
2627
use rustc_middle::ty::fast_reject::SimplifiedType;
@@ -828,7 +829,7 @@ impl MetadataBlob {
828829
out,
829830
"{}{}",
830831
feature,
831-
if let Some(since) = since {
832+
if let FeatureStability::AcceptedSince(since) = since {
832833
format!(" since {since}")
833834
} else {
834835
String::new()
@@ -1176,8 +1177,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
11761177
}
11771178

11781179
/// Iterates over all the stability attributes in the given crate.
1179-
fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
1180-
tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
1180+
fn get_lib_features(self) -> LibFeatures {
1181+
LibFeatures {
1182+
stability: self
1183+
.root
1184+
.lib_features
1185+
.decode(self)
1186+
.map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
1187+
.collect(),
1188+
}
11811189
}
11821190

11831191
/// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ provide! { tcx, def_id, other, cdata,
346346
module_children => {
347347
tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess))
348348
}
349-
defined_lib_features => { cdata.get_lib_features(tcx) }
349+
lib_features => { cdata.get_lib_features() }
350350
stability_implications => {
351351
cdata.get_stability_implications(tcx).iter().copied().collect()
352352
}

compiler/rustc_metadata/src/rmeta/encoder.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_middle::middle::dependency_format::Linkage;
2525
use rustc_middle::middle::exported_symbols::{
2626
metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
2727
};
28+
use rustc_middle::middle::lib_features::FeatureStability;
2829
use rustc_middle::mir::interpret;
2930
use rustc_middle::query::LocalCrate;
3031
use rustc_middle::query::Providers;
@@ -1902,10 +1903,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19021903
self.lazy_array(deps.iter().map(|(_, dep)| dep))
19031904
}
19041905

1905-
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
1906+
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
19061907
empty_proc_macro!(self);
19071908
let tcx = self.tcx;
1908-
let lib_features = tcx.lib_features(());
1909+
let lib_features = tcx.lib_features(LOCAL_CRATE);
19091910
self.lazy_array(lib_features.to_vec())
19101911
}
19111912

compiler/rustc_metadata/src/rmeta/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use decoder::Metadata;
33
use def_path_hash_map::DefPathHashMapRef;
44
use rustc_data_structures::fx::FxHashMap;
55
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
6+
use rustc_middle::middle::lib_features::FeatureStability;
67
use table::TableBuilder;
78

89
use rustc_ast as ast;
@@ -263,7 +264,7 @@ pub(crate) struct CrateRoot {
263264

264265
crate_deps: LazyArray<CrateDep>,
265266
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
266-
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
267+
lib_features: LazyArray<(Symbol, FeatureStability)>,
267268
stability_implications: LazyArray<(Symbol, Symbol)>,
268269
lang_items: LazyArray<(DefIndex, LangItem)>,
269270
lang_items_missing: LazyArray<LangItem>,

compiler/rustc_middle/src/middle/mod.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,23 @@ pub mod lib_features {
77
use rustc_data_structures::fx::FxHashMap;
88
use rustc_span::{symbol::Symbol, Span};
99

10-
#[derive(HashStable, Debug)]
10+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
11+
#[derive(HashStable, TyEncodable, TyDecodable)]
12+
pub enum FeatureStability {
13+
AcceptedSince(Symbol),
14+
Unstable,
15+
}
16+
17+
#[derive(HashStable, Debug, Default)]
1118
pub struct LibFeatures {
12-
/// A map from feature to stabilisation version.
13-
pub stable: FxHashMap<Symbol, (Symbol, Span)>,
14-
pub unstable: FxHashMap<Symbol, Span>,
19+
pub stability: FxHashMap<Symbol, (FeatureStability, Span)>,
1520
}
1621

1722
impl LibFeatures {
18-
pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
19-
let mut all_features: Vec<_> = self
20-
.stable
21-
.iter()
22-
.map(|(f, (s, _))| (*f, Some(*s)))
23-
.chain(self.unstable.keys().map(|f| (*f, None)))
24-
.collect();
25-
all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
23+
pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> {
24+
let mut all_features: Vec<_> =
25+
self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect();
26+
all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str()));
2627
all_features
2728
}
2829
}

compiler/rustc_middle/src/query/mod.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1732,13 +1732,10 @@ rustc_queries! {
17321732
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
17331733
}
17341734

1735-
query lib_features(_: ()) -> &'tcx LibFeatures {
1736-
arena_cache
1737-
desc { "calculating the lib features map" }
1738-
}
1739-
query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
1735+
query lib_features(_: CrateNum) -> &'tcx LibFeatures {
17401736
desc { "calculating the lib features defined in a crate" }
17411737
separate_provide_extern
1738+
arena_cache
17421739
}
17431740
query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
17441741
arena_cache

compiler/rustc_middle/src/ty/parameterized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! {
5959
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
6060
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
6161
crate::middle::exported_symbols::SymbolExportInfo,
62+
crate::middle::lib_features::FeatureStability,
6263
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
6364
crate::mir::ConstQualifs,
6465
ty::AssocItemContainer,

compiler/rustc_passes/src/lib_features.rs

+36-37
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,25 @@ use rustc_ast::Attribute;
88
use rustc_attr::VERSION_PLACEHOLDER;
99
use rustc_hir::intravisit::Visitor;
1010
use rustc_middle::hir::nested_filter;
11-
use rustc_middle::middle::lib_features::LibFeatures;
12-
use rustc_middle::query::Providers;
11+
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
12+
use rustc_middle::query::{LocalCrate, Providers};
1313
use rustc_middle::ty::TyCtxt;
1414
use rustc_span::symbol::Symbol;
1515
use rustc_span::{sym, Span};
1616

1717
use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
1818

19-
fn new_lib_features() -> LibFeatures {
20-
LibFeatures { stable: Default::default(), unstable: Default::default() }
21-
}
22-
2319
pub struct LibFeatureCollector<'tcx> {
2420
tcx: TyCtxt<'tcx>,
2521
lib_features: LibFeatures,
2622
}
2723

2824
impl<'tcx> LibFeatureCollector<'tcx> {
2925
fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> {
30-
LibFeatureCollector { tcx, lib_features: new_lib_features() }
26+
LibFeatureCollector { tcx, lib_features: LibFeatures::default() }
3127
}
3228

33-
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
29+
fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)> {
3430
let stab_attrs = [
3531
sym::stable,
3632
sym::unstable,
@@ -72,8 +68,11 @@ impl<'tcx> LibFeatureCollector<'tcx> {
7268
| sym::rustc_const_unstable
7369
| sym::rustc_default_body_unstable
7470
);
75-
if since.is_some() || is_unstable {
76-
return Some((feature, since, attr.span));
71+
if is_unstable {
72+
return Some((feature, FeatureStability::Unstable, attr.span));
73+
}
74+
if let Some(since) = since {
75+
return Some((feature, FeatureStability::AcceptedSince(since), attr.span));
7776
}
7877
}
7978
// We need to iterate over the other attributes, because
@@ -86,39 +85,39 @@ impl<'tcx> LibFeatureCollector<'tcx> {
8685
None
8786
}
8887

89-
fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
90-
let already_in_stable = self.lib_features.stable.contains_key(&feature);
91-
let already_in_unstable = self.lib_features.unstable.contains_key(&feature);
92-
93-
match (since, already_in_stable, already_in_unstable) {
94-
(Some(since), _, false) => {
95-
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
96-
if *prev_since != since {
97-
self.tcx.sess.emit_err(FeatureStableTwice {
98-
span,
99-
feature,
100-
since,
101-
prev_since: *prev_since,
102-
});
103-
return;
104-
}
105-
}
88+
fn collect_feature(&mut self, feature: Symbol, stability: FeatureStability, span: Span) {
89+
let existing_stability = self.lib_features.stability.get(&feature).cloned();
10690

107-
self.lib_features.stable.insert(feature, (since, span));
91+
match (stability, existing_stability) {
92+
(_, None) => {
93+
self.lib_features.stability.insert(feature, (stability, span));
10894
}
109-
(None, false, _) => {
110-
self.lib_features.unstable.insert(feature, span);
95+
(
96+
FeatureStability::AcceptedSince(since),
97+
Some((FeatureStability::AcceptedSince(prev_since), _)),
98+
) => {
99+
if prev_since != since {
100+
self.tcx.sess.emit_err(FeatureStableTwice { span, feature, since, prev_since });
101+
}
102+
}
103+
(FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => {
104+
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
105+
span,
106+
feature,
107+
declared: "stable",
108+
prev_declared: "unstable",
109+
});
111110
}
112-
(Some(_), _, true) | (None, true, _) => {
113-
let declared = if since.is_some() { "stable" } else { "unstable" };
114-
let prev_declared = if since.is_none() { "stable" } else { "unstable" };
111+
(FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => {
115112
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
116113
span,
117114
feature,
118-
declared,
119-
prev_declared,
115+
declared: "unstable",
116+
prev_declared: "stable",
120117
});
121118
}
119+
// duplicate `unstable` feature is ok.
120+
(FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {}
122121
}
123122
}
124123
}
@@ -137,11 +136,11 @@ impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
137136
}
138137
}
139138

140-
fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
139+
fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
141140
// If `staged_api` is not enabled then we aren't allowed to define lib
142141
// features; there is no point collecting them.
143142
if !tcx.features().staged_api {
144-
return new_lib_features();
143+
return LibFeatures::default();
145144
}
146145

147146
let mut collector = LibFeatureCollector::new(tcx);

compiler/rustc_passes/src/stability.rs

+18-21
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ use rustc_attr::{
99
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
1010
use rustc_hir as hir;
1111
use rustc_hir::def::{DefKind, Res};
12-
use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID};
12+
use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID, LOCAL_CRATE};
1313
use rustc_hir::hir_id::CRATE_HIR_ID;
1414
use rustc_hir::intravisit::{self, Visitor};
1515
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
1616
use rustc_middle::hir::nested_filter;
17+
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
1718
use rustc_middle::middle::privacy::EffectiveVisibilities;
1819
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
1920
use rustc_middle::query::Providers;
@@ -978,29 +979,27 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
978979
tcx: TyCtxt<'tcx>,
979980
remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
980981
remaining_implications: &mut FxHashMap<Symbol, Symbol>,
981-
defined_features: &[(Symbol, Option<Symbol>)],
982+
defined_features: &LibFeatures,
982983
all_implications: &FxHashMap<Symbol, Symbol>,
983984
) {
984-
for (feature, since) in defined_features {
985-
if let Some(since) = since
985+
for (feature, since) in defined_features.to_vec() {
986+
if let FeatureStability::AcceptedSince(since) = since
986987
&& let Some(span) = remaining_lib_features.get(&feature)
987988
{
988989
// Warn if the user has enabled an already-stable lib feature.
989990
if let Some(implies) = all_implications.get(&feature) {
990-
unnecessary_partially_stable_feature_lint(
991-
tcx, *span, *feature, *implies, *since,
992-
);
991+
unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since);
993992
} else {
994-
unnecessary_stable_feature_lint(tcx, *span, *feature, *since);
993+
unnecessary_stable_feature_lint(tcx, *span, feature, since);
995994
}
996995
}
997-
remaining_lib_features.remove(feature);
996+
remaining_lib_features.remove(&feature);
998997

999998
// `feature` is the feature doing the implying, but `implied_by` is the feature with
1000999
// the attribute that establishes this relationship. `implied_by` is guaranteed to be a
10011000
// feature defined in the local crate because `remaining_implications` is only the
10021001
// implications from this crate.
1003-
remaining_implications.remove(feature);
1002+
remaining_implications.remove(&feature);
10041003

10051004
if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
10061005
break;
@@ -1009,12 +1008,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10091008
}
10101009

10111010
// All local crate implications need to have the feature that implies it confirmed to exist.
1012-
let mut remaining_implications =
1013-
tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone();
1011+
let mut remaining_implications = tcx.stability_implications(LOCAL_CRATE).clone();
10141012

10151013
// We always collect the lib features declared in the current crate, even if there are
10161014
// no unknown features, because the collection also does feature attribute validation.
1017-
let local_defined_features = tcx.lib_features(()).to_vec();
1015+
let local_defined_features = tcx.lib_features(LOCAL_CRATE);
10181016
if !remaining_lib_features.is_empty() || !remaining_implications.is_empty() {
10191017
// Loading the implications of all crates is unavoidable to be able to emit the partial
10201018
// stabilization diagnostic, but it can be avoided when there are no
@@ -1028,7 +1026,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10281026
tcx,
10291027
&mut remaining_lib_features,
10301028
&mut remaining_implications,
1031-
local_defined_features.as_slice(),
1029+
local_defined_features,
10321030
&all_implications,
10331031
);
10341032

@@ -1040,7 +1038,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10401038
tcx,
10411039
&mut remaining_lib_features,
10421040
&mut remaining_implications,
1043-
tcx.defined_lib_features(cnum).to_vec().as_slice(),
1041+
tcx.lib_features(cnum),
10441042
&all_implications,
10451043
);
10461044
}
@@ -1051,13 +1049,12 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10511049
}
10521050

10531051
for (implied_by, feature) in remaining_implications {
1054-
let local_defined_features = tcx.lib_features(());
1055-
let span = *local_defined_features
1056-
.stable
1052+
let local_defined_features = tcx.lib_features(LOCAL_CRATE);
1053+
let span = local_defined_features
1054+
.stability
10571055
.get(&feature)
1058-
.map(|(_, span)| span)
1059-
.or_else(|| local_defined_features.unstable.get(&feature))
1060-
.expect("feature that implied another does not exist");
1056+
.expect("feature that implied another does not exist")
1057+
.1;
10611058
tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
10621059
}
10631060

0 commit comments

Comments
 (0)