https://gcc.gnu.org/g:1223585918cf691ebd0214f4c5134cbf355c54bc

commit r16-2878-g1223585918cf691ebd0214f4c5134cbf355c54bc
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Tue Jun 17 11:32:21 2025 +0100

    gccrs: Fix issues around PartialEq Eq Ord Partial Ord
    
    There is still an issue with derive on PartialOrd but this adds good tests
    and fixes a bug we had handling the default Rhs = Self generic type param
    substitutions on the comparison traits.
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-tyty.cc (ParamType::handle_substitions): make this 
consistent
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/bug-with-default-generic.rs: New test.
            * rust/execute/torture/partial-eq-1.rs: New test.
            * rust/execute/torture/partial-eq-2.rs: New test.
            * rust/execute/torture/partial-eq-3.rs: New test.
            * rust/execute/torture/partial-eq-4.rs: New test.
            * rust/execute/torture/partial-ord-1.rs: New test.
            * rust/execute/torture/partial-ord-2.rs: New test.
            * rust/execute/torture/partial-ord-3.rs: New test.
            * rust/execute/torture/partial-ord-4.rs: New test.
            * rust/execute/torture/partial-ord-5.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-tyty.cc                    |  10 +-
 .../rust/compile/bug-with-default-generic.rs       |  15 +
 gcc/testsuite/rust/execute/torture/partial-eq-1.rs | 103 +++++
 gcc/testsuite/rust/execute/torture/partial-eq-2.rs |  60 +++
 gcc/testsuite/rust/execute/torture/partial-eq-3.rs | 457 +++++++++++++++++++
 gcc/testsuite/rust/execute/torture/partial-eq-4.rs | 457 +++++++++++++++++++
 .../rust/execute/torture/partial-ord-1.rs          | 101 +++++
 .../rust/execute/torture/partial-ord-2.rs          | 469 ++++++++++++++++++++
 .../rust/execute/torture/partial-ord-3.rs          | 489 +++++++++++++++++++++
 .../rust/execute/torture/partial-ord-4.rs          | 115 +++++
 .../rust/execute/torture/partial-ord-5.rs          | 487 ++++++++++++++++++++
 11 files changed, 2758 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 91c68efe972d..e2dfa743b9aa 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -3545,12 +3545,12 @@ ParamType::handle_substitions 
(SubstitutionArgumentMappings &subst_mappings)
   ParamType *p = static_cast<ParamType *> (clone ());
   subst_mappings.on_param_subst (*p, arg);
 
-  // there are two cases one where we substitute directly to a new PARAM and
-  // otherwise
-  if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
+  const BaseType *resolved = arg.get_tyty ();
+  if (resolved->get_kind () == TyTy::TypeKind::PARAM)
     {
-      p->set_ty_ref (arg.get_tyty ()->get_ref ());
-      return p;
+      const ParamType &pp = *static_cast<const ParamType *> (resolved);
+      if (pp.can_resolve ())
+       resolved = pp.resolve ();
     }
 
   // this is the new subst that this needs to pass
diff --git a/gcc/testsuite/rust/compile/bug-with-default-generic.rs 
b/gcc/testsuite/rust/compile/bug-with-default-generic.rs
new file mode 100644
index 000000000000..25f46a09c7dc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bug-with-default-generic.rs
@@ -0,0 +1,15 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait MyBinaryTrait<Rhs = Self> {
+    fn do_something(&self, rhs: &Rhs);
+}
+
+struct Foo<T> {
+    // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+    value: T,
+}
+
+impl<T> MyBinaryTrait for Foo<T> {
+    fn do_something(&self, _rhs: &Self) {}
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-1.rs 
b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs
new file mode 100644
index 000000000000..db123a1b5e7d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs
@@ -0,0 +1,103 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+mod core {
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[lang = "sized"]
+        pub trait Sized {}
+    }
+
+    pub mod cmp {
+        use super::marker::Sized;
+
+        #[lang = "eq"]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        pub trait Eq: PartialEq<Self> {
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+    }
+}
+
+use core::cmp::{Eq, PartialEq};
+
+// PartialEq for i32 and u32 so we can compare across types
+impl PartialEq<u32> for i32 {
+    fn eq(&self, other: &u32) -> bool {
+        *self >= 0 && (*self as u32) == *other
+    }
+}
+impl PartialEq<i32> for u32 {
+    fn eq(&self, other: &i32) -> bool {
+        *other >= 0 && *self == *other as u32
+    }
+}
+
+// Our generic struct
+struct Foo<T> {
+    value: T,
+}
+
+// Manual impl of PartialEq for different generic params
+impl<T, U> PartialEq<Foo<U>> for Foo<T>
+where
+    T: PartialEq<U>,
+{
+    fn eq(&self, other: &Foo<U>) -> bool {
+        self.value.eq(&other.value)
+    }
+}
+
+impl<T: PartialEq> Eq for Foo<T> {}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { value: 42i32 };
+    let b = Foo { value: 42u32 };
+    let c = Foo { value: 7u32 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a == c {
+        print("a == c");
+    } else {
+        print("a != c");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-2.rs 
b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs
new file mode 100644
index 000000000000..debed8c83f32
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs
@@ -0,0 +1,60 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+    fn eq(&self, other: &Rhs) -> bool;
+
+    fn ne(&self, other: &Rhs) -> bool {
+        !self.eq(other)
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+struct Foo<T> {
+    value: T,
+}
+
+impl<T: PartialEq> PartialEq for Foo<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.value.eq(&other.value)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { value: 42i32 };
+    let b = Foo { value: 42i32 };
+    let c = Foo { value: 99i32 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a == c {
+        print("a == c");
+    } else {
+        print("a != c");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-3.rs 
b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs
new file mode 100644
index 000000000000..849910afc832
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs
@@ -0,0 +1,457 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        // #[rustc_diagnostic_item = "option_type"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Option<T> {
+            /// No value
+            #[lang = "None"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            None,
+            /// Some value `T`
+            #[lang = "Some"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(PartialEq)]`")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(Eq)]`")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[lang = "sized"]
+        // #[rustc_on_unimplemented(
+        //     message = "the size for values of type `{Self}` cannot be known 
at compilation time",
+        //     label = "doesn't have a size known at compile-time"
+        // )]
+        // #[fundamental] // for Default, for example, which requires that 
`[T]: !Default` be evaluatable
+        // #[rustc_specialization_trait]
+        pub trait Sized {
+            // Empty.
+        }
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Ordering {
+            /// An ordering where a compared value is less than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Less = -1,
+            /// An ordering where a compared value is equal to another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Equal = 0,
+            /// An ordering where a compared value is greater than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} == {Rhs}`"
+        // )]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            /// This method tests for `self` and `other` values to be equal, 
and is used
+            /// by `==`.
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Eq: PartialEq<Self> {
+            // this method is used solely by #[deriving] to assert
+            // that every component of a type implements #[deriving]
+            // itself, the current deriving infrastructure means doing this
+            // assertion without using a method on this trait is nearly
+            // impossible.
+            //
+            // This should never be implemented by hand.
+            #[doc(hidden)]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} < {Rhs}` and `{Self} > 
{Rhs}`"
+        // )]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            /// This method returns an ordering between `self` and `other` 
values if one exists.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// let result = 1.0.partial_cmp(&2.0);
+            /// assert_eq!(result, Some(Ordering::Less));
+            ///
+            /// let result = 1.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Equal));
+            ///
+            /// let result = 2.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Greater));
+            /// ```
+            ///
+            /// When comparison is impossible:
+            ///
+            /// ```
+            /// let result = f64::NAN.partial_cmp(&1.0);
+            /// assert_eq!(result, None);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            /// This method tests less than (for `self` and `other`) and is 
used by the `<` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 < 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 < 1.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests less than or equal to (for `self` and 
`other`) and is used by the `<=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 <= 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 <= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than (for `self` and `other`) and is 
used by the `>` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 > 2.0;
+            /// assert_eq!(result, false);
+            ///
+            /// let result = 2.0 > 2.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than or equal to (for `self` and 
`other`) and is used by the `>=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 2.0 >= 1.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 >= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        #[doc(alias = "<")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Ord: Eq + PartialOrd<Self> {
+            /// This method returns an [`Ordering`] between `self` and `other`.
+            ///
+            /// By convention, `self.cmp(&other)` returns the ordering 
matching the expression
+            /// `self <operator> other` if true.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// assert_eq!(5.cmp(&10), Ordering::Less);
+            /// assert_eq!(10.cmp(&5), Ordering::Greater);
+            /// assert_eq!(5.cmp(&5), Ordering::Equal);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn cmp(&self, other: &Self) -> Ordering;
+
+            /// Compares and returns the maximum of two values.
+            ///
+            /// Returns the second argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(2, 1.max(2));
+            /// assert_eq!(2, 2.max(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn max(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Compares and returns the minimum of two values.
+            ///
+            /// Returns the first argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(1, 1.min(2));
+            /// assert_eq!(2, 2.min(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn min(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Restrict a value to a certain interval.
+            ///
+            /// Returns `max` if `self` is greater than `max`, and `min` if 
`self` is
+            /// less than `min`. Otherwise this returns `self`.
+            ///
+            /// # Panics
+            ///
+            /// Panics if `min > max`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(clamp)]
+            ///
+            /// assert!((-3).clamp(-2, 1) == -2);
+            /// assert!(0.clamp(-2, 1) == 0);
+            /// assert!(2.clamp(-2, 1) == 1);
+            /// ```
+            #[must_use]
+            #[unstable(feature = "clamp", issue = "44095")]
+            fn clamp(self, min: Self, max: Self) -> Self
+            where
+                Self: Sized,
+            {
+                if self < min {
+                    min
+                } else if self > max {
+                    max
+                } else {
+                    self
+                }
+            }
+        }
+    }
+
+    pub mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self > *other {
+            Ordering::Greater
+        } else if *self < *other {
+            Ordering::Less
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+#[derive(PartialEq)]
+struct Foo {
+    a: i32,
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { a: 42i32 };
+    let b = Foo { a: 42i32 };
+    let c = Foo { a: 7i32 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a == c {
+        print("a == c");
+    } else {
+        print("a != c");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-4.rs 
b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs
new file mode 100644
index 000000000000..b6997d8592fa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs
@@ -0,0 +1,457 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        // #[rustc_diagnostic_item = "option_type"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Option<T> {
+            /// No value
+            #[lang = "None"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            None,
+            /// Some value `T`
+            #[lang = "Some"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(PartialEq)]`")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(Eq)]`")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[lang = "sized"]
+        // #[rustc_on_unimplemented(
+        //     message = "the size for values of type `{Self}` cannot be known 
at compilation time",
+        //     label = "doesn't have a size known at compile-time"
+        // )]
+        // #[fundamental] // for Default, for example, which requires that 
`[T]: !Default` be evaluatable
+        // #[rustc_specialization_trait]
+        pub trait Sized {
+            // Empty.
+        }
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Ordering {
+            /// An ordering where a compared value is less than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Less = -1,
+            /// An ordering where a compared value is equal to another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Equal = 0,
+            /// An ordering where a compared value is greater than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} == {Rhs}`"
+        // )]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            /// This method tests for `self` and `other` values to be equal, 
and is used
+            /// by `==`.
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Eq: PartialEq<Self> {
+            // this method is used solely by #[deriving] to assert
+            // that every component of a type implements #[deriving]
+            // itself, the current deriving infrastructure means doing this
+            // assertion without using a method on this trait is nearly
+            // impossible.
+            //
+            // This should never be implemented by hand.
+            #[doc(hidden)]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} < {Rhs}` and `{Self} > 
{Rhs}`"
+        // )]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            /// This method returns an ordering between `self` and `other` 
values if one exists.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// let result = 1.0.partial_cmp(&2.0);
+            /// assert_eq!(result, Some(Ordering::Less));
+            ///
+            /// let result = 1.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Equal));
+            ///
+            /// let result = 2.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Greater));
+            /// ```
+            ///
+            /// When comparison is impossible:
+            ///
+            /// ```
+            /// let result = f64::NAN.partial_cmp(&1.0);
+            /// assert_eq!(result, None);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            /// This method tests less than (for `self` and `other`) and is 
used by the `<` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 < 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 < 1.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests less than or equal to (for `self` and 
`other`) and is used by the `<=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 <= 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 <= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than (for `self` and `other`) and is 
used by the `>` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 > 2.0;
+            /// assert_eq!(result, false);
+            ///
+            /// let result = 2.0 > 2.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than or equal to (for `self` and 
`other`) and is used by the `>=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 2.0 >= 1.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 >= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        #[doc(alias = "<")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Ord: Eq + PartialOrd<Self> {
+            /// This method returns an [`Ordering`] between `self` and `other`.
+            ///
+            /// By convention, `self.cmp(&other)` returns the ordering 
matching the expression
+            /// `self <operator> other` if true.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// assert_eq!(5.cmp(&10), Ordering::Less);
+            /// assert_eq!(10.cmp(&5), Ordering::Greater);
+            /// assert_eq!(5.cmp(&5), Ordering::Equal);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn cmp(&self, other: &Self) -> Ordering;
+
+            /// Compares and returns the maximum of two values.
+            ///
+            /// Returns the second argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(2, 1.max(2));
+            /// assert_eq!(2, 2.max(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn max(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Compares and returns the minimum of two values.
+            ///
+            /// Returns the first argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(1, 1.min(2));
+            /// assert_eq!(2, 2.min(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn min(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Restrict a value to a certain interval.
+            ///
+            /// Returns `max` if `self` is greater than `max`, and `min` if 
`self` is
+            /// less than `min`. Otherwise this returns `self`.
+            ///
+            /// # Panics
+            ///
+            /// Panics if `min > max`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(clamp)]
+            ///
+            /// assert!((-3).clamp(-2, 1) == -2);
+            /// assert!(0.clamp(-2, 1) == 0);
+            /// assert!(2.clamp(-2, 1) == 1);
+            /// ```
+            #[must_use]
+            #[unstable(feature = "clamp", issue = "44095")]
+            fn clamp(self, min: Self, max: Self) -> Self
+            where
+                Self: Sized,
+            {
+                if self < min {
+                    min
+                } else if self > max {
+                    max
+                } else {
+                    self
+                }
+            }
+        }
+    }
+
+    pub mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self > *other {
+            Ordering::Greater
+        } else if *self < *other {
+            Ordering::Less
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+    a: i32,
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { a: 42i32 };
+    let b = Foo { a: 42i32 };
+    let c = Foo { a: 7i32 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a == c {
+        print("a == c");
+    } else {
+        print("a != c");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-1.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs
new file mode 100644
index 000000000000..a3558e7cb7a9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs
@@ -0,0 +1,101 @@
+/* { dg-output "x == y\r*\nx > z\r*\n" }*/
+#[lang = "sized"]
+pub trait Sized {}
+
+pub enum Option<T> {
+    #[lang = "None"]
+    None,
+    #[lang = "Some"]
+    Some(T),
+}
+
+use Option::{None, Some};
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+    fn eq(&self, other: &Rhs) -> bool;
+
+    fn ne(&self, other: &Rhs) -> bool {
+        !self.eq(other)
+    }
+}
+
+pub enum Ordering {
+    Less = -1,
+    Equal = 0,
+    Greater = 1,
+}
+
+#[lang = "partial_ord"]
+pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+}
+
+// Implement for i32
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// Implement PartialOrd for i32
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self < *other {
+            Some(Ordering::Less)
+        } else if *self > *other {
+            Some(Ordering::Greater)
+        } else {
+            Some(Ordering::Equal)
+        }
+    }
+}
+
+// Struct with manual PartialEq
+struct Foo {
+    a: i32,
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, other: &Self) -> bool {
+        self.a.eq(&other.a)
+    }
+}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.a.partial_cmp(&other.a)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let x = Foo { a: 42 };
+    let y = Foo { a: 42 };
+    let z = Foo { a: 7 };
+
+    match x.partial_cmp(&y) {
+        Some(Ordering::Equal) => print("x == y"),
+        Some(Ordering::Less) => print("x < y"),
+        Some(Ordering::Greater) => print("x > y"),
+        None => print("x ? y"),
+    }
+
+    match x.partial_cmp(&z) {
+        Some(Ordering::Equal) => print("x == z"),
+        Some(Ordering::Less) => print("x < z"),
+        Some(Ordering::Greater) => print("x > z"),
+        None => print("x ? z"),
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-2.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs
new file mode 100644
index 000000000000..d3b713fc5e26
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs
@@ -0,0 +1,469 @@
+/* { dg-output "x == y\r*\nx > z\r*\n" }*/
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        // #[rustc_diagnostic_item = "option_type"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Option<T> {
+            /// No value
+            #[lang = "None"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            None,
+            /// Some value `T`
+            #[lang = "Some"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(PartialEq)]`")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(Eq)]`")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[lang = "sized"]
+        // #[rustc_on_unimplemented(
+        //     message = "the size for values of type `{Self}` cannot be known 
at compilation time",
+        //     label = "doesn't have a size known at compile-time"
+        // )]
+        // #[fundamental] // for Default, for example, which requires that 
`[T]: !Default` be evaluatable
+        // #[rustc_specialization_trait]
+        pub trait Sized {
+            // Empty.
+        }
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Ordering {
+            /// An ordering where a compared value is less than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Less = -1,
+            /// An ordering where a compared value is equal to another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Equal = 0,
+            /// An ordering where a compared value is greater than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} == {Rhs}`"
+        // )]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            /// This method tests for `self` and `other` values to be equal, 
and is used
+            /// by `==`.
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Eq: PartialEq<Self> {
+            // this method is used solely by #[deriving] to assert
+            // that every component of a type implements #[deriving]
+            // itself, the current deriving infrastructure means doing this
+            // assertion without using a method on this trait is nearly
+            // impossible.
+            //
+            // This should never be implemented by hand.
+            #[doc(hidden)]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} < {Rhs}` and `{Self} > 
{Rhs}`"
+        // )]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            /// This method returns an ordering between `self` and `other` 
values if one exists.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// let result = 1.0.partial_cmp(&2.0);
+            /// assert_eq!(result, Some(Ordering::Less));
+            ///
+            /// let result = 1.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Equal));
+            ///
+            /// let result = 2.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Greater));
+            /// ```
+            ///
+            /// When comparison is impossible:
+            ///
+            /// ```
+            /// let result = f64::NAN.partial_cmp(&1.0);
+            /// assert_eq!(result, None);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            /// This method tests less than (for `self` and `other`) and is 
used by the `<` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 < 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 < 1.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests less than or equal to (for `self` and 
`other`) and is used by the `<=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 <= 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 <= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than (for `self` and `other`) and is 
used by the `>` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 > 2.0;
+            /// assert_eq!(result, false);
+            ///
+            /// let result = 2.0 > 2.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than or equal to (for `self` and 
`other`) and is used by the `>=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 2.0 >= 1.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 >= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        #[doc(alias = "<")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Ord: Eq + PartialOrd<Self> {
+            /// This method returns an [`Ordering`] between `self` and `other`.
+            ///
+            /// By convention, `self.cmp(&other)` returns the ordering 
matching the expression
+            /// `self <operator> other` if true.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// assert_eq!(5.cmp(&10), Ordering::Less);
+            /// assert_eq!(10.cmp(&5), Ordering::Greater);
+            /// assert_eq!(5.cmp(&5), Ordering::Equal);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn cmp(&self, other: &Self) -> Ordering;
+
+            /// Compares and returns the maximum of two values.
+            ///
+            /// Returns the second argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(2, 1.max(2));
+            /// assert_eq!(2, 2.max(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn max(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Compares and returns the minimum of two values.
+            ///
+            /// Returns the first argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(1, 1.min(2));
+            /// assert_eq!(2, 2.min(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn min(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Restrict a value to a certain interval.
+            ///
+            /// Returns `max` if `self` is greater than `max`, and `min` if 
`self` is
+            /// less than `min`. Otherwise this returns `self`.
+            ///
+            /// # Panics
+            ///
+            /// Panics if `min > max`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(clamp)]
+            ///
+            /// assert!((-3).clamp(-2, 1) == -2);
+            /// assert!(0.clamp(-2, 1) == 0);
+            /// assert!(2.clamp(-2, 1) == 1);
+            /// ```
+            #[must_use]
+            #[unstable(feature = "clamp", issue = "44095")]
+            fn clamp(self, min: Self, max: Self) -> Self
+            where
+                Self: Sized,
+            {
+                if self < min {
+                    min
+                } else if self > max {
+                    max
+                } else {
+                    self
+                }
+            }
+        }
+    }
+
+    pub mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self > *other {
+            Ordering::Greater
+        } else if *self < *other {
+            Ordering::Less
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+struct Foo {
+    a: i32,
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, other: &'_ Self) -> bool {
+        self.a == other.a
+    }
+}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+        self.a.partial_cmp(&other.a)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let x = Foo { a: 42 };
+    let y = Foo { a: 42 };
+    let z = Foo { a: 7 };
+
+    match x.partial_cmp(&y) {
+        Option::Some(Ordering::Equal) => print("x == y"),
+        Option::Some(Ordering::Less) => print("x < y"),
+        Option::Some(Ordering::Greater) => print("x > y"),
+        Option::None => print("x ? y"),
+    }
+
+    match x.partial_cmp(&z) {
+        Option::Some(Ordering::Equal) => print("x == z"),
+        Option::Some(Ordering::Less) => print("x < z"),
+        Option::Some(Ordering::Greater) => print("x > z"),
+        Option::None => print("x ? z"),
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-3.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs
new file mode 100644
index 000000000000..7aec07c5caaa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs
@@ -0,0 +1,489 @@
+/* { dg-output "x == y\r*\nx > z\r*\nx < z\r*\nx >= y\r*\nx <= y\r*\n" } */
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        // #[rustc_diagnostic_item = "option_type"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Option<T> {
+            /// No value
+            #[lang = "None"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            None,
+            /// Some value `T`
+            #[lang = "Some"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(PartialEq)]`")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(Eq)]`")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[lang = "sized"]
+        // #[rustc_on_unimplemented(
+        //     message = "the size for values of type `{Self}` cannot be known 
at compilation time",
+        //     label = "doesn't have a size known at compile-time"
+        // )]
+        // #[fundamental] // for Default, for example, which requires that 
`[T]: !Default` be evaluatable
+        // #[rustc_specialization_trait]
+        pub trait Sized {
+            // Empty.
+        }
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Ordering {
+            /// An ordering where a compared value is less than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Less = -1,
+            /// An ordering where a compared value is equal to another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Equal = 0,
+            /// An ordering where a compared value is greater than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} == {Rhs}`"
+        // )]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            /// This method tests for `self` and `other` values to be equal, 
and is used
+            /// by `==`.
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Eq: PartialEq<Self> {
+            // this method is used solely by #[deriving] to assert
+            // that every component of a type implements #[deriving]
+            // itself, the current deriving infrastructure means doing this
+            // assertion without using a method on this trait is nearly
+            // impossible.
+            //
+            // This should never be implemented by hand.
+            #[doc(hidden)]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} < {Rhs}` and `{Self} > 
{Rhs}`"
+        // )]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            /// This method returns an ordering between `self` and `other` 
values if one exists.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// let result = 1.0.partial_cmp(&2.0);
+            /// assert_eq!(result, Some(Ordering::Less));
+            ///
+            /// let result = 1.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Equal));
+            ///
+            /// let result = 2.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Greater));
+            /// ```
+            ///
+            /// When comparison is impossible:
+            ///
+            /// ```
+            /// let result = f64::NAN.partial_cmp(&1.0);
+            /// assert_eq!(result, None);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            /// This method tests less than (for `self` and `other`) and is 
used by the `<` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 < 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 < 1.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests less than or equal to (for `self` and 
`other`) and is used by the `<=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 <= 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 <= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than (for `self` and `other`) and is 
used by the `>` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 > 2.0;
+            /// assert_eq!(result, false);
+            ///
+            /// let result = 2.0 > 2.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than or equal to (for `self` and 
`other`) and is used by the `>=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 2.0 >= 1.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 >= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        #[doc(alias = "<")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Ord: Eq + PartialOrd<Self> {
+            /// This method returns an [`Ordering`] between `self` and `other`.
+            ///
+            /// By convention, `self.cmp(&other)` returns the ordering 
matching the expression
+            /// `self <operator> other` if true.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// assert_eq!(5.cmp(&10), Ordering::Less);
+            /// assert_eq!(10.cmp(&5), Ordering::Greater);
+            /// assert_eq!(5.cmp(&5), Ordering::Equal);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn cmp(&self, other: &Self) -> Ordering;
+
+            /// Compares and returns the maximum of two values.
+            ///
+            /// Returns the second argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(2, 1.max(2));
+            /// assert_eq!(2, 2.max(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn max(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Compares and returns the minimum of two values.
+            ///
+            /// Returns the first argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(1, 1.min(2));
+            /// assert_eq!(2, 2.min(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn min(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Restrict a value to a certain interval.
+            ///
+            /// Returns `max` if `self` is greater than `max`, and `min` if 
`self` is
+            /// less than `min`. Otherwise this returns `self`.
+            ///
+            /// # Panics
+            ///
+            /// Panics if `min > max`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(clamp)]
+            ///
+            /// assert!((-3).clamp(-2, 1) == -2);
+            /// assert!(0.clamp(-2, 1) == 0);
+            /// assert!(2.clamp(-2, 1) == 1);
+            /// ```
+            #[must_use]
+            #[unstable(feature = "clamp", issue = "44095")]
+            fn clamp(self, min: Self, max: Self) -> Self
+            where
+                Self: Sized,
+            {
+                if self < min {
+                    min
+                } else if self > max {
+                    max
+                } else {
+                    self
+                }
+            }
+        }
+    }
+
+    pub mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self > *other {
+            Ordering::Greater
+        } else if *self < *other {
+            Ordering::Less
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+struct Foo {
+    a: i32,
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, other: &Self) -> bool {
+        self.a == other.a
+    }
+}
+impl Eq for Foo {}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.a.partial_cmp(&other.a)
+    }
+}
+
+impl Ord for Foo {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.a.cmp(&other.a)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let x = Foo { a: 42 };
+    let y = Foo { a: 42 };
+    let z = Foo { a: 7 };
+
+    // test direct equality
+    if x == y {
+        print("x == y");
+    }
+
+    // test PartialOrd via match
+    match x.partial_cmp(&z) {
+        Option::Some(Ordering::Greater) => print("x > z"),
+        _ => print("x ? z"),
+    }
+
+    // test `<` directly
+    if z < x {
+        print("x < z");
+    }
+
+    // test `>=`
+    if x >= y {
+        print("x >= y");
+    }
+
+    // test `<=`
+    if x <= y {
+        print("x <= y");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-4.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs
new file mode 100644
index 000000000000..fd52f328c58b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs
@@ -0,0 +1,115 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        pub enum Option<T> {
+            #[lang = "None"]
+            None,
+            #[lang = "Some"]
+            Some(T),
+        }
+    }
+
+    mod marker {
+        #[lang = "sized"]
+        pub trait Sized {}
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        pub enum Ordering {
+            Less = -1,
+            Equal = 0,
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[lang = "partial_ord"]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+        }
+    }
+}
+
+use core::cmp::{Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+}
+
+struct Foo {
+    a: i32,
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, other: &'_ Self) -> bool {
+        self.a == other.a
+    }
+}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+        ::core::cmp::PartialOrd::partial_cmp(&self.a, &other.a)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { a: 42i32 };
+    let b = Foo { a: 42i32 };
+    let c = Foo { a: 7i32 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a == c {
+        print("a == c");
+    } else {
+        print("a != c");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-5.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs
new file mode 100644
index 000000000000..721d2aa00655
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs
@@ -0,0 +1,487 @@
+/* { dg-output "a == b\r*\na != c\r*\na >= c\r*\na <= b\r*\na > c\r*\nc < 
b\r*\n" } */
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+    mod option {
+        // #[rustc_diagnostic_item = "option_type"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Option<T> {
+            /// No value
+            #[lang = "None"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            None,
+            /// Some value `T`
+            #[lang = "Some"]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(PartialEq)]`")]
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {
+            // Empty.
+        }
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        // #[rustc_on_unimplemented(message = "the type `{Self}` does not 
`#[derive(Eq)]`")]
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {
+            // Empty.
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[lang = "sized"]
+        // #[rustc_on_unimplemented(
+        //     message = "the size for values of type `{Self}` cannot be known 
at compilation time",
+        //     label = "doesn't have a size known at compile-time"
+        // )]
+        // #[fundamental] // for Default, for example, which requires that 
`[T]: !Default` be evaluatable
+        // #[rustc_specialization_trait]
+        pub trait Sized {
+            // Empty.
+        }
+    }
+
+    mod cmp {
+        use super::marker::Sized;
+        use super::option::Option;
+
+        // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub enum Ordering {
+            /// An ordering where a compared value is less than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Less = -1,
+            /// An ordering where a compared value is equal to another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Equal = 0,
+            /// An ordering where a compared value is greater than another.
+            #[stable(feature = "rust1", since = "1.0.0")]
+            Greater = 1,
+        }
+
+        #[lang = "eq"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} == {Rhs}`"
+        // )]
+        pub trait PartialEq<Rhs: ?Sized = Self> {
+            /// This method tests for `self` and `other` values to be equal, 
and is used
+            /// by `==`.
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn eq(&self, other: &Rhs) -> bool;
+
+            fn ne(&self, other: &Rhs) -> bool {
+                !self.eq(other)
+            }
+        }
+
+        #[doc(alias = "==")]
+        #[doc(alias = "!=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Eq: PartialEq<Self> {
+            // this method is used solely by #[deriving] to assert
+            // that every component of a type implements #[deriving]
+            // itself, the current deriving infrastructure means doing this
+            // assertion without using a method on this trait is nearly
+            // impossible.
+            //
+            // This should never be implemented by hand.
+            #[doc(hidden)]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        // #[rustc_on_unimplemented(
+        //     message = "can't compare `{Self}` with `{Rhs}`",
+        //     label = "no implementation for `{Self} < {Rhs}` and `{Self} > 
{Rhs}`"
+        // )]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            /// This method returns an ordering between `self` and `other` 
values if one exists.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// let result = 1.0.partial_cmp(&2.0);
+            /// assert_eq!(result, Some(Ordering::Less));
+            ///
+            /// let result = 1.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Equal));
+            ///
+            /// let result = 2.0.partial_cmp(&1.0);
+            /// assert_eq!(result, Some(Ordering::Greater));
+            /// ```
+            ///
+            /// When comparison is impossible:
+            ///
+            /// ```
+            /// let result = f64::NAN.partial_cmp(&1.0);
+            /// assert_eq!(result, None);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            /// This method tests less than (for `self` and `other`) and is 
used by the `<` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 < 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 < 1.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests less than or equal to (for `self` and 
`other`) and is used by the `<=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 <= 2.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 <= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than (for `self` and `other`) and is 
used by the `>` operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 1.0 > 2.0;
+            /// assert_eq!(result, false);
+            ///
+            /// let result = 2.0 > 2.0;
+            /// assert_eq!(result, false);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            /// This method tests greater than or equal to (for `self` and 
`other`) and is used by the `>=`
+            /// operator.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// let result = 2.0 >= 1.0;
+            /// assert_eq!(result, true);
+            ///
+            /// let result = 2.0 >= 2.0;
+            /// assert_eq!(result, true);
+            /// ```
+            #[inline]
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater | Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        #[doc(alias = "<")]
+        #[doc(alias = ">")]
+        #[doc(alias = "<=")]
+        #[doc(alias = ">=")]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub trait Ord: Eq + PartialOrd<Self> {
+            /// This method returns an [`Ordering`] between `self` and `other`.
+            ///
+            /// By convention, `self.cmp(&other)` returns the ordering 
matching the expression
+            /// `self <operator> other` if true.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use std::cmp::Ordering;
+            ///
+            /// assert_eq!(5.cmp(&10), Ordering::Less);
+            /// assert_eq!(10.cmp(&5), Ordering::Greater);
+            /// assert_eq!(5.cmp(&5), Ordering::Equal);
+            /// ```
+            #[must_use]
+            #[stable(feature = "rust1", since = "1.0.0")]
+            fn cmp(&self, other: &Self) -> Ordering;
+
+            /// Compares and returns the maximum of two values.
+            ///
+            /// Returns the second argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(2, 1.max(2));
+            /// assert_eq!(2, 2.max(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn max(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Compares and returns the minimum of two values.
+            ///
+            /// Returns the first argument if the comparison determines them 
to be equal.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// assert_eq!(1, 1.min(2));
+            /// assert_eq!(2, 2.min(2));
+            /// ```
+            #[stable(feature = "ord_max_min", since = "1.21.0")]
+            #[must_use]
+            fn min(self, other: Self) -> Self
+            where
+                Self: Sized,
+            {
+                self
+            }
+
+            /// Restrict a value to a certain interval.
+            ///
+            /// Returns `max` if `self` is greater than `max`, and `min` if 
`self` is
+            /// less than `min`. Otherwise this returns `self`.
+            ///
+            /// # Panics
+            ///
+            /// Panics if `min > max`.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(clamp)]
+            ///
+            /// assert!((-3).clamp(-2, 1) == -2);
+            /// assert!(0.clamp(-2, 1) == 0);
+            /// assert!(2.clamp(-2, 1) == 1);
+            /// ```
+            #[must_use]
+            #[unstable(feature = "clamp", issue = "44095")]
+            fn clamp(self, min: Self, max: Self) -> Self
+            where
+                Self: Sized,
+            {
+                if self < min {
+                    min
+                } else if self > max {
+                    max
+                } else {
+                    self
+                }
+            }
+        }
+    }
+
+    pub mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl PartialEq for i32 {
+    fn eq(&self, other: &Self) -> bool {
+        *self == *other
+    }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else if *self < *other {
+            Option::Some(Ordering::Less)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        *self < *other
+    }
+    fn le(&self, other: &Self) -> bool {
+        *self <= *other
+    }
+    fn ge(&self, other: &Self) -> bool {
+        *self >= *other
+    }
+    fn gt(&self, other: &Self) -> bool {
+        *self > *other
+    }
+}
+
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self > *other {
+            Ordering::Greater
+        } else if *self < *other {
+            Ordering::Less
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Ord)]
+struct Foo {
+    a: i32,
+}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+        self.a.partial_cmp(&other.a)
+    }
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo { a: 42 };
+    let b = Foo { a: 42 };
+    let c = Foo { a: 7 };
+
+    if a == b {
+        print("a == b");
+    } else {
+        print("a != b");
+    }
+
+    if a != c {
+        print("a != c");
+    } else {
+        print("a == c");
+    }
+
+    if a < c {
+        print("a < c");
+    } else {
+        print("a >= c");
+    }
+
+    if a <= b {
+        print("a <= b");
+    } else {
+        print("a > b");
+    }
+
+    if a > c {
+        print("a > c");
+    } else {
+        print("a <= c");
+    }
+
+    if c >= b {
+        print("c >= b");
+    } else {
+        print("c < b");
+    }
+
+    0
+}

Reply via email to