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

commit r16-2849-ge0ad76bf33fb89108c00787f12122d6675ba40ac
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Sat Jun 14 20:34:33 2025 +0100

    gccrs: Fix bug in query type stopping PartialOrd
    
    There was a complex recurisve type query hierarchy here but the type was
    resolved so we can just do an early return here
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-type-util.cc (query_type): early return.
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/torture/basic_partial_ord1.rs: New test.
            * rust/execute/torture/basic_partial_ord2.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-type-util.cc               |   6 +-
 .../rust/execute/torture/basic_partial_ord1.rs     | 176 ++++++++++++++++++++
 .../rust/execute/torture/basic_partial_ord2.rs     | 184 +++++++++++++++++++++
 3 files changed, 363 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/typecheck/rust-type-util.cc 
b/gcc/rust/typecheck/rust-type-util.cc
index c6c5b4bb55fa..a549449dcef0 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -40,12 +40,12 @@ query_type (HirId reference, TyTy::BaseType **result)
   auto &resolver = *Resolver::get ();
   TypeCheckContext *context = TypeCheckContext::get ();
 
-  if (context->query_in_progress (reference))
-    return false;
-
   if (context->lookup_type (reference, result))
     return true;
 
+  if (context->query_in_progress (reference))
+    return false;
+
   context->insert_query (reference);
 
   std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate
diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs 
b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
new file mode 100644
index 000000000000..efb825bc908c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
@@ -0,0 +1,176 @@
+/* { dg-output "less\r*" }*/
+mod core {
+    mod option {
+        pub enum Option<T> {
+            None,
+            Some(T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {}
+
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {}
+
+        #[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)
+            }
+        }
+
+        pub trait Eq: PartialEq<Self> {
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) | 
Option::Some(Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) | 
Option::Some(Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        pub trait Ord: Eq + PartialOrd<Self> {
+            fn cmp(&self, other: &Self) -> Ordering;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::option::Option;
+
+// Needed impls for primitives
+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::Less)
+        } else if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+}
+
+impl Eq for i32 {}
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self < *other {
+            Ordering::Less
+        } else if *self > *other {
+            Ordering::Greater
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+// Manual impl for struct Bar
+struct Bar {
+    a: i32,
+    b: i32,
+}
+
+impl PartialEq for Bar {
+    fn eq(&self, other: &Self) -> bool {
+        self.a.eq(&other.a) && self.b.eq(&other.b)
+    }
+}
+
+impl Eq for Bar {}
+
+impl PartialOrd for Bar {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        match self.a.partial_cmp(&other.a) {
+            Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b),
+            ord => ord,
+        }
+    }
+}
+
+impl Ord for Bar {
+    fn cmp(&self, other: &Self) -> Ordering {
+        match self.a.cmp(&other.a) {
+            Ordering::Equal => self.b.cmp(&other.b),
+            ord => ord,
+        }
+    }
+}
+
+// External print shim
+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/basic_partial_ord2.rs 
b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
new file mode 100644
index 000000000000..b8c367255fa1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
@@ -0,0 +1,184 @@
+/* { dg-output "<><=>=\r*" } */
+/* { dg-options "-w" } */
+mod core {
+    mod option {
+        pub enum Option<T> {
+            None,
+            Some(T),
+        }
+    }
+
+    mod marker {
+        #[lang = "phantom_data"]
+        pub struct PhantomData<T: ?Sized>;
+
+        #[lang = "structural_peq"]
+        pub trait StructuralPartialEq {}
+
+        #[lang = "structural_teq"]
+        pub trait StructuralEq {}
+
+        #[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)
+            }
+        }
+
+        pub trait Eq: PartialEq<Self> {
+            fn assert_receiver_is_total_eq(&self) {}
+        }
+
+        #[lang = "partial_ord"]
+        pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+            fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+            fn lt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) => true,
+                    _ => false,
+                }
+            }
+
+            fn le(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Less) | 
Option::Some(Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+
+            fn gt(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) => true,
+                    _ => false,
+                }
+            }
+
+            fn ge(&self, other: &Rhs) -> bool {
+                match self.partial_cmp(other) {
+                    Option::Some(Ordering::Greater) | 
Option::Some(Ordering::Equal) => true,
+                    _ => false,
+                }
+            }
+        }
+
+        pub trait Ord: Eq + PartialOrd<Self> {
+            fn cmp(&self, other: &Self) -> Ordering;
+        }
+    }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::option::Option;
+
+// Needed impls for primitives
+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::Less)
+        } else if *self > *other {
+            Option::Some(Ordering::Greater)
+        } else {
+            Option::Some(Ordering::Equal)
+        }
+    }
+}
+
+impl Eq for i32 {}
+impl Ord for i32 {
+    fn cmp(&self, other: &Self) -> Ordering {
+        if *self < *other {
+            Ordering::Less
+        } else if *self > *other {
+            Ordering::Greater
+        } else {
+            Ordering::Equal
+        }
+    }
+}
+
+// Manual impl for struct Bar
+struct Bar {
+    a: i32,
+    b: i32,
+}
+
+impl PartialEq for Bar {
+    fn eq(&self, other: &Self) -> bool {
+        self.a.eq(&other.a) && self.b.eq(&other.b)
+    }
+}
+
+impl Eq for Bar {}
+
+impl PartialOrd for Bar {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        match self.a.partial_cmp(&other.a) {
+            Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b),
+            ord => ord,
+        }
+    }
+}
+
+impl Ord for Bar {
+    fn cmp(&self, other: &Self) -> Ordering {
+        match self.a.cmp(&other.a) {
+            Ordering::Equal => self.b.cmp(&other.b),
+            ord => ord,
+        }
+    }
+}
+
+// External print shim
+extern "C" {
+    fn printf(s: *const i8);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(s as *const str as *const i8);
+    }
+}
+
+fn main() -> i32 {
+    let a = Bar { a: 1, b: 2 };
+    let b = Bar { a: 1, b: 3 };
+    let c = Bar { a: 1, b: 2 };
+
+    if a < b {
+        print("<");
+    }
+    if b > a {
+        print(">");
+    }
+    if a <= c {
+        print("<=");
+    }
+    if b >= c {
+        print(">=");
+    }
+
+    0
+}

Reply via email to