Line data Source code
1 : // Copyright (C) 2020-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.h"
20 : #include "rust-derive-clone.h"
21 : #include "rust-derive-copy.h"
22 : #include "rust-derive-debug.h"
23 : #include "rust-derive-default.h"
24 : #include "rust-derive-eq.h"
25 : #include "rust-derive-ord.h"
26 : #include "rust-derive-partial-eq.h"
27 : #include "rust-derive-hash.h"
28 : #include "rust-system.h"
29 :
30 : namespace Rust {
31 : namespace AST {
32 :
33 1051 : DeriveVisitor::DeriveVisitor (location_t loc, Builder::Source item_source)
34 1051 : : loc (loc), builder (Builder (loc, item_source))
35 1051 : {}
36 :
37 : std::vector<std::unique_ptr<Item>>
38 1056 : DeriveVisitor::derive (Item &item, const Attribute &attr,
39 : BuiltinMacro to_derive, Builder::Source item_source)
40 : {
41 1056 : auto loc = attr.get_locus ();
42 :
43 1056 : using Kind = AST::Item::Kind;
44 1056 : auto item_kind = item.get_item_kind ();
45 1056 : if (item_kind != Kind::Enum && item_kind != Kind::Struct
46 6 : && item_kind != Kind::Union)
47 : {
48 3 : rust_error_at (loc,
49 : "derive may only be applied to structs, enums and unions");
50 3 : return {};
51 : }
52 :
53 1053 : switch (to_derive)
54 : {
55 243 : case BuiltinMacro::Clone:
56 243 : return vec (DeriveClone (loc, item_source).go (item));
57 135 : case BuiltinMacro::Copy:
58 135 : return vec (DeriveCopy (loc, item_source).go (item));
59 175 : case BuiltinMacro::Debug:
60 175 : rust_warning_at (
61 : loc, 0,
62 : "derive(Debug) is not fully implemented yet and has no effect - only a "
63 : "stub implementation will be generated");
64 175 : return vec (DeriveDebug (loc, item_source).go (item));
65 27 : case BuiltinMacro::Default:
66 27 : return vec (DeriveDefault (loc, item_source).go (item));
67 105 : case BuiltinMacro::Eq:
68 105 : return DeriveEq (loc, item_source).go (item);
69 204 : case BuiltinMacro::PartialEq:
70 204 : return DerivePartialEq (loc, item_source).go (item);
71 37 : case BuiltinMacro::Hash:
72 37 : return vec (DeriveHash (loc, item_source).go (item));
73 62 : case BuiltinMacro::Ord:
74 62 : return vec (
75 62 : DeriveOrd (DeriveOrd::Ordering::Total, loc, item_source).go (item));
76 63 : case BuiltinMacro::PartialOrd:
77 63 : return vec (
78 63 : DeriveOrd (DeriveOrd::Ordering::Partial, loc, item_source).go (item));
79 2 : case BuiltinMacro::RustcEncodable:
80 2 : case BuiltinMacro::RustcDecodable:
81 3 : rust_sorry_at (loc, "derive(%s) is not yet implemented",
82 : to_derive == BuiltinMacro::RustcEncodable
83 : ? "RustcEncodable"
84 : : "RustcDecodable");
85 2 : return {};
86 0 : default:
87 0 : rust_unreachable ();
88 : };
89 : }
90 :
91 : DeriveVisitor::ImplGenerics
92 1360 : DeriveVisitor::setup_impl_generics (
93 : const std::string &type_name,
94 : const std::vector<std::unique_ptr<GenericParam>> &type_generics,
95 : tl::optional<std::function<std::unique_ptr<TypeParamBound> ()>> &&extra_bound)
96 : const
97 : {
98 1360 : std::vector<Lifetime> lifetime_args;
99 1360 : std::vector<GenericArg> generic_args;
100 1360 : std::vector<std::unique_ptr<GenericParam>> impl_generics;
101 1698 : for (const auto &generic : type_generics)
102 : {
103 338 : switch (generic->get_kind ())
104 : {
105 93 : case GenericParam::Kind::Lifetime:
106 93 : {
107 93 : LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get ();
108 :
109 93 : Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ());
110 93 : lifetime_args.push_back (std::move (l));
111 :
112 93 : auto impl_lifetime_param
113 93 : = builder.new_lifetime_param (lifetime_param);
114 93 : impl_generics.push_back (std::move (impl_lifetime_param));
115 93 : }
116 93 : break;
117 :
118 238 : case GenericParam::Kind::Type:
119 238 : {
120 238 : TypeParam &type_param = (TypeParam &) *generic.get ();
121 :
122 238 : std::unique_ptr<Type> associated_type = builder.single_type_path (
123 476 : type_param.get_type_representation ().as_string ());
124 :
125 238 : GenericArg type_arg
126 238 : = GenericArg::create_type (std::move (associated_type));
127 238 : generic_args.push_back (std::move (type_arg));
128 :
129 238 : std::vector<std::unique_ptr<TypeParamBound>> extra_bounds;
130 :
131 238 : if (extra_bound)
132 206 : extra_bounds.emplace_back (extra_bound.value () ());
133 :
134 238 : auto impl_type_param
135 238 : = builder.new_type_param (type_param, std::move (extra_bounds),
136 238 : Builder::DefaultParamGen::Remove);
137 :
138 238 : impl_generics.push_back (std::move (impl_type_param));
139 238 : }
140 238 : break;
141 :
142 7 : case GenericParam::Kind::Const:
143 7 : {
144 7 : ConstGenericParam &const_param
145 7 : = (ConstGenericParam &) *generic.get ();
146 :
147 7 : auto associated_expr
148 : = std::make_unique<IdentifierExpr> (const_param.get_name (),
149 7 : std::vector<Attribute> (),
150 7 : const_param.get_locus ());
151 :
152 7 : GenericArg const_arg
153 7 : = GenericArg::create_const (std::move (associated_expr));
154 7 : generic_args.push_back (std::move (const_arg));
155 :
156 7 : auto impl_const_param = builder.new_const_param (const_param);
157 7 : impl_generics.push_back (std::move (impl_const_param));
158 7 : }
159 7 : break;
160 : }
161 : }
162 :
163 1360 : auto generic_args_for_self
164 1360 : = GenericArgs (lifetime_args, generic_args, {} /*binding args*/, loc);
165 :
166 1360 : std::unique_ptr<Type> self_type_path
167 1360 : = impl_generics.empty ()
168 2454 : ? builder.single_type_path (type_name)
169 4080 : : builder.single_generic_type_path (type_name, generic_args_for_self);
170 :
171 1360 : return ImplGenerics{std::move (self_type_path), std::move (impl_generics)};
172 1360 : }
173 :
174 : } // namespace AST
175 : } // namespace Rust
|