Skip to content

Commit

Permalink
derive(PartialEq): Also derive StructuralPartialEq
Browse files Browse the repository at this point in the history
gcc/rust/ChangeLog:

	* expand/rust-derive-partial-eq.cc: Adapt signatures to generate two impls.
	* expand/rust-derive-partial-eq.h: Likewise.
	* expand/rust-derive.cc (DeriveVisitor::derive): Adapt to multiple item generation.

gcc/testsuite/ChangeLog:

	* rust/compile/derive-eq-invalid.rs:
	* rust/compile/derive-partialeq1.rs:
  • Loading branch information
CohenArthur committed Feb 4, 2025
1 parent 83f33ab commit 9d425d5
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 22 deletions.
41 changes: 23 additions & 18 deletions gcc/rust/expand/rust-derive-partial-eq.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,40 @@

namespace Rust {
namespace AST {
DerivePartialEq::DerivePartialEq (location_t loc)
: DeriveVisitor (loc), expanded (nullptr)
{}
DerivePartialEq::DerivePartialEq (location_t loc) : DeriveVisitor (loc) {}

std::unique_ptr<AST::Item>
std::vector<std::unique_ptr<AST::Item>>
DerivePartialEq::go (Item &item)
{
item.accept_vis (*this);

rust_assert (expanded);

return std::move (expanded);
}

std::unique_ptr<Item>
DerivePartialEq::partial_eq_impl (
std::vector<std::unique_ptr<Item>>
DerivePartialEq::partialeq_impls (
std::unique_ptr<AssociatedItem> &&eq_fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics)
{
auto eq = builder.type_path (LangItem::Kind::EQ);
auto speq = builder.type_path (LangItem::Kind::STRUCTURAL_PEQ);

auto trait_items = vec (std::move (eq_fn));

auto generics
// no extra bound on StructuralPeq
auto peq_generics
= setup_impl_generics (name, type_generics, builder.trait_bound (eq));
auto speq_generics = setup_impl_generics (name, type_generics);

auto peq = builder.trait_impl (eq, std::move (peq_generics.self_type),
std::move (trait_items),
std::move (peq_generics.impl));

auto structural_peq
= builder.trait_impl (speq, std::move (speq_generics.self_type), {},
std::move (speq_generics.impl));

return builder.trait_impl (eq, std::move (generics.self_type),
std::move (trait_items),
std::move (generics.impl));
return vec (std::move (peq), std::move (structural_peq));
}

std::unique_ptr<AssociatedItem>
Expand Down Expand Up @@ -137,7 +142,7 @@ DerivePartialEq::visit_tuple (TupleStruct &item)
auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);

expanded
= partial_eq_impl (std::move (fn), type_name, item.get_generic_params ());
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
}

void
Expand All @@ -153,7 +158,7 @@ DerivePartialEq::visit_struct (StructStruct &item)
auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);

expanded
= partial_eq_impl (std::move (fn), type_name, item.get_generic_params ());
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
}

MatchCase
Expand Down Expand Up @@ -250,11 +255,12 @@ void
DerivePartialEq::visit_enum (Enum &item)
{
auto cases = std::vector<MatchCase> ();
auto type_name = item.get_identifier ().as_string ();

for (auto &variant : item.get_variants ())
{
auto variant_path
= builder.variant_path (item.get_identifier ().as_string (),
= builder.variant_path (type_name,
variant->get_identifier ().as_string ());

switch (variant->get_enum_item_kind ())
Expand Down Expand Up @@ -290,11 +296,10 @@ DerivePartialEq::visit_enum (Enum &item)
builder.identifier ("other"))),
std::move (cases));

auto fn = eq_fn (std::move (match), item.get_identifier ().as_string ());
auto fn = eq_fn (std::move (match), type_name);

expanded
= partial_eq_impl (std::move (fn), item.get_identifier ().as_string (),
item.get_generic_params ());
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
}

void
Expand Down
10 changes: 7 additions & 3 deletions gcc/rust/expand/rust-derive-partial-eq.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ class DerivePartialEq : DeriveVisitor
public:
DerivePartialEq (location_t loc);

std::unique_ptr<AST::Item> go (Item &item);
std::vector<std::unique_ptr<AST::Item>> go (Item &item);

private:
std::unique_ptr<Item> expanded;
std::vector<std::unique_ptr<Item>> expanded;

std::unique_ptr<Item> partial_eq_impl (
/**
* Generate both an implementation of `PartialEq` and `StructuralPartialEq`
* for the given type
*/
std::vector<std::unique_ptr<Item>> partialeq_impls (
std::unique_ptr<AssociatedItem> &&eq_fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);

Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/expand/rust-derive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
case BuiltinMacro::Eq:
return vec (DeriveEq (attr.get_locus ()).go (item));
case BuiltinMacro::PartialEq:
return vec (DerivePartialEq (attr.get_locus ()).go (item));
return DerivePartialEq (attr.get_locus ()).go (item);
case BuiltinMacro::Ord:
case BuiltinMacro::PartialOrd:
case BuiltinMacro::Hash:
Expand Down
6 changes: 6 additions & 0 deletions gcc/testsuite/rust/compile/derive-eq-invalid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ struct PhantomData<T>;
#[lang = "sized"]
trait Sized {}

#[lang = "structural_peq"]
trait StructuralPartialEq {}

#[lang = "structural_teq"]
trait StructuralEq {}

#[derive(PartialEq)]
struct NotEq;

Expand Down
3 changes: 3 additions & 0 deletions gcc/testsuite/rust/compile/derive-partialeq1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ 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
Expand Down

0 comments on commit 9d425d5

Please sign in to comment.