LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-derive-eq.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.7 % 110 102
Test Date: 2026-10-03 16:17:38 Functions: 91.7 % 12 11
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2025-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-derive-eq.h"
      20              : #include "rust-ast.h"
      21              : #include "rust-expr.h"
      22              : #include "rust-item.h"
      23              : #include "rust-path.h"
      24              : #include "rust-pattern.h"
      25              : #include "rust-system.h"
      26              : 
      27              : namespace Rust {
      28              : namespace AST {
      29              : 
      30              : static TypePath
      31          296 : get_eq_trait_path (Builder &builder)
      32              : {
      33         1184 :   return builder.type_path ({builder.get_path_start (), "cmp", "Eq"}, true);
      34              : }
      35              : 
      36          133 : DeriveEq::DeriveEq (location_t loc, Builder::Source item_source)
      37          133 :   : DeriveVisitor (loc, item_source)
      38          133 : {}
      39              : 
      40              : std::vector<std::unique_ptr<AST::Item>>
      41          133 : DeriveEq::go (Item &item)
      42              : {
      43          133 :   item.accept_vis (*this);
      44              : 
      45          133 :   return std::move (expanded);
      46              : }
      47              : 
      48              : std::unique_ptr<AssociatedItem>
      49          133 : DeriveEq::assert_receiver_is_total_eq_fn (
      50              :   std::vector<std::unique_ptr<Type>> &&types)
      51              : {
      52          133 :   auto stmts = std::vector<std::unique_ptr<Stmt>> ();
      53              : 
      54          133 :   stmts.emplace_back (assert_param_is_eq ());
      55              : 
      56          320 :   for (auto &&type : types)
      57          187 :     stmts.emplace_back (assert_type_is_eq (std::move (type)));
      58              : 
      59          133 :   auto block = std::unique_ptr<BlockExpr> (
      60          133 :     new BlockExpr (std::move (stmts), nullptr, {}, {}, tl::nullopt, loc, loc));
      61              : 
      62          133 :   auto self = builder.self_ref_param ();
      63              : 
      64          532 :   return builder.function ("assert_receiver_is_total_eq",
      65          399 :                            vec (std::move (self)), {}, std::move (block));
      66          133 : }
      67              : 
      68              : std::unique_ptr<Stmt>
      69          133 : DeriveEq::assert_param_is_eq ()
      70              : {
      71          133 :   auto eq_bound = std::unique_ptr<TypeParamBound> (
      72          133 :     new TraitBound (get_eq_trait_path (builder), loc));
      73              : 
      74          133 :   auto sized_bound = std::unique_ptr<TypeParamBound> (
      75          266 :     new TraitBound (builder.type_path (LangItem::Kind::SIZED), loc, false,
      76          133 :                     true /* opening_question_mark */));
      77              : 
      78          133 :   auto bounds = vec (std::move (eq_bound), std::move (sized_bound));
      79              : 
      80          133 :   auto assert_param_is_eq = "AssertParamIsEq";
      81              : 
      82          133 :   auto t = std::unique_ptr<GenericParam> (
      83          266 :     new TypeParam (Identifier ("T"), loc, std::move (bounds)));
      84              : 
      85          399 :   return builder.struct_struct (
      86          266 :     assert_param_is_eq, vec (std::move (t)),
      87              :     {StructField (
      88          399 :       Identifier ("_t"),
      89          266 :       builder.single_generic_type_path (
      90              :         LangItem::Kind::PHANTOM_DATA,
      91          133 :         GenericArgs (
      92          399 :           {}, {GenericArg::create_type (builder.single_type_path ("T"))}, {})),
      93          399 :       Visibility::create_private (), loc)});
      94          133 : }
      95              : 
      96              : std::unique_ptr<Stmt>
      97          187 : DeriveEq::assert_type_is_eq (std::unique_ptr<Type> &&type)
      98              : {
      99          187 :   auto assert_param_is_eq = "AssertParamIsEq";
     100              : 
     101              :   // AssertParamIsCopy::<Self>
     102          187 :   auto assert_param_is_eq_ty
     103              :     = std::unique_ptr<TypePathSegment> (new TypePathSegmentGeneric (
     104          374 :       PathIdentSegment (assert_param_is_eq, loc), false,
     105          561 :       GenericArgs ({}, {GenericArg::create_type (std::move (type))}, {}, loc),
     106          374 :       loc));
     107              : 
     108              :   // TODO: Improve this, it's really ugly
     109          187 :   auto type_paths = std::vector<std::unique_ptr<TypePathSegment>> ();
     110          187 :   type_paths.emplace_back (std::move (assert_param_is_eq_ty));
     111              : 
     112          187 :   auto full_path
     113          187 :     = std::unique_ptr<Type> (new TypePath ({std::move (type_paths)}, loc));
     114              : 
     115          187 :   return builder.let (builder.wildcard (), std::move (full_path));
     116          187 : }
     117              : 
     118              : std::vector<std::unique_ptr<Item>>
     119          133 : DeriveEq::eq_impls (
     120              :   std::unique_ptr<AssociatedItem> &&fn, std::string name,
     121              :   const std::vector<std::unique_ptr<GenericParam>> &type_generics)
     122              : {
     123          133 :   auto eq = [this] () { return get_eq_trait_path (builder); };
     124           30 :   auto eq_bound = [&, this] () { return builder.trait_bound (eq ()); };
     125              : 
     126          133 :   auto steq = builder.type_path (LangItem::Kind::STRUCTURAL_TEQ);
     127              : 
     128          133 :   auto trait_items = vec (std::move (fn));
     129              : 
     130          133 :   auto eq_generics = setup_impl_generics (name, type_generics, eq_bound);
     131          133 :   auto steq_generics = setup_impl_generics (name, type_generics);
     132              : 
     133          266 :   auto eq_impl = builder.trait_impl (eq (), std::move (eq_generics.self_type),
     134              :                                      std::move (trait_items),
     135          133 :                                      std::move (eq_generics.impl));
     136              : 
     137              :   // StructuralEq is a marker trait
     138          133 :   decltype (trait_items) steq_trait_items = {};
     139              : 
     140          133 :   auto steq_impl
     141          266 :     = builder.trait_impl (steq, std::move (steq_generics.self_type),
     142              :                           std::move (steq_trait_items),
     143          133 :                           std::move (steq_generics.impl));
     144              : 
     145          133 :   return vec (std::move (eq_impl), std::move (steq_impl));
     146          399 : }
     147              : 
     148              : void
     149           18 : DeriveEq::visit_tuple (TupleStruct &item)
     150              : {
     151           18 :   auto types = std::vector<std::unique_ptr<Type>> ();
     152              : 
     153           36 :   for (auto &field : item.get_fields ())
     154           18 :     types.emplace_back (field.get_field_type ().reconstruct ());
     155              : 
     156           36 :   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
     157           18 :                        item.get_identifier ().as_string (),
     158           36 :                        item.get_generic_params ());
     159           18 : }
     160              : 
     161              : void
     162           83 : DeriveEq::visit_struct (StructStruct &item)
     163              : {
     164           83 :   auto types = std::vector<std::unique_ptr<Type>> ();
     165              : 
     166          214 :   for (auto &field : item.get_fields ())
     167          131 :     types.emplace_back (field.get_field_type ().reconstruct ());
     168              : 
     169          166 :   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
     170           83 :                        item.get_identifier ().as_string (),
     171          166 :                        item.get_generic_params ());
     172           83 : }
     173              : 
     174              : void
     175           32 : DeriveEq::visit_enum (Enum &item)
     176              : {
     177           32 :   auto types = std::vector<std::unique_ptr<Type>> ();
     178              : 
     179          123 :   for (auto &variant : item.get_variants ())
     180              :     {
     181           91 :       switch (variant->get_enum_item_kind ())
     182              :         {
     183           58 :         case EnumItem::Kind::Identifier:
     184           58 :         case EnumItem::Kind::Discriminant:
     185              :           // nothing to do as they contain no inner types
     186           58 :           continue;
     187           32 :         case EnumItem::Kind::Tuple:
     188           32 :           {
     189           32 :             auto &tuple = static_cast<EnumItemTuple &> (*variant);
     190              : 
     191           68 :             for (auto &field : tuple.get_tuple_fields ())
     192           36 :               types.emplace_back (field.get_field_type ().reconstruct ());
     193              :             break;
     194              :           }
     195            1 :         case EnumItem::Kind::Struct:
     196            1 :           {
     197            1 :             auto &tuple = static_cast<EnumItemStruct &> (*variant);
     198              : 
     199            3 :             for (auto &field : tuple.get_struct_fields ())
     200            2 :               types.emplace_back (field.get_field_type ().reconstruct ());
     201              : 
     202              :             break;
     203              :           }
     204           58 :         }
     205              :     }
     206              : 
     207           96 :   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
     208           32 :                        item.get_identifier ().as_string (),
     209           64 :                        item.get_generic_params ());
     210           32 : }
     211              : 
     212              : void
     213            0 : DeriveEq::visit_union (Union &item)
     214              : {
     215            0 :   auto types = std::vector<std::unique_ptr<Type>> ();
     216              : 
     217            0 :   for (auto &field : item.get_variants ())
     218            0 :     types.emplace_back (field.get_field_type ().reconstruct ());
     219              : 
     220            0 :   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
     221            0 :                        item.get_identifier ().as_string (),
     222            0 :                        item.get_generic_params ());
     223            0 : }
     224              : 
     225              : } // namespace AST
     226              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.