Rollup merge of #96478 - WaffleLapkin:rustc_default_body_unstable, r=Aaron1011
Implement `#[rustc_default_body_unstable]` This PR implements a new stability attribute — `#[rustc_default_body_unstable]`. `#[rustc_default_body_unstable]` controls the stability of default bodies in traits. For example: ```rust pub trait Trait { #[rustc_default_body_unstable(feature = "feat", isssue = "none")] fn item() {} } ``` In order to implement `Trait` user needs to either - implement `item` (even though it has a default implementation) - enable `#![feature(feat)]` This is useful in conjunction with [`#[rustc_must_implement_one_of]`](https://github.com/rust-lang/rust/pull/92164), we may want to relax requirements for a trait, for example allowing implementing either of `PartialEq::{eq, ne}`, but do so in a safe way — making implementation of only `PartialEq::ne` unstable. r? `@Aaron1011` cc `@nrc` (iirc you were interested in this wrt `read_buf`), `@danielhenrymantilla` (you were interested in the related `#[rustc_must_implement_one_of]`) P.S. This is my first time working with stability attributes, so I'm not sure if I did everything right 😅
This commit is contained in:
commit
1dc4858914
22 changed files with 348 additions and 28 deletions
|
@ -29,11 +29,16 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
}
|
||||
|
||||
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
|
||||
let stab_attrs =
|
||||
[sym::stable, sym::unstable, sym::rustc_const_stable, sym::rustc_const_unstable];
|
||||
let stab_attrs = [
|
||||
sym::stable,
|
||||
sym::unstable,
|
||||
sym::rustc_const_stable,
|
||||
sym::rustc_const_unstable,
|
||||
sym::rustc_default_body_unstable,
|
||||
];
|
||||
|
||||
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
|
||||
// #[rustc_const_stable(…)], or #[rustc_const_unstable(…)].
|
||||
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
|
||||
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
|
||||
let meta_kind = attr.meta_kind();
|
||||
if let Some(MetaItemKind::List(ref metas)) = meta_kind {
|
||||
|
@ -53,8 +58,12 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
// This additional check for stability is to make sure we
|
||||
// don't emit additional, irrelevant errors for malformed
|
||||
// attributes.
|
||||
let is_unstable =
|
||||
matches!(*stab_attr, sym::unstable | sym::rustc_const_unstable);
|
||||
let is_unstable = matches!(
|
||||
*stab_attr,
|
||||
sym::unstable
|
||||
| sym::rustc_const_unstable
|
||||
| sym::rustc_default_body_unstable
|
||||
);
|
||||
if since.is_some() || is_unstable {
|
||||
return Some((feature, since, attr.span));
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//! A pass that annotates every item and method with its stability level,
|
||||
//! propagating default levels lexically from parent to children ast nodes.
|
||||
|
||||
use attr::StabilityLevel;
|
||||
use rustc_attr::{self as attr, ConstStability, Stability, Unstable, UnstableReason};
|
||||
use rustc_attr::{
|
||||
self as attr, ConstStability, Stability, StabilityLevel, Unstable, UnstableReason,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
use rustc_hir as hir;
|
||||
|
@ -161,7 +162,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
||||
let (stab, const_stab, body_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
||||
let mut const_span = None;
|
||||
|
||||
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
|
||||
|
@ -209,6 +210,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((body_stab, _span)) = body_stab {
|
||||
// FIXME: check that this item can have body stability
|
||||
|
||||
self.index.default_body_stab_map.insert(def_id, body_stab);
|
||||
debug!(?self.index.default_body_stab_map);
|
||||
}
|
||||
|
||||
let stab = stab.map(|(stab, span)| {
|
||||
// Error if prohibited, or can't inherit anything from a container.
|
||||
if kind == AnnotationKind::Prohibited
|
||||
|
@ -613,6 +621,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
|||
let mut index = Index {
|
||||
stab_map: Default::default(),
|
||||
const_stab_map: Default::default(),
|
||||
default_body_stab_map: Default::default(),
|
||||
depr_map: Default::default(),
|
||||
implications: Default::default(),
|
||||
};
|
||||
|
@ -673,6 +682,9 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
stability_implications: |tcx, _| tcx.stability().implications.clone(),
|
||||
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
|
||||
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
|
||||
lookup_default_body_stability: |tcx, id| {
|
||||
tcx.stability().local_default_body_stability(id.expect_local())
|
||||
},
|
||||
lookup_deprecation_entry: |tcx, id| {
|
||||
tcx.stability().local_deprecation_entry(id.expect_local())
|
||||
},
|
||||
|
@ -723,7 +735,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
let features = self.tcx.features();
|
||||
if features.staged_api {
|
||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item.span);
|
||||
let (stab, const_stab, _) =
|
||||
attr::find_stability(&self.tcx.sess, attrs, item.span);
|
||||
|
||||
// If this impl block has an #[unstable] attribute, give an
|
||||
// error if all involved types and traits are stable, because
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue