LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-derive-default.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 81.6 % 76 62
Test Date: 2026-02-28 14:20:25 Functions: 81.8 % 11 9
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-default.h"
      20              : #include "rust-ast.h"
      21              : #include "rust-diagnostics.h"
      22              : #include "rust-path.h"
      23              : #include "rust-system.h"
      24              : 
      25              : namespace Rust {
      26              : namespace AST {
      27              : 
      28           15 : DeriveDefault::DeriveDefault (location_t loc)
      29           15 :   : DeriveVisitor (loc), expanded (nullptr)
      30           15 : {}
      31              : 
      32              : std::unique_ptr<Item>
      33           15 : DeriveDefault::go (Item &item)
      34              : {
      35           15 :   item.accept_vis (*this);
      36              : 
      37           15 :   rust_assert (expanded);
      38              : 
      39           15 :   return std::move (expanded);
      40              : }
      41              : 
      42              : std::unique_ptr<Expr>
      43           17 : DeriveDefault::default_call (std::unique_ptr<Type> &&type)
      44              : {
      45           17 :   auto default_trait = builder.type_path ({"core", "default", "Default"}, true);
      46              : 
      47           17 :   auto default_fn
      48           34 :     = builder.qualified_path_in_expression (std::move (type), default_trait,
      49           51 :                                             builder.path_segment ("default"));
      50              : 
      51           17 :   return builder.call (std::move (default_fn));
      52           17 : }
      53              : 
      54              : std::unique_ptr<AssociatedItem>
      55           15 : DeriveDefault::default_fn (std::unique_ptr<Expr> &&return_expr)
      56              : {
      57           15 :   auto self_ty
      58           15 :     = std::unique_ptr<Type> (new TypePath (builder.type_path ("Self")));
      59              : 
      60           15 :   auto block = std::unique_ptr<BlockExpr> (
      61           15 :     new BlockExpr ({}, std::move (return_expr), {}, {}, tl::nullopt, loc, loc));
      62              : 
      63           30 :   return builder.function ("default", {}, std::move (self_ty),
      64           15 :                            std::move (block));
      65           15 : }
      66              : 
      67              : std::unique_ptr<Item>
      68           15 : DeriveDefault::default_impl (
      69              :   std::unique_ptr<AssociatedItem> &&default_fn, std::string name,
      70              :   const std::vector<std::unique_ptr<GenericParam>> &type_generics)
      71              : {
      72           30 :   auto default_path = [this] () {
      73           15 :     return builder.type_path ({"core", "default", "Default"}, true);
      74           15 :   };
      75              : 
      76           15 :   auto trait_items = vec (std::move (default_fn));
      77              : 
      78           30 :   auto generics = setup_impl_generics (name, type_generics, [&, this] () {
      79            0 :     return builder.trait_bound (default_path ());
      80           15 :   });
      81              : 
      82           30 :   return builder.trait_impl (default_path (), std::move (generics.self_type),
      83              :                              std::move (trait_items),
      84           30 :                              std::move (generics.impl));
      85           15 : }
      86              : 
      87              : void
      88            8 : DeriveDefault::visit_struct (StructStruct &item)
      89              : {
      90            8 :   if (item.is_unit_struct ())
      91              :     {
      92            0 :       auto unit_ctor
      93            0 :         = builder.struct_expr_struct (item.get_struct_name ().as_string ());
      94            0 :       expanded = default_impl (default_fn (std::move (unit_ctor)),
      95            0 :                                item.get_struct_name ().as_string (),
      96            0 :                                item.get_generic_params ());
      97            0 :       return;
      98            0 :     }
      99              : 
     100            8 :   auto cloned_fields = std::vector<std::unique_ptr<StructExprField>> ();
     101           18 :   for (auto &field : item.get_fields ())
     102              :     {
     103           20 :       auto name = field.get_field_name ().as_string ();
     104           10 :       auto type = field.get_field_type ().reconstruct ();
     105           10 :       auto expr = default_call (std::move (type));
     106              : 
     107           10 :       cloned_fields.emplace_back (
     108           20 :         builder.struct_expr_field (std::move (name), std::move (expr)));
     109           10 :     }
     110              : 
     111           16 :   auto ctor = builder.struct_expr (item.get_struct_name ().as_string (),
     112           16 :                                    std::move (cloned_fields));
     113              : 
     114           16 :   expanded = default_impl (default_fn (std::move (ctor)),
     115            8 :                            item.get_struct_name ().as_string (),
     116           16 :                            item.get_generic_params ());
     117            8 : }
     118              : 
     119              : void
     120            7 : DeriveDefault::visit_tuple (TupleStruct &tuple_item)
     121              : {
     122            7 :   auto defaulted_fields = std::vector<std::unique_ptr<Expr>> ();
     123              : 
     124           14 :   for (auto &field : tuple_item.get_fields ())
     125              :     {
     126            7 :       auto type = field.get_field_type ().reconstruct ();
     127              : 
     128            7 :       defaulted_fields.emplace_back (default_call (std::move (type)));
     129            7 :     }
     130              : 
     131            7 :   auto return_expr
     132           14 :     = builder.call (builder.identifier (
     133            7 :                       tuple_item.get_struct_name ().as_string ()),
     134           14 :                     std::move (defaulted_fields));
     135              : 
     136           14 :   expanded = default_impl (default_fn (std::move (return_expr)),
     137            7 :                            tuple_item.get_struct_name ().as_string (),
     138           14 :                            tuple_item.get_generic_params ());
     139            7 : }
     140              : 
     141              : void
     142            0 : DeriveDefault::visit_enum (Enum &enum_item)
     143              : {
     144              :   // This is no longer the case in later Rust versions where you can choose a
     145              :   // default variant to emit using the `#[default]` attribute:
     146              :   //
     147              :   // ```rust
     148              :   // #[derive(Default)]
     149              :   // enum Baz {
     150              :   //     #[default]
     151              :   //     A,
     152              :   //     B(i32),
     153              :   //     C { a: i32 }
     154              :   // }
     155              :   // ```
     156              :   //
     157              :   // will emit the following impl
     158              :   //
     159              :   // ```rust
     160              :   // impl ::core::default::Default for Baz {
     161              :   //     #[inline]
     162              :   //     fn default() -> Baz { Self::A }
     163              :   // }
     164              :   // ```
     165            0 :   rust_error_at (loc, ErrorCode::E0665,
     166              :                  "%<Default%> cannot be derived for enums, only structs");
     167            0 : }
     168              : 
     169              : void
     170            0 : DeriveDefault::visit_union (Union &enum_item)
     171              : {
     172            0 :   rust_error_at (loc, "derive(Default) cannot be used on unions");
     173            0 : }
     174              : 
     175              : } // namespace AST
     176              : } // 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.