Description
The predicates_of
query currently inserts Self: Trait
as a generic predicate for traits. This could become Self: ~const Trait
and probably resolves some of the hackery around default_method_body_is_const
. For example, we have explicitly allowed calling other methods inside the same trait for default_method_body_is_const
bodies during const checking. If we had Self: ~const Trait
as a caller bound then we don't need to explicitly allow this.
There is also another issue that would be resolved by this:
#![feature(const_trait_impl)]
#![feature(const_fn_trait_bound)]
pub trait Foo {
#[default_method_body_is_const]
fn do_stuff(self) where Self: Sized {
do_stuff_as_foo(self);
}
}
const fn do_stuff_as_foo<T: ~const Foo>(foo: T) {
std::mem::forget(foo);
}
The snippet above currently fails to compile. If we had Self: ~const Foo
then it would work.
The problem is that I tried doing this and there was a lot of mysterious errors. So I limited Self: ~const Trait
to default_method_body_is_const
methods. It compiled but some ui tests related to object safety fails after the change. Below is the diff of my current progress:
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index e7b728d491b..74ca462c470 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1986,6 +1986,14 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
let mut result = tcx.predicates_defined_on(def_id);
+ if tcx.has_attr(def_id, sym::default_method_body_is_const) {
+ let span = rustc_span::DUMMY_SP;
+ result.predicates =
+ tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
+ ty::TraitRef::identity(tcx, tcx.parent(def_id).unwrap()).with_constness(ty::BoundConstness::ConstIfConst).to_predicate(tcx),
+ span,
+ ))));
+ }
if tcx.is_trait(def_id) {
// For traits, add `Self: Trait` predicate. This is
// not part of the predicates that a user writes, but it
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index deed9901cc9..61d5352be2c 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1243,7 +1243,8 @@ mod impls {
macro_rules! partial_eq_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
- impl PartialEq for $t {
+ #[rustc_const_unstable(feature = "const_cmp", issue = "none")]
+ impl const PartialEq for $t {
#[inline]
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
#[inline]
@@ -1280,10 +1281,11 @@ impl Eq for $t {}
macro_rules! partial_ord_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
- impl PartialOrd for $t {
+ #[rustc_const_unstable(feature = "const_cmp", issue = "none")]
+ impl const PartialOrd for $t {
#[inline]
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
- match (self <= other, self >= other) {
+ match (*self <= *other, *self >= *other) {
(false, false) => None,
(false, true) => Some(Greater),
(true, false) => Some(Less),
@@ -1323,10 +1325,13 @@ fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
macro_rules! ord_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
- impl PartialOrd for $t {
+ #[rustc_const_unstable(feature = "const_cmp", issue = "none")]
+ impl const PartialOrd for $t {
#[inline]
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
- Some(self.cmp(other))
+ Some(if *self < *other { Less }
+ else if *self == *other { Equal }
+ else { Greater })
}
#[inline]
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }