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
|