make some rustc_feature internals private, and ensure invariants with debug assertions
This commit is contained in:
parent
46ce5cbf33
commit
1381773e01
@ -604,7 +604,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||||||
if sess.opts.unstable_features.is_nightly_build() {
|
if sess.opts.unstable_features.is_nightly_build() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if features.enabled_features.is_empty() {
|
if features.enabled_features().is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut errored = false;
|
let mut errored = false;
|
||||||
@ -621,7 +621,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||||||
for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
|
for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
|
||||||
let name = ident.name;
|
let name = ident.name;
|
||||||
let stable_since = features
|
let stable_since = features
|
||||||
.enabled_lang_features
|
.enabled_lang_features()
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
|
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
|
||||||
.next();
|
.next();
|
||||||
@ -643,11 +643,11 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||||||
|
|
||||||
fn check_incompatible_features(sess: &Session, features: &Features) {
|
fn check_incompatible_features(sess: &Session, features: &Features) {
|
||||||
let enabled_features = features
|
let enabled_features = features
|
||||||
.enabled_lang_features
|
.enabled_lang_features()
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.map(|(name, span, _)| (name, span))
|
.map(|(name, span, _)| (name, span))
|
||||||
.chain(features.enabled_lib_features.iter().copied());
|
.chain(features.enabled_lib_features().iter().copied());
|
||||||
|
|
||||||
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
|
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
|
||||||
.iter()
|
.iter()
|
||||||
@ -674,7 +674,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
|
|||||||
|
|
||||||
// Ban GCE with the new solver, because it does not implement GCE correctly.
|
// Ban GCE with the new solver, because it does not implement GCE correctly.
|
||||||
if let Some(&(_, gce_span, _)) = features
|
if let Some(&(_, gce_span, _)) = features
|
||||||
.enabled_lang_features
|
.enabled_lang_features()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
|
.find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ fn feature_list(attr: &Attribute) -> ThinVec<ast::MetaItemInner> {
|
|||||||
// If the enabled feature is stable, record it.
|
// If the enabled feature is stable, record it.
|
||||||
if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
||||||
let since = Some(Symbol::intern(f.since));
|
let since = Some(Symbol::intern(f.since));
|
||||||
features.set_enabled_lang_feature(name, mi.span(), since);
|
features.set_enabled_lang_feature(name, mi.span(), since, None);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,6 @@ fn feature_list(attr: &Attribute) -> ThinVec<ast::MetaItemInner> {
|
|||||||
|
|
||||||
// If the enabled feature is unstable, record it.
|
// If the enabled feature is unstable, record it.
|
||||||
if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
|
if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
|
||||||
(f.set_enabled)(&mut features);
|
|
||||||
// When the ICE comes from core, alloc or std (approximation of the standard
|
// When the ICE comes from core, alloc or std (approximation of the standard
|
||||||
// library), there's a chance that the person hitting the ICE may be using
|
// library), there's a chance that the person hitting the ICE may be using
|
||||||
// -Zbuild-std or similar with an untested target. The bug is probably in the
|
// -Zbuild-std or similar with an untested target. The bug is probably in the
|
||||||
@ -115,7 +114,7 @@ fn feature_list(attr: &Attribute) -> ThinVec<ast::MetaItemInner> {
|
|||||||
{
|
{
|
||||||
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
|
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
features.set_enabled_lang_feature(name, mi.span(), None);
|
features.set_enabled_lang_feature(name, mi.span(), None, Some(f));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
pub struct UnstableFeature {
|
pub struct UnstableFeature {
|
||||||
pub feature: Feature,
|
pub feature: Feature,
|
||||||
pub set_enabled: fn(&mut Features),
|
set_enabled: fn(&mut Features),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
@ -54,11 +54,11 @@ macro_rules! declare_features {
|
|||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
pub struct Features {
|
pub struct Features {
|
||||||
/// `#![feature]` attrs for language features, for error reporting.
|
/// `#![feature]` attrs for language features, for error reporting.
|
||||||
pub enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
|
enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
|
||||||
/// `#![feature]` attrs for non-language (library) features.
|
/// `#![feature]` attrs for non-language (library) features.
|
||||||
pub enabled_lib_features: Vec<(Symbol, Span)>,
|
enabled_lib_features: Vec<(Symbol, Span)>,
|
||||||
/// `enabled_lang_features` + `enabled_lib_features`.
|
/// `enabled_lang_features` + `enabled_lib_features`.
|
||||||
pub enabled_features: FxHashSet<Symbol>,
|
enabled_features: FxHashSet<Symbol>,
|
||||||
/// State of individual features (unstable lang features only).
|
/// State of individual features (unstable lang features only).
|
||||||
/// This is `true` if and only if the corresponding feature is listed in `enabled_lang_features`.
|
/// This is `true` if and only if the corresponding feature is listed in `enabled_lang_features`.
|
||||||
$(
|
$(
|
||||||
@ -70,17 +70,27 @@ pub struct Features {
|
|||||||
impl Features {
|
impl Features {
|
||||||
pub fn set_enabled_lang_feature(
|
pub fn set_enabled_lang_feature(
|
||||||
&mut self,
|
&mut self,
|
||||||
symbol: Symbol,
|
name: Symbol,
|
||||||
span: Span,
|
span: Span,
|
||||||
since: Option<Symbol>
|
since: Option<Symbol>,
|
||||||
|
feature: Option<&UnstableFeature>,
|
||||||
) {
|
) {
|
||||||
self.enabled_lang_features.push((symbol, span, since));
|
self.enabled_lang_features.push((name, span, since));
|
||||||
self.enabled_features.insert(symbol);
|
self.enabled_features.insert(name);
|
||||||
|
if let Some(feature) = feature {
|
||||||
|
assert_eq!(feature.feature.name, name);
|
||||||
|
(feature.set_enabled)(self);
|
||||||
|
} else {
|
||||||
|
// Ensure we don't skip a `set_enabled` call.
|
||||||
|
debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_enabled_lib_feature(&mut self, symbol: Symbol, span: Span) {
|
pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
|
||||||
self.enabled_lib_features.push((symbol, span));
|
self.enabled_lib_features.push((name, span));
|
||||||
self.enabled_features.insert(symbol);
|
self.enabled_features.insert(name);
|
||||||
|
// Ensure we don't skip a `set_enabled` call.
|
||||||
|
debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is intended for hashing the set of enabled language features.
|
/// This is intended for hashing the set of enabled language features.
|
||||||
@ -93,9 +103,36 @@ pub fn set_enabled_lib_feature(&mut self, symbol: Symbol, span: Span) {
|
|||||||
[$(self.$feature as u8),+]
|
[$(self.$feature as u8),+]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
|
||||||
|
&self.enabled_lang_features
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enabled_lib_features(&self) -> &Vec<(Symbol, Span)> {
|
||||||
|
&self.enabled_lib_features
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enabled_features(&self) -> &FxHashSet<Symbol> {
|
||||||
|
&self.enabled_features
|
||||||
|
}
|
||||||
|
|
||||||
/// Is the given feature enabled (via `#[feature(...)]`)?
|
/// Is the given feature enabled (via `#[feature(...)]`)?
|
||||||
pub fn enabled(&self, feature: Symbol) -> bool {
|
pub fn enabled(&self, feature: Symbol) -> bool {
|
||||||
self.enabled_features.contains(&feature)
|
let e = self.enabled_features.contains(&feature);
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
// Ensure this matches `self.$feature`, if that exists.
|
||||||
|
let e2 = match feature {
|
||||||
|
$( sym::$feature => Some(self.$feature), )*
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(e2) = e2 {
|
||||||
|
assert_eq!(
|
||||||
|
e, e2,
|
||||||
|
"mismatch in feature state for `{feature}`: \
|
||||||
|
`enabled_features` says {e} but `self.{feature}` says {e2}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some features are known to be incomplete and using them is likely to have
|
/// Some features are known to be incomplete and using them is likely to have
|
||||||
|
@ -2288,10 +2288,10 @@ impl EarlyLintPass for IncompleteInternalFeatures {
|
|||||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
||||||
let features = cx.builder.features();
|
let features = cx.builder.features();
|
||||||
features
|
features
|
||||||
.enabled_lang_features
|
.enabled_lang_features()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, span, _)| (name, span))
|
.map(|(name, span, _)| (name, span))
|
||||||
.chain(features.enabled_lib_features.iter().map(|(name, span)| (name, span)))
|
.chain(features.enabled_lib_features().iter().map(|(name, span)| (name, span)))
|
||||||
.filter(|(&name, _)| features.incomplete(name) || features.internal(name))
|
.filter(|(&name, _)| features.incomplete(name) || features.internal(name))
|
||||||
.for_each(|(&name, &span)| {
|
.for_each(|(&name, &span)| {
|
||||||
if features.incomplete(name) {
|
if features.incomplete(name) {
|
||||||
|
@ -935,7 +935,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||||||
tcx.hir().visit_all_item_likes_in_crate(&mut missing);
|
tcx.hir().visit_all_item_likes_in_crate(&mut missing);
|
||||||
}
|
}
|
||||||
|
|
||||||
let enabled_lang_features = &tcx.features().enabled_lang_features;
|
let enabled_lang_features = tcx.features().enabled_lang_features();
|
||||||
let mut lang_features = UnordSet::default();
|
let mut lang_features = UnordSet::default();
|
||||||
for &(feature, span, since) in enabled_lang_features {
|
for &(feature, span, since) in enabled_lang_features {
|
||||||
if let Some(since) = since {
|
if let Some(since) = since {
|
||||||
@ -948,7 +948,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let enabled_lib_features = &tcx.features().enabled_lib_features;
|
let enabled_lib_features = tcx.features().enabled_lib_features();
|
||||||
let mut remaining_lib_features = FxIndexMap::default();
|
let mut remaining_lib_features = FxIndexMap::default();
|
||||||
for (feature, span) in enabled_lib_features {
|
for (feature, span) in enabled_lib_features {
|
||||||
if remaining_lib_features.contains_key(&feature) {
|
if remaining_lib_features.contains_key(&feature) {
|
||||||
|
@ -112,8 +112,8 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
|
|||||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
|
||||||
// Unfortunately we cannot exhaustively list fields here, since the
|
// Unfortunately we cannot exhaustively list fields here, since the
|
||||||
// struct is macro generated.
|
// struct is macro generated.
|
||||||
self.enabled_lang_features.hash_stable(hcx, hasher);
|
self.enabled_lang_features().hash_stable(hcx, hasher);
|
||||||
self.enabled_lib_features.hash_stable(hcx, hasher);
|
self.enabled_lib_features().hash_stable(hcx, hasher);
|
||||||
|
|
||||||
self.all_lang_features()[..].hash_stable(hcx, hasher);
|
self.all_lang_features()[..].hash_stable(hcx, hasher);
|
||||||
for feature in rustc_feature::UNSTABLE_FEATURES.iter() {
|
for feature in rustc_feature::UNSTABLE_FEATURES.iter() {
|
||||||
|
Loading…
Reference in New Issue
Block a user