1
Fork 0

Implement #[rustc_default_body_unstable]

This attribute allows to mark default body of a trait function as
unstable. This means that implementing the trait without implementing
the function will require enabling unstable feature.

This is useful in conjunction with `#[rustc_must_implement_one_of]`,
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.
This commit is contained in:
Maybe Waffle 2022-04-27 18:14:19 +04:00
parent 96b9bb4620
commit 177af47104
14 changed files with 206 additions and 17 deletions

View file

@ -131,6 +131,14 @@ impl ConstStability {
}
}
/// Represents the `#[rustc_default_body_unstable]` attribute.
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct DefaultBodyStability {
pub level: StabilityLevel,
pub feature: Symbol,
}
/// The available stability levels.
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
@ -214,7 +222,8 @@ pub fn find_stability(
sess: &Session,
attrs: &[Attribute],
item_sp: Span,
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) {
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
{
find_stability_generic(sess, attrs.iter(), item_sp)
}
@ -222,7 +231,7 @@ fn find_stability_generic<'a, I>(
sess: &Session,
attrs_iter: I,
item_sp: Span,
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>)
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
where
I: Iterator<Item = &'a Attribute>,
{
@ -230,6 +239,7 @@ where
let mut stab: Option<(Stability, Span)> = None;
let mut const_stab: Option<(ConstStability, Span)> = None;
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
let mut promotable = false;
let mut allowed_through_unstable_modules = false;
@ -243,6 +253,7 @@ where
sym::stable,
sym::rustc_promotable,
sym::rustc_allowed_through_unstable_modules,
sym::rustc_default_body_unstable,
]
.iter()
.any(|&s| attr.has_name(s))
@ -280,7 +291,7 @@ where
let meta_name = meta.name_or_empty();
match meta_name {
sym::rustc_const_unstable | sym::unstable => {
sym::rustc_const_unstable | sym::rustc_default_body_unstable | sym::unstable => {
if meta_name == sym::unstable && stab.is_some() {
handle_errors(
&sess.parse_sess,
@ -295,6 +306,13 @@ where
AttrError::MultipleStabilityLevels,
);
break;
} else if meta_name == sym::rustc_default_body_unstable && body_stab.is_some() {
handle_errors(
&sess.parse_sess,
attr.span,
AttrError::MultipleStabilityLevels,
);
break;
}
let mut feature = None;
@ -405,11 +423,14 @@ where
};
if sym::unstable == meta_name {
stab = Some((Stability { level, feature }, attr.span));
} else {
} else if sym::rustc_const_unstable == meta_name {
const_stab = Some((
ConstStability { level, feature, promotable: false },
attr.span,
));
} else {
body_stab =
Some((DefaultBodyStability { level, feature }, attr.span));
}
}
(None, _, _) => {
@ -542,7 +563,7 @@ where
}
}
(stab, const_stab)
(stab, const_stab, body_stab)
}
pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {