https://gcc.gnu.org/g:d8d02332bccefdd449c938e93afc78ef7e295337

commit r16-2928-gd8d02332bccefdd449c938e93afc78ef7e295337
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Fri Jun 27 17:13:29 2025 +0100

    gccrs: Fix bad bounds checking for PartialOrd
    
    This was a nasty issue to debug, the issue was very eager type bounds
    checking. So for example:
    
      pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs>
    
    The super trait of PartialEq<Rhs> is a generic substitution and we reuse
    our bounds code here for normal generic bounds and generics an invalid
    bounds check was occuring when PartialEq<Rhs> was getting substituted becase
    this is a trait doing proper bounds checking is not valid here because this
    is telling us about the bounds in this case.
    
    Fixes Rust-GCC#3836
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-trait-resolve.cc 
(TraitResolver::resolve_trait): track is super trait
            * typecheck/rust-hir-type-bounds.h: refactor bounds scan
            * typecheck/rust-hir-type-check-base.h: track from super trait
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
likewise
            * typecheck/rust-tyty-bounds.cc 
(TypeBoundsProbe::is_bound_satisfied_for_type): refactor
            (TypeBoundsProbe::scan): likewise
            (TypeBoundPredicate::apply_generic_arguments): likewise
            * typecheck/rust-tyty-subst.cc: optional bounds checking on parm 
subst
            * typecheck/rust-tyty-subst.h: likewise
            * typecheck/rust-tyty.h: likewise
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/derive_partial_ord1.rs: this is now fully supported
            * rust/execute/torture/basic_partial_ord1.rs: add missing i32 impl
            * rust/execute/torture/basic_partial_ord2.rs: likewise
            * rust/compile/issue-3836.rs: New test.
            * rust/execute/torture/issue-3836.rs: New test.
            * rust/execute/torture/partial-ord-6.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-hir-trait-resolve.cc       |   3 +-
 gcc/rust/typecheck/rust-hir-type-bounds.h          |   4 +
 gcc/rust/typecheck/rust-hir-type-check-base.h      |   2 +-
 gcc/rust/typecheck/rust-hir-type-check-expr.cc     |   2 +-
 gcc/rust/typecheck/rust-tyty-bounds.cc             |  78 ++--
 gcc/rust/typecheck/rust-tyty-subst.cc              |   6 +-
 gcc/rust/typecheck/rust-tyty-subst.h               |   2 +-
 gcc/rust/typecheck/rust-tyty.h                     |   7 +-
 gcc/testsuite/rust/compile/derive_partial_ord1.rs  |   2 +-
 gcc/testsuite/rust/compile/issue-3836.rs           |  67 +++
 .../rust/execute/torture/basic_partial_ord1.rs     |  13 +
 .../rust/execute/torture/basic_partial_ord2.rs     |  13 +
 gcc/testsuite/rust/execute/torture/issue-3836.rs   | 454 ++++++++++++++++++
 .../rust/execute/torture/partial-ord-6.rs          | 518 +++++++++++++++++++++
 14 files changed, 1128 insertions(+), 43 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index fccc53ed6c2d..7f224076cd74 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -288,7 +288,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
 
              auto predicate = get_predicate_from_bound (
                b->get_path (),
-               tl::nullopt /*this will setup a PLACEHOLDER for self*/);
+               tl::nullopt /*this will setup a PLACEHOLDER for self*/,
+               BoundPolarity::RegularBound, false, true);
              if (predicate.is_error ())
                return &TraitReference::error_node ();
 
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h 
b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 3cf77733e45a..5384700e97fb 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -37,6 +37,10 @@ public:
 
 private:
   void scan ();
+  bool
+  process_impl_block (HirId id, HIR::ImplBlock *impl,
+                     std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+                       &possible_trait_paths);
   void assemble_marker_builtins ();
   void add_trait_bound (HIR::Trait *trait);
   void assemble_builtin_candidate (LangItem::Kind item);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h 
b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 580082a6adfb..a8084f2bf5b8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -46,7 +46,7 @@ protected:
     HIR::TypePath &path,
     tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
     BoundPolarity polarity = BoundPolarity::RegularBound,
-    bool is_qualified_type = false);
+    bool is_qualified_type = false, bool is_super_trait = false);
 
   bool check_for_unconstrained (
     const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index ccde4dd77bff..c1404561f4d0 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1866,7 +1866,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
   args.get_type_args ().push_back (std::unique_ptr<HIR::Type> 
(implicit_tuple));
 
   // apply the arguments
-  predicate.apply_generic_arguments (&args, false);
+  predicate.apply_generic_arguments (&args, false, false);
 
   // finally inherit the trait bound
   infered->inherit_bounds ({predicate});
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index f5b18004c187..c34d3628895a 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -61,6 +61,39 @@ TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType 
*receiver,
   return false;
 }
 
+bool
+TypeBoundsProbe::process_impl_block (
+  HirId id, HIR::ImplBlock *impl,
+  std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+    &possible_trait_paths)
+{
+  // we are filtering for trait-impl-blocks
+  if (!impl->has_trait_ref ())
+    return true;
+
+  // can be recursive trait resolution
+  HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
+  if (t == nullptr)
+    return true;
+  // DefId trait_id = t->get_mappings ().get_defid ();
+  // if (context->trait_query_in_progress (trait_id))
+  //   return true;
+
+  HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
+  TyTy::BaseType *impl_type = nullptr;
+  if (!query_type (impl_ty_id, &impl_type))
+    return true;
+
+  if (!receiver->can_eq (impl_type, false))
+    {
+      if (!impl_type->can_eq (receiver, false))
+       return true;
+    }
+
+  possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
+  return true;
+}
+
 void
 TypeBoundsProbe::scan ()
 {
@@ -68,31 +101,7 @@ TypeBoundsProbe::scan ()
     possible_trait_paths;
   mappings.iterate_impl_blocks (
     [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
-      // we are filtering for trait-impl-blocks
-      if (!impl->has_trait_ref ())
-       return true;
-
-      // can be recursive trait resolution
-      HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
-      if (t == nullptr)
-       return true;
-      DefId trait_id = t->get_mappings ().get_defid ();
-      if (context->trait_query_in_progress (trait_id))
-       return true;
-
-      HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
-      TyTy::BaseType *impl_type = nullptr;
-      if (!query_type (impl_ty_id, &impl_type))
-       return true;
-
-      if (!receiver->can_eq (impl_type, false))
-       {
-         if (!impl_type->can_eq (receiver, false))
-           return true;
-       }
-
-      possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
-      return true;
+      return process_impl_block (id, impl, possible_trait_paths);
     });
 
   for (auto &path : possible_trait_paths)
@@ -212,7 +221,7 @@ TyTy::TypeBoundPredicate
 TypeCheckBase::get_predicate_from_bound (
   HIR::TypePath &type_path,
   tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
-  BoundPolarity polarity, bool is_qualified_type_path)
+  BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait)
 {
   TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
   bool already_resolved
@@ -335,7 +344,8 @@ TypeCheckBase::get_predicate_from_bound (
   if (!args.is_empty () || predicate.requires_generic_args ())
     {
       // this is applying generic arguments to a trait reference
-      predicate.apply_generic_arguments (&args, associated_self.has_value ());
+      predicate.apply_generic_arguments (&args, associated_self.has_value (),
+                                        is_super_trait);
     }
 
   context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
@@ -516,7 +526,8 @@ TypeBoundPredicate::is_object_safe (bool emit_error, 
location_t locus) const
 
 void
 TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
-                                            bool has_associated_self)
+                                            bool has_associated_self,
+                                            bool is_super_trait)
 {
   rust_assert (!substitutions.empty ());
   if (has_associated_self)
@@ -537,23 +548,26 @@ TypeBoundPredicate::apply_generic_arguments 
(HIR::GenericArgs *generic_args,
     Resolver::TypeCheckContext::get ()->regions_from_generic_args (
       *generic_args));
 
-  apply_argument_mappings (args);
+  apply_argument_mappings (args, is_super_trait);
 }
 
 void
 TypeBoundPredicate::apply_argument_mappings (
-  SubstitutionArgumentMappings &arguments)
+  SubstitutionArgumentMappings &arguments, bool is_super_trait)
 {
   used_arguments = arguments;
   error_flag |= used_arguments.is_error ();
   auto &subst_mappings = used_arguments;
+
+  bool substs_need_bounds_check = !is_super_trait;
   for (auto &sub : get_substs ())
     {
       SubstitutionArg arg = SubstitutionArg::error ();
       bool ok
        = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
       if (ok && arg.get_tyty () != nullptr)
-       sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
+       sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
+                          substs_need_bounds_check);
     }
 
   // associated argument mappings
@@ -574,7 +588,7 @@ TypeBoundPredicate::apply_argument_mappings (
       auto adjusted
        = super_trait.adjust_mappings_for_this (used_arguments,
                                                true /*trait mode*/);
-      super_trait.apply_argument_mappings (adjusted);
+      super_trait.apply_argument_mappings (adjusted, is_super_trait);
     }
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 28d311a8aad2..2d5e87e5adda 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -115,7 +115,8 @@ SubstitutionParamMapping::need_substitution () const
 
 bool
 SubstitutionParamMapping::fill_param_ty (
-  SubstitutionArgumentMappings &subst_mappings, location_t locus)
+  SubstitutionArgumentMappings &subst_mappings, location_t locus,
+  bool needs_bounds_check)
 {
   SubstitutionArg arg = SubstitutionArg::error ();
   bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
@@ -139,8 +140,7 @@ SubstitutionParamMapping::fill_param_ty (
       rust_debug_loc (locus,
                      "fill_param_ty bounds_compatible: param %s type %s",
                      param->get_name ().c_str (), type.get_name ().c_str ());
-
-      if (!param->is_implicit_self_trait ())
+      if (needs_bounds_check && !param->is_implicit_self_trait ())
        {
          if (!param->bounds_compatible (type, locus, true))
            return false;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h 
b/gcc/rust/typecheck/rust-tyty-subst.h
index 2f5de23aa00f..141db3d448b7 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -51,7 +51,7 @@ public:
   std::string as_string () const;
 
   bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
-                     location_t locus);
+                     location_t locus, bool needs_bounds_check = true);
 
   SubstitutionParamMapping clone () const;
 
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index e0d0358e9e66..13e9184f29d7 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -539,14 +539,15 @@ public:
 
   std::string get_name () const;
 
-  // check that this predicate is object-safe see:
+  // check that this  is object-safe see:
   // https://doc.rust-lang.org/reference/items/traits.html#object-safety
   bool is_object_safe (bool emit_error, location_t locus) const;
 
   void apply_generic_arguments (HIR::GenericArgs *generic_args,
-                               bool has_associated_self);
+                               bool has_associated_self, bool is_super_trait);
 
-  void apply_argument_mappings (SubstitutionArgumentMappings &arguments);
+  void apply_argument_mappings (SubstitutionArgumentMappings &arguments,
+                               bool is_super_trait);
 
   bool contains_item (const std::string &search) const;
 
diff --git a/gcc/testsuite/rust/compile/derive_partial_ord1.rs 
b/gcc/testsuite/rust/compile/derive_partial_ord1.rs
index 1f74b4dc9031..eeca62da0784 100644
--- a/gcc/testsuite/rust/compile/derive_partial_ord1.rs
+++ b/gcc/testsuite/rust/compile/derive_partial_ord1.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-frust-compile-until=typecheck" }
+// { dg-additional-options "-w" }
 
 #![feature(intrinsics)]
 
diff --git a/gcc/testsuite/rust/compile/issue-3836.rs 
b/gcc/testsuite/rust/compile/issue-3836.rs
new file mode 100644
index 000000000000..a2287957ad14
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3836.rs
@@ -0,0 +1,67 @@
+// { dg-options "-w" }
+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> {
+            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 {
+        false
+    }
+}
+
+impl PartialOrd for i32 {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Option::Some(Ordering::Equal)
+    }
+}
+
+struct Foo {
+    a: i32,
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, other: &'_ Self) -> bool {
+        ::core::cmp::PartialEq::eq(&self.a, &other.a)
+    }
+}
diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs 
b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
index efb825bc908c..0431629e9ea6 100644
--- a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
@@ -103,6 +103,19 @@ impl PartialOrd for i32 {
             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 Eq for i32 {}
diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs 
b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
index b8c367255fa1..b6a96953d4a9 100644
--- a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
@@ -104,6 +104,19 @@ impl PartialOrd for i32 {
             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 Eq for i32 {}
diff --git a/gcc/testsuite/rust/execute/torture/issue-3836.rs 
b/gcc/testsuite/rust/execute/torture/issue-3836.rs
new file mode 100644
index 000000000000..61ad42492e74
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3836.rs
@@ -0,0 +1,454 @@
+// { dg-options "-w" }
+// { dg-output "less\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
+        }
+    }
+}
+
+// ------------
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct Bar {
+    a: i32,
+    b: 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 x = Bar { a: 1, b: 2 };
+    let y = Bar { a: 1, b: 3 };
+
+    match x.partial_cmp(&y) {
+        Option::Some(Ordering::Less) => print("less"),
+        Option::Some(Ordering::Greater) => print("greater"),
+        Option::Some(Ordering::Equal) => print("equal"),
+        _ => print("none"),
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-6.rs 
b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs
new file mode 100644
index 000000000000..5d64f8c2f84c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs
@@ -0,0 +1,518 @@
+// { dg-additional-options "-w" }
+/* { dg-output "Foo A < B\r?\nFoo B < C\r?\nFoo C == C\r?\nBar x < 
y\r?\nBarFull s1 < s2\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 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
+        }
+    }
+}
+
+impl Eq for i32 {}
+
+#[derive(PartialEq, PartialOrd)]
+enum Foo {
+    A,
+    B(i32, i32, i32),
+    C { inner: i32, outer: i32 },
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct Bar {
+    a: i32,
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct BarFull {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+}
+
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        puts(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    // Enum comparison
+    let a = Foo::A;
+    let b = Foo::B(15, 14, 13);
+    let c = Foo::C {
+        inner: 10,
+        outer: 20,
+    };
+
+    match a.partial_cmp(&b) {
+        Option::Some(Ordering::Less) => print("Foo A < B"),
+        Option::Some(Ordering::Greater) => print("Foo A > B"),
+        Option::Some(Ordering::Equal) => print("Foo A == B"),
+        _ => print("Foo A ? B"),
+    }
+
+    match b.partial_cmp(&c) {
+        Option::Some(Ordering::Less) => print("Foo B < C"),
+        Option::Some(Ordering::Greater) => print("Foo B > C"),
+        Option::Some(Ordering::Equal) => print("Foo B == C"),
+        _ => print("Foo B ? C"),
+    }
+
+    match c.partial_cmp(&c) {
+        Option::Some(Ordering::Less) => print("Foo C < C ???"),
+        Option::Some(Ordering::Greater) => print("Foo C > C ???"),
+        Option::Some(Ordering::Equal) => print("Foo C == C"),
+        _ => print("Foo C ? C"),
+    }
+
+    // Struct comparison: Bar
+    let x = Bar { a: 10 };
+    let y = Bar { a: 20 };
+
+    if x < y {
+        print("Bar x < y");
+    } else if x > y {
+        print("Bar x > y");
+    } else {
+        print("Bar x == y");
+    }
+
+    // Struct comparison: BarFull
+    let s1 = BarFull {
+        a: 1,
+        b: 2,
+        c: 3,
+        d: 4,
+    };
+    let s2 = BarFull {
+        a: 1,
+        b: 2,
+        c: 3,
+        d: 5,
+    };
+
+    match s1.cmp(&s2) {
+        Ordering::Less => print("BarFull s1 < s2"),
+        Ordering::Greater => print("BarFull s1 > s2"),
+        Ordering::Equal => print("BarFull s1 == s2"),
+    }
+
+    0
+}

Reply via email to