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