Skip to content

Commit

Permalink
Unify defined_lib_features and lib_features queries
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 23, 2023
1 parent 4e21162 commit d221878
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 58 deletions.
16 changes: 14 additions & 2 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_index::{Idx, IndexVec};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::lib_features::LibFeatures;
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType;
Expand Down Expand Up @@ -1007,8 +1008,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}

/// Iterates over all the stability attributes in the given crate.
fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
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));
}
FeatureStability::Unstable => {
features.unstable.insert(symbol, DUMMY_SP);
}
}
}
features
}

/// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ provide! { tcx, def_id, other, cdata,
module_children => {
tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess))
}
defined_lib_features => { cdata.get_lib_features(tcx) }
lib_features => { cdata.get_lib_features(tcx) }
stability_implications => {
cdata.get_stability_implications(tcx).iter().copied().collect()
}
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
};
use rustc_middle::middle::lib_features::FeatureStability;
use rustc_middle::mir::interpret;
use rustc_middle::query::LocalCrate;
use rustc_middle::query::Providers;
Expand Down Expand Up @@ -1871,10 +1872,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_array(deps.iter().map(|(_, dep)| dep))
}

fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let lib_features = tcx.lib_features(());
let lib_features = tcx.lib_features(LOCAL_CRATE);
self.lazy_array(lib_features.to_vec())
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use decoder::Metadata;
use def_path_hash_map::DefPathHashMapRef;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::lib_features::FeatureStability;
use table::TableBuilder;

use rustc_ast as ast;
Expand Down Expand Up @@ -264,7 +265,7 @@ pub(crate) struct CrateRoot {

crate_deps: LazyArray<CrateDep>,
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
lib_features: LazyArray<(Symbol, FeatureStability)>,
stability_implications: LazyArray<(Symbol, Symbol)>,
lang_items: LazyArray<(DefIndex, LangItem)>,
lang_items_missing: LazyArray<LangItem>,
Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_middle/src/middle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,27 @@ pub mod lib_features {
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{symbol::Symbol, Span};

#[derive(HashStable, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub enum FeatureStability {
AcceptedSince(Symbol),
Unstable,
}

#[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>,
}

impl LibFeatures {
pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> {
let mut all_features: Vec<_> = self
.stable
.iter()
.map(|(f, (s, _))| (*f, Some(*s)))
.chain(self.unstable.keys().map(|f| (*f, None)))
.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());
all_features
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,13 +1744,10 @@ rustc_queries! {
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
}

query lib_features(_: ()) -> &'tcx LibFeatures {
arena_cache
desc { "calculating the lib features map" }
}
query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
query lib_features(_: CrateNum) -> &'tcx LibFeatures {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
arena_cache
}
query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
arena_cache
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! {
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::lib_features::FeatureStability,
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
Expand Down
67 changes: 36 additions & 31 deletions compiler/rustc_passes/src/lib_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,25 @@ use rustc_ast::Attribute;
use rustc_attr::{rust_version_symbol, 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,
}

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,
Expand Down Expand Up @@ -70,8 +66,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
Expand All @@ -84,37 +83,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, _) => {
(FeatureStability::AcceptedSince(_), _, true) => {
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
span,
feature,
declared: "stable",
prev_declared: "unstable",
});
}
(FeatureStability::Unstable, 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::Unstable, true, _) => {
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
span,
feature,
declared,
prev_declared,
declared: "unstable",
prev_declared: "stable",
});
}
}
Expand All @@ -135,11 +140,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);
Expand Down
26 changes: 14 additions & 12 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -994,26 +995,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 && let Some(span) = remaining_lib_features.get(&feature) {
for (feature, stability) in defined_features.to_vec() {
if let FeatureStability::AcceptedSince(since) = stability
&& 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;
Expand All @@ -1027,7 +1029,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
Expand All @@ -1041,7 +1043,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,
);

Expand All @@ -1053,7 +1055,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,
);
}
Expand All @@ -1064,7 +1066,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)
Expand Down

0 comments on commit d221878

Please sign in to comment.