]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: derive(PartialEq): Also derive StructuralPartialEq
authorArthur Cohen <arthur.cohen@embecosm.com>
Tue, 4 Feb 2025 15:06:33 +0000 (16:06 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Mon, 24 Mar 2025 12:07:09 +0000 (13:07 +0100)
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: Declare StructuralPartialEq.
* rust/compile/derive-partialeq1.rs: Likewise.
* rust/execute/torture/derive-partialeq1.rs: Likewise.

gcc/rust/expand/rust-derive-partial-eq.cc
gcc/rust/expand/rust-derive-partial-eq.h
gcc/rust/expand/rust-derive.cc
gcc/testsuite/rust/compile/derive-eq-invalid.rs
gcc/testsuite/rust/compile/derive-partialeq1.rs
gcc/testsuite/rust/execute/torture/derive-partialeq1.rs

index 6f7ef7d8780f6e0eb3d3843f54e1a9c98f50a68c..ff66faabc781fce10aa63419b3819cd5b9a1ebf9 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
 
 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>
@@ -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
@@ -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
@@ -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 ())
@@ -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
index 2bc18d2b98a5206572702511532de7813d9775ff..ac963a63c8aafd1b6675ee56ccd3fd941821b57f 100644 (file)
@@ -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);
 
index cd162247ec452f7432e034084e6b682e1bbdaca3..250ef726f43d89f49763195b464e9f2c7cdbeffc 100644 (file)
@@ -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:
index 0c4d48ef6ea6449fcfe6d4d775cbc95ca0438ebb..b0bf856486d3c84f0efac7602ac75c083b9b986f 100644 (file)
@@ -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;
 
index 715132419298e8b42748b56adabfbf2ac0322a82..35e33fbc25c2e6670939121817c3a66dcf2fb021 100644 (file)
@@ -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
index 4d5124e85cfba3e43bfba2b4193c8eda8bd9e040..67b2773e498fdc0d586f83f1f20000cb4c1e1c32 100644 (file)
@@ -25,6 +25,9 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
     }
 }
 
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
 #[derive(PartialEq, Copy)] // { dg-warning "unused name" }
 struct Foo;