require trait impls to have matching const stabilities as the traits
This commit is contained in:
parent
00f245915b
commit
ef66cbb27b
8 changed files with 200 additions and 15 deletions
|
@ -94,6 +94,11 @@ pub fn rustc_allow_const_fn_unstable(
|
||||||
/// world into two functions: those that are safe to expose on stable (and hence may not use
|
/// world into two functions: those that are safe to expose on stable (and hence may not use
|
||||||
/// unstable features, not even recursively), and those that are not.
|
/// unstable features, not even recursively), and those that are not.
|
||||||
pub fn is_fn_or_trait_safe_to_expose_on_stable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
pub fn is_fn_or_trait_safe_to_expose_on_stable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
|
// A default body in a `#[const_trait]` is const-stable when the trait is const-stable.
|
||||||
|
if tcx.is_const_default_method(def_id) {
|
||||||
|
return is_fn_or_trait_safe_to_expose_on_stable(tcx, tcx.parent(def_id));
|
||||||
|
}
|
||||||
|
|
||||||
match tcx.lookup_const_stability(def_id) {
|
match tcx.lookup_const_stability(def_id) {
|
||||||
None => {
|
None => {
|
||||||
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
|
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
|
||||||
|
|
|
@ -725,6 +725,12 @@ passes_target_feature_on_statement =
|
||||||
.warn = {-passes_previously_accepted}
|
.warn = {-passes_previously_accepted}
|
||||||
.label = {passes_should_be_applied_to_fn.label}
|
.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 =
|
passes_trait_impl_const_stable =
|
||||||
trait implementations cannot be const stable yet
|
trait implementations cannot be const stable yet
|
||||||
.note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
.note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||||
|
|
|
@ -1552,6 +1552,45 @@ pub(crate) struct TraitImplConstStable {
|
||||||
pub span: Span,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_unknown_feature, code = E0635)]
|
#[diag(passes_unknown_feature, code = E0635)]
|
||||||
pub(crate) struct UnknownFeature {
|
pub(crate) struct UnknownFeature {
|
||||||
|
|
|
@ -313,7 +313,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
.map(|(stab, _span)| ConstStability::from_partial(stab, const_stability_indirect));
|
.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 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.
|
// We only ever inherit unstable features.
|
||||||
let Some(inherit_regular_stab) =
|
let Some(inherit_regular_stab) =
|
||||||
final_stab.filter(|s| s.is_unstable())
|
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()
|
if features.const_trait_impl()
|
||||||
&& self.tcx.is_const_trait_impl(item.owner_id.to_def_id())
|
&& let hir::Constness::Const = constness
|
||||||
&& const_stab.is_some_and(|stab| stab.is_const_stable())
|
|
||||||
{
|
{
|
||||||
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 {
|
if let hir::Constness::Const = constness
|
||||||
rustc_hir::Constness::Const => {
|
&& let Some(def_id) = t.trait_def_id()
|
||||||
if let Some(def_id) = t.trait_def_id() {
|
{
|
||||||
// FIXME(const_trait_impl): Improve the span here.
|
// FIXME(const_trait_impl): Improve the span here.
|
||||||
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
|
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
|
||||||
}
|
|
||||||
}
|
|
||||||
rustc_hir::Constness::NotConst => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for impl_item_ref in *items {
|
for impl_item_ref in *items {
|
||||||
|
|
|
@ -96,6 +96,7 @@ pub trait Add<Rhs = Self> {
|
||||||
macro_rules! add_impl {
|
macro_rules! add_impl {
|
||||||
($($t:ty)*) => ($(
|
($($t:ty)*) => ($(
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
|
||||||
impl const Add for $t {
|
impl const Add for $t {
|
||||||
type Output = $t;
|
type Output = $t;
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@ pub trait Deref {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||||
impl<T: ?Sized> const Deref for &T {
|
impl<T: ?Sized> const Deref for &T {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
|
@ -163,6 +164,7 @@ impl<T: ?Sized> const Deref for &T {
|
||||||
impl<T: ?Sized> !DerefMut for &T {}
|
impl<T: ?Sized> !DerefMut for &T {}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||||
impl<T: ?Sized> const Deref for &mut T {
|
impl<T: ?Sized> const Deref for &mut T {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
|
@ -273,6 +275,7 @@ pub trait DerefMut: ~const Deref {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||||
impl<T: ?Sized> const DerefMut for &mut T {
|
impl<T: ?Sized> const DerefMut for &mut T {
|
||||||
fn deref_mut(&mut self) -> &mut T {
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
*self
|
*self
|
||||||
|
|
|
@ -85,4 +85,36 @@ const fn implicitly_stable_const_context() {
|
||||||
//~^ ERROR cannot use `#[feature(const_trait_impl)]`
|
//~^ ERROR cannot use `#[feature(const_trait_impl)]`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check that const stability of impls and traits must match
|
||||||
|
#[const_trait]
|
||||||
|
#[rustc_const_unstable(feature = "beef", issue = "none")]
|
||||||
|
trait U {}
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
|
||||||
|
trait S {}
|
||||||
|
|
||||||
|
// implied stable
|
||||||
|
impl const U for u8 {}
|
||||||
|
//~^ const stability on the impl does not match the const stability on the trait
|
||||||
|
|
||||||
|
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
|
||||||
|
impl const U for u16 {}
|
||||||
|
//~^ const stability on the impl does not match the const stability on the trait
|
||||||
|
//~| trait implementations cannot be const stable yet
|
||||||
|
|
||||||
|
#[rustc_const_unstable(feature = "beef", issue = "none")]
|
||||||
|
impl const U for u32 {}
|
||||||
|
|
||||||
|
// implied stable
|
||||||
|
impl const S for u8 {}
|
||||||
|
|
||||||
|
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
|
||||||
|
impl const S for u16 {}
|
||||||
|
//~^ trait implementations cannot be const stable yet
|
||||||
|
|
||||||
|
#[rustc_const_unstable(feature = "beef", issue = "none")]
|
||||||
|
impl const S for u32 {}
|
||||||
|
//~^ const stability on the impl does not match the const stability on the trait
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,70 @@
|
||||||
|
error: const stability on the impl does not match the const stability on the trait
|
||||||
|
--> $DIR/staged-api.rs:98:1
|
||||||
|
|
|
||||||
|
LL | impl const U for u8 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: this impl is (implicitly) stable...
|
||||||
|
--> $DIR/staged-api.rs:98:1
|
||||||
|
|
|
||||||
|
LL | impl const U for u8 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...but the trait is unstable
|
||||||
|
--> $DIR/staged-api.rs:91:7
|
||||||
|
|
|
||||||
|
LL | trait U {}
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: trait implementations cannot be const stable yet
|
||||||
|
--> $DIR/staged-api.rs:102:1
|
||||||
|
|
|
||||||
|
LL | impl const U for u16 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||||
|
|
||||||
|
error: const stability on the impl does not match the const stability on the trait
|
||||||
|
--> $DIR/staged-api.rs:102:1
|
||||||
|
|
|
||||||
|
LL | impl const U for u16 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: this impl is (implicitly) stable...
|
||||||
|
--> $DIR/staged-api.rs:102:1
|
||||||
|
|
|
||||||
|
LL | impl const U for u16 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...but the trait is unstable
|
||||||
|
--> $DIR/staged-api.rs:91:7
|
||||||
|
|
|
||||||
|
LL | trait U {}
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: trait implementations cannot be const stable yet
|
||||||
|
--> $DIR/staged-api.rs:113:1
|
||||||
|
|
|
||||||
|
LL | impl const S for u16 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||||
|
|
||||||
|
error: const stability on the impl does not match the const stability on the trait
|
||||||
|
--> $DIR/staged-api.rs:117:1
|
||||||
|
|
|
||||||
|
LL | impl const S for u32 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: this impl is unstable...
|
||||||
|
--> $DIR/staged-api.rs:117:1
|
||||||
|
|
|
||||||
|
LL | impl const S for u32 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...but the trait is stable
|
||||||
|
--> $DIR/staged-api.rs:95:7
|
||||||
|
|
|
||||||
|
LL | trait S {}
|
||||||
|
| ^
|
||||||
|
|
||||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
|
||||||
--> $DIR/staged-api.rs:38:5
|
--> $DIR/staged-api.rs:38:5
|
||||||
|
|
|
|
||||||
|
@ -323,5 +390,5 @@ LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
|
||||||
LL | const fn implicitly_stable_const_context() {
|
LL | const fn implicitly_stable_const_context() {
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 19 previous errors
|
error: aborting due to 24 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue