diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/expand/rust-derive-partial-eq.cc | 66 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/derive-partialeq2.rs | 66 |
2 files changed, 118 insertions, 14 deletions
diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index ff66faa..22368bc 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -199,8 +199,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, auto self_pattern_str = "__self_" + std::to_string (i); auto other_pattern_str = "__other_" + std::to_string (i); - rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ()); - self_patterns.emplace_back ( builder.identifier_pattern (self_pattern_str)); other_patterns.emplace_back ( @@ -240,15 +238,55 @@ MatchCase DerivePartialEq::match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant) { - // NOTE: We currently do not support compiling struct patterns where an - // identifier is assigned a new pattern, e.g. Bloop { f0: x } - // This is what we should be using to compile PartialEq for enum struct - // variants, as we need to be comparing the field of each instance meaning we - // need to give two different names to two different instances of the same - // field. We cannot just use the field's name like we do when deriving - // `Clone`. - - rust_unreachable (); + auto self_fields = std::vector<std::unique_ptr<StructPatternField>> (); + auto other_fields = std::vector<std::unique_ptr<StructPatternField>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_<field>` and + // `other_<field>` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (self_elts))), + false, false, loc)); + auto other_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (other_elts))), + false, false, loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); + + auto expr = build_eq_expression (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); } void @@ -275,9 +313,9 @@ DerivePartialEq::visit_enum (Enum &item) static_cast<EnumItemTuple &> (*variant))); break; case EnumItem::Kind::Struct: - rust_sorry_at ( - item.get_locus (), - "cannot derive(PartialEq) for enum struct variants yet"); + cases.emplace_back ( + match_enum_struct (variant_path, + static_cast<EnumItemStruct &> (*variant))); break; } } diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs new file mode 100644 index 0000000..15374d9 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs @@ -0,0 +1,66 @@ +// { dg-output "true\r*\nfalse\r*\nfalse\r*\nfalse\r*\nfalse\r*\n" } + +#![feature(intrinsics)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +#[lang = "eq"] +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; + + /// This method tests for `!=`. + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +#[derive(PartialEq)] +enum Foo { + A { a: i32, b: i32 }, + B(i32, i32), + C, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(b: bool) { + if b { + unsafe { puts("true" as *const str as *const i8) } + } else { + unsafe { puts("false" as *const str as *const i8) } + } +} + +fn main() -> i32 { + let x = Foo::A { a: 15, b: 14 }; + + let b1 = x == Foo::A { a: 15, b: 14 }; + let b12 = x == Foo::A { a: 15, b: 19 }; + let b13 = x == Foo::A { a: 19, b: 14 }; + let b2 = x == Foo::B(15, 14); + let b3 = x == Foo::C; + + print(b1); + print(b12); + print(b13); + print(b2); + print(b3); + + 0 +} |