Store feature stability un-split
This commit is contained in:
parent
86299a1247
commit
2d187d54fd
@ -1177,19 +1177,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
}
|
||||
|
||||
/// Iterates over all the stability attributes in the given crate.
|
||||
fn get_lib_features(self, _tcx: TyCtxt<'tcx>) -> LibFeatures {
|
||||
let mut features = LibFeatures::default();
|
||||
for (symbol, stability) in self.root.lib_features.decode(self) {
|
||||
match stability {
|
||||
FeatureStability::AcceptedSince(since) => {
|
||||
features.stable.insert(symbol, (since, DUMMY_SP));
|
||||
fn get_lib_features(self) -> LibFeatures {
|
||||
LibFeatures {
|
||||
stability: self
|
||||
.root
|
||||
.lib_features
|
||||
.decode(self)
|
||||
.map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
|
||||
.collect(),
|
||||
}
|
||||
FeatureStability::Unstable => {
|
||||
features.unstable.insert(symbol, DUMMY_SP);
|
||||
}
|
||||
}
|
||||
}
|
||||
features
|
||||
}
|
||||
|
||||
/// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
|
||||
|
@ -346,7 +346,7 @@ provide! { tcx, def_id, other, cdata,
|
||||
module_children => {
|
||||
tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess))
|
||||
}
|
||||
lib_features => { cdata.get_lib_features(tcx) }
|
||||
lib_features => { cdata.get_lib_features() }
|
||||
stability_implications => {
|
||||
cdata.get_stability_implications(tcx).iter().copied().collect()
|
||||
}
|
||||
|
@ -16,20 +16,14 @@ pub mod lib_features {
|
||||
|
||||
#[derive(HashStable, Debug, Default)]
|
||||
pub struct LibFeatures {
|
||||
/// A map from feature to stabilisation version.
|
||||
pub stable: FxHashMap<Symbol, (Symbol, Span)>,
|
||||
pub unstable: FxHashMap<Symbol, Span>,
|
||||
pub stability: FxHashMap<Symbol, (FeatureStability, Span)>,
|
||||
}
|
||||
|
||||
impl LibFeatures {
|
||||
pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> {
|
||||
let mut all_features: Vec<_> = self
|
||||
.stable
|
||||
.iter()
|
||||
.map(|(f, (s, _))| (*f, FeatureStability::AcceptedSince(*s)))
|
||||
.chain(self.unstable.iter().map(|(f, _)| (*f, FeatureStability::Unstable)))
|
||||
.collect();
|
||||
all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
|
||||
let mut all_features: Vec<_> =
|
||||
self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect();
|
||||
all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str()));
|
||||
all_features
|
||||
}
|
||||
}
|
||||
|
@ -86,26 +86,21 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
||||
}
|
||||
|
||||
fn collect_feature(&mut self, feature: Symbol, stability: FeatureStability, span: Span) {
|
||||
let already_in_stable = self.lib_features.stable.contains_key(&feature);
|
||||
let already_in_unstable = self.lib_features.unstable.contains_key(&feature);
|
||||
let existing_stability = self.lib_features.stability.get(&feature).cloned();
|
||||
|
||||
match (stability, already_in_stable, already_in_unstable) {
|
||||
(FeatureStability::AcceptedSince(since), _, false) => {
|
||||
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature)
|
||||
&& *prev_since != since
|
||||
{
|
||||
self.tcx.sess.emit_err(FeatureStableTwice {
|
||||
span,
|
||||
feature,
|
||||
since,
|
||||
prev_since: *prev_since,
|
||||
});
|
||||
return;
|
||||
match (stability, existing_stability) {
|
||||
(_, None) => {
|
||||
self.lib_features.stability.insert(feature, (stability, span));
|
||||
}
|
||||
|
||||
self.lib_features.stable.insert(feature, (since, span));
|
||||
(
|
||||
FeatureStability::AcceptedSince(since),
|
||||
Some((FeatureStability::AcceptedSince(prev_since), _)),
|
||||
) => {
|
||||
if prev_since != since {
|
||||
self.tcx.sess.emit_err(FeatureStableTwice { span, feature, since, prev_since });
|
||||
}
|
||||
(FeatureStability::AcceptedSince(_), _, true) => {
|
||||
}
|
||||
(FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => {
|
||||
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
|
||||
span,
|
||||
feature,
|
||||
@ -113,10 +108,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
||||
prev_declared: "unstable",
|
||||
});
|
||||
}
|
||||
(FeatureStability::Unstable, false, _) => {
|
||||
self.lib_features.unstable.insert(feature, span);
|
||||
}
|
||||
(FeatureStability::Unstable, true, _) => {
|
||||
(FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => {
|
||||
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
|
||||
span,
|
||||
feature,
|
||||
@ -124,6 +116,8 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
||||
prev_declared: "stable",
|
||||
});
|
||||
}
|
||||
// duplicate `unstable` feature is ok.
|
||||
(FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_attr::{
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||
@ -1008,12 +1008,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
||||
}
|
||||
|
||||
// All local crate implications need to have the feature that implies it confirmed to exist.
|
||||
let mut remaining_implications =
|
||||
tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone();
|
||||
let mut remaining_implications = tcx.stability_implications(LOCAL_CRATE).clone();
|
||||
|
||||
// We always collect the lib features declared in the current crate, even if there are
|
||||
// no unknown features, because the collection also does feature attribute validation.
|
||||
let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE);
|
||||
let local_defined_features = tcx.lib_features(LOCAL_CRATE);
|
||||
if !remaining_lib_features.is_empty() || !remaining_implications.is_empty() {
|
||||
// Loading the implications of all crates is unavoidable to be able to emit the partial
|
||||
// stabilization diagnostic, but it can be avoided when there are no
|
||||
@ -1050,13 +1049,12 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
||||
}
|
||||
|
||||
for (implied_by, feature) in remaining_implications {
|
||||
let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE);
|
||||
let span = *local_defined_features
|
||||
.stable
|
||||
let local_defined_features = tcx.lib_features(LOCAL_CRATE);
|
||||
let span = local_defined_features
|
||||
.stability
|
||||
.get(&feature)
|
||||
.map(|(_, span)| span)
|
||||
.or_else(|| local_defined_features.unstable.get(&feature))
|
||||
.expect("feature that implied another does not exist");
|
||||
.expect("feature that implied another does not exist")
|
||||
.1;
|
||||
tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user