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