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
|