1
Fork 0

require trait impls to have matching const stabilities as the traits

This commit is contained in:
Deadbeef 2025-02-07 21:58:08 +08:00
parent 00f245915b
commit ef66cbb27b
8 changed files with 200 additions and 15 deletions

View file

@ -725,6 +725,12 @@ passes_target_feature_on_statement =
.warn = {-passes_previously_accepted}
.label = {passes_should_be_applied_to_fn.label}
passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait
passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable...
passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable...
passes_trait_impl_const_stability_mismatch_trait_stable = ...but the trait is stable
passes_trait_impl_const_stability_mismatch_trait_unstable = ...but the trait is unstable
passes_trait_impl_const_stable =
trait implementations cannot be const stable yet
.note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information

View file

@ -1552,6 +1552,45 @@ pub(crate) struct TraitImplConstStable {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_trait_impl_const_stability_mismatch)]
pub(crate) struct TraitImplConstStabilityMismatch {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub impl_stability: ImplConstStability,
#[subdiagnostic]
pub trait_stability: TraitConstStability,
}
#[derive(Subdiagnostic)]
pub(crate) enum TraitConstStability {
#[note(passes_trait_impl_const_stability_mismatch_trait_stable)]
Stable {
#[primary_span]
span: Span,
},
#[note(passes_trait_impl_const_stability_mismatch_trait_unstable)]
Unstable {
#[primary_span]
span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum ImplConstStability {
#[note(passes_trait_impl_const_stability_mismatch_impl_stable)]
Stable {
#[primary_span]
span: Span,
},
#[note(passes_trait_impl_const_stability_mismatch_impl_unstable)]
Unstable {
#[primary_span]
span: Span,
},
}
#[derive(Diagnostic)]
#[diag(passes_unknown_feature, code = E0635)]
pub(crate) struct UnknownFeature {

View file

@ -313,7 +313,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
.map(|(stab, _span)| ConstStability::from_partial(stab, const_stability_indirect));
// If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
// We only ever inherit unstable features.
let Some(inherit_regular_stab) =
final_stab.filter(|s| s.is_unstable())
@ -826,24 +826,56 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
}
}
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
// needs to have an error emitted.
if features.const_trait_impl()
&& self.tcx.is_const_trait_impl(item.owner_id.to_def_id())
&& const_stab.is_some_and(|stab| stab.is_const_stable())
&& let hir::Constness::Const = constness
{
self.tcx.dcx().emit_err(errors::TraitImplConstStable { span: item.span });
let stable_or_implied_stable = match const_stab {
None => true,
Some(stab) if stab.is_const_stable() => {
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
// needs to have an error emitted.
// Note: Remove this error once `const_trait_impl` is stabilized
self.tcx
.dcx()
.emit_err(errors::TraitImplConstStable { span: item.span });
true
}
Some(_) => false,
};
if let Some(trait_id) = t.trait_def_id()
&& let Some(const_stab) = self.tcx.lookup_const_stability(trait_id)
{
// the const stability of a trait impl must match the const stability on the trait.
if const_stab.is_const_stable() != stable_or_implied_stable {
let trait_span = self.tcx.def_ident_span(trait_id).unwrap();
let impl_stability = if stable_or_implied_stable {
errors::ImplConstStability::Stable { span: item.span }
} else {
errors::ImplConstStability::Unstable { span: item.span }
};
let trait_stability = if const_stab.is_const_stable() {
errors::TraitConstStability::Stable { span: trait_span }
} else {
errors::TraitConstStability::Unstable { span: trait_span }
};
self.tcx.dcx().emit_err(errors::TraitImplConstStabilityMismatch {
span: item.span,
impl_stability,
trait_stability,
});
}
}
}
}
match constness {
rustc_hir::Constness::Const => {
if let Some(def_id) = t.trait_def_id() {
// FIXME(const_trait_impl): Improve the span here.
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
}
}
rustc_hir::Constness::NotConst => {}
if let hir::Constness::Const = constness
&& let Some(def_id) = t.trait_def_id()
{
// FIXME(const_trait_impl): Improve the span here.
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
}
for impl_item_ref in *items {