Unify defined_lib_features and lib_features queries
This commit is contained in:
parent
46ecc10c69
commit
86299a1247
9 changed files with 85 additions and 62 deletions
|
@ -8,18 +8,14 @@ use rustc_ast::Attribute;
|
|||
use rustc_attr::VERSION_PLACEHOLDER;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::lib_features::LibFeatures;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||
use rustc_middle::query::{LocalCrate, Providers};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
|
||||
|
||||
fn new_lib_features() -> LibFeatures {
|
||||
LibFeatures { stable: Default::default(), unstable: Default::default() }
|
||||
}
|
||||
|
||||
pub struct LibFeatureCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
lib_features: LibFeatures,
|
||||
|
@ -27,10 +23,10 @@ pub struct LibFeatureCollector<'tcx> {
|
|||
|
||||
impl<'tcx> LibFeatureCollector<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> {
|
||||
LibFeatureCollector { tcx, lib_features: new_lib_features() }
|
||||
LibFeatureCollector { tcx, lib_features: LibFeatures::default() }
|
||||
}
|
||||
|
||||
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
|
||||
fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)> {
|
||||
let stab_attrs = [
|
||||
sym::stable,
|
||||
sym::unstable,
|
||||
|
@ -72,8 +68,11 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
| sym::rustc_const_unstable
|
||||
| sym::rustc_default_body_unstable
|
||||
);
|
||||
if since.is_some() || is_unstable {
|
||||
return Some((feature, since, attr.span));
|
||||
if is_unstable {
|
||||
return Some((feature, FeatureStability::Unstable, attr.span));
|
||||
}
|
||||
if let Some(since) = since {
|
||||
return Some((feature, FeatureStability::AcceptedSince(since), attr.span));
|
||||
}
|
||||
}
|
||||
// We need to iterate over the other attributes, because
|
||||
|
@ -86,37 +85,43 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
|
||||
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);
|
||||
|
||||
match (since, already_in_stable, already_in_unstable) {
|
||||
(Some(since), _, false) => {
|
||||
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
|
||||
if *prev_since != since {
|
||||
self.tcx.sess.emit_err(FeatureStableTwice {
|
||||
span,
|
||||
feature,
|
||||
since,
|
||||
prev_since: *prev_since,
|
||||
});
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
self.lib_features.stable.insert(feature, (since, span));
|
||||
}
|
||||
(None, false, _) => {
|
||||
self.lib_features.unstable.insert(feature, span);
|
||||
}
|
||||
(Some(_), _, true) | (None, true, _) => {
|
||||
let declared = if since.is_some() { "stable" } else { "unstable" };
|
||||
let prev_declared = if since.is_none() { "stable" } else { "unstable" };
|
||||
(FeatureStability::AcceptedSince(_), _, true) => {
|
||||
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
|
||||
span,
|
||||
feature,
|
||||
declared,
|
||||
prev_declared,
|
||||
declared: "stable",
|
||||
prev_declared: "unstable",
|
||||
});
|
||||
}
|
||||
(FeatureStability::Unstable, false, _) => {
|
||||
self.lib_features.unstable.insert(feature, span);
|
||||
}
|
||||
(FeatureStability::Unstable, true, _) => {
|
||||
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
|
||||
span,
|
||||
feature,
|
||||
declared: "unstable",
|
||||
prev_declared: "stable",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -137,11 +142,11 @@ impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
|
||||
fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
|
||||
// If `staged_api` is not enabled then we aren't allowed to define lib
|
||||
// features; there is no point collecting them.
|
||||
if !tcx.features().staged_api {
|
||||
return new_lib_features();
|
||||
return LibFeatures::default();
|
||||
}
|
||||
|
||||
let mut collector = LibFeatureCollector::new(tcx);
|
||||
|
|
|
@ -14,6 +14,7 @@ use rustc_hir::hir_id::CRATE_HIR_ID;
|
|||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
|
||||
use rustc_middle::query::Providers;
|
||||
|
@ -978,29 +979,27 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
|
||||
remaining_implications: &mut FxHashMap<Symbol, Symbol>,
|
||||
defined_features: &[(Symbol, Option<Symbol>)],
|
||||
defined_features: &LibFeatures,
|
||||
all_implications: &FxHashMap<Symbol, Symbol>,
|
||||
) {
|
||||
for (feature, since) in defined_features {
|
||||
if let Some(since) = since
|
||||
for (feature, since) in defined_features.to_vec() {
|
||||
if let FeatureStability::AcceptedSince(since) = since
|
||||
&& let Some(span) = remaining_lib_features.get(&feature)
|
||||
{
|
||||
// Warn if the user has enabled an already-stable lib feature.
|
||||
if let Some(implies) = all_implications.get(&feature) {
|
||||
unnecessary_partially_stable_feature_lint(
|
||||
tcx, *span, *feature, *implies, *since,
|
||||
);
|
||||
unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since);
|
||||
} else {
|
||||
unnecessary_stable_feature_lint(tcx, *span, *feature, *since);
|
||||
unnecessary_stable_feature_lint(tcx, *span, feature, since);
|
||||
}
|
||||
}
|
||||
remaining_lib_features.remove(feature);
|
||||
remaining_lib_features.remove(&feature);
|
||||
|
||||
// `feature` is the feature doing the implying, but `implied_by` is the feature with
|
||||
// the attribute that establishes this relationship. `implied_by` is guaranteed to be a
|
||||
// feature defined in the local crate because `remaining_implications` is only the
|
||||
// implications from this crate.
|
||||
remaining_implications.remove(feature);
|
||||
remaining_implications.remove(&feature);
|
||||
|
||||
if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
|
||||
break;
|
||||
|
@ -1014,7 +1013,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
|
||||
// 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(()).to_vec();
|
||||
let local_defined_features = tcx.lib_features(rustc_hir::def_id::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
|
||||
|
@ -1028,7 +1027,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
tcx,
|
||||
&mut remaining_lib_features,
|
||||
&mut remaining_implications,
|
||||
local_defined_features.as_slice(),
|
||||
local_defined_features,
|
||||
&all_implications,
|
||||
);
|
||||
|
||||
|
@ -1040,7 +1039,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
tcx,
|
||||
&mut remaining_lib_features,
|
||||
&mut remaining_implications,
|
||||
tcx.defined_lib_features(cnum).to_vec().as_slice(),
|
||||
tcx.lib_features(cnum),
|
||||
&all_implications,
|
||||
);
|
||||
}
|
||||
|
@ -1051,7 +1050,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
|
||||
for (implied_by, feature) in remaining_implications {
|
||||
let local_defined_features = tcx.lib_features(());
|
||||
let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE);
|
||||
let span = *local_defined_features
|
||||
.stable
|
||||
.get(&feature)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue