]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix bug in query type stopping PartialOrd
authorPhilip Herron <herron.philip@googlemail.com>
Sat, 14 Jun 2025 19:34:33 +0000 (20:34 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:46 +0000 (16:36 +0200)
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.philip@googlemail.com>
gcc/rust/typecheck/rust-type-util.cc
gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs [new file with mode: 0644]
gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs [new file with mode: 0644]

index c6c5b4bb55fa5db0aad2967148ec989801b7c2c7..a549449dcef03c8d250d91c99fe1ac6cbdc6aa41 100644 (file)
@@ -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 (file)
index 0000000..efb825b
--- /dev/null
@@ -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 (file)
index 0000000..b8c3672
--- /dev/null
@@ -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
+}