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