Auto merge of #140399 - tiif:unstable_impl, r=lcnr,BoxyUwU
Implement unstable trait impl This PR allows marking impls of stable trait with stable type as unstable. ## Approach In std/core, an impl can be marked as unstable by annotating it with ``#[unstable_feature_bound(feat_name)]``. This will add a ``ClauseKind::Unstable_Feature(feat_name)`` to the list of predicates in ``predicates_of`` . When an unstable impl's function is called, we will first iterate through all the goals in ``param_env`` to check if there is any ``ClauseKind::UnstableFeature(feat_name)`` in ``param_env``. The existence of ``ClauseKind::Unstable_Feature(feat_name)`` in ``param_env`` means an``#[unstable_feature_bound(feat_name)]`` is present at the call site of the function, so we allow the check to succeed in this case. If ``ClauseKind::UnstableFeature(feat_name)`` does not exist in ``param_env``, we will still allow the check to succeed for either of the cases below: 1. The feature is enabled through ``#[feature(feat_name)]`` outside of std / core. 2. We are in codegen because we may be monomorphizing a body from an upstream crate which had an unstable feature enabled that the downstream crate do not. For the rest of the case, it will fail with ambiguity. ## Limitation In this PR, we do not support: 1. using items that need ``#[unstable_feature_bound]`` within stable APIs 2. annotate main function with ``#[unstable_feature_bound]`` 3. annotate ``#[unstable_feature_bound]`` on items other than free function and impl ## Acknowledgement The design and mentoring are done by `@BoxyUwU`
This commit is contained in:
@@ -27,6 +27,26 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct UnstableFeatureBoundParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
|
||||
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
|
||||
type Item = (Symbol, Span);
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
if !cx.features().staged_api() {
|
||||
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
|
||||
}
|
||||
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
|
||||
.into_iter()
|
||||
.zip(iter::repeat(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AllowConstFnUnstableParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
|
||||
|
||||
@@ -98,6 +98,16 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability {
|
||||
for other_attr in cx.all_attrs {
|
||||
if other_attr.word_is(sym::unstable_feature_bound) {
|
||||
cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability {
|
||||
span: cx.target_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (stability, span) = self.stability?;
|
||||
|
||||
Some(AttributeKind::Stability { stability, span })
|
||||
|
||||
@@ -13,7 +13,9 @@ use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirI
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
|
||||
use crate::attributes::allow_unstable::{
|
||||
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
|
||||
};
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser,
|
||||
OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
|
||||
@@ -133,6 +135,7 @@ attribute_parsers!(
|
||||
Combine<AllowInternalUnstableParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
// tidy-alphabetical-start
|
||||
|
||||
@@ -503,6 +503,14 @@ pub(crate) struct UnrecognizedReprHint {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
|
||||
#[help]
|
||||
pub(crate) struct UnstableFeatureBoundIncompatibleStability {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
|
||||
pub(crate) struct NakedFunctionIncompatibleAttribute {
|
||||
|
||||
Reference in New Issue
Block a user