Skip to content

const_trait_impl: investigate how to put Self: ~const Trait bounds in traits #92158

Closed
@fee1-dead

Description

@fee1-dead

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) }

Metadata

Metadata

Assignees

Labels

A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)F-const_trait_impl`#![feature(const_trait_impl)]`

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions