mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 20:01:31 -05:00
gccrs: derive(PartialEq): Allow deriving enum structs
gcc/rust/ChangeLog: * expand/rust-derive-partial-eq.cc (DerivePartialEq::match_enum_tuple): Remove debug call. (DerivePartialEq::match_enum_struct): Add proper implementation. (DerivePartialEq::visit_enum): Call it. gcc/testsuite/ChangeLog: * rust/execute/torture/derive-partialeq2.rs: New test.
This commit is contained in:
@@ -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`.
|
||||
auto self_fields = std::vector<std::unique_ptr<StructPatternField>> ();
|
||||
auto other_fields = std::vector<std::unique_ptr<StructPatternField>> ();
|
||||
|
||||
rust_unreachable ();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
66
gcc/testsuite/rust/execute/torture/derive-partialeq2.rs
Normal file
66
gcc/testsuite/rust/execute/torture/derive-partialeq2.rs
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user