Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : : #ifndef RUST_AST_ITEM_H
20 : : #define RUST_AST_ITEM_H
21 : :
22 : : #include "rust-ast.h"
23 : : #include "rust-hir-map.h"
24 : : #include "rust-mapping-common.h"
25 : : #include "rust-path.h"
26 : : #include "rust-common.h"
27 : : #include "rust-expr.h"
28 : :
29 : : namespace Rust {
30 : : namespace AST {
31 : : // forward decls
32 : : class TypePath;
33 : :
34 : : // TODO: inline?
35 : : /*struct AbiName {
36 : : std::string abi_name;
37 : : // Technically is meant to be STRING_LITERAL
38 : :
39 : : public:
40 : : // Returns whether abi name is empty, i.e. doesn't exist.
41 : : bool is_empty() const {
42 : : return abi_name.empty();
43 : : }
44 : :
45 : : AbiName(std::string name) : abi_name(std::move(name)) {}
46 : :
47 : : // Empty AbiName constructor
48 : : AbiName() {}
49 : : };*/
50 : :
51 : : // A type generic parameter (as opposed to a lifetime generic parameter)
52 : : class TypeParam : public GenericParam
53 : : {
54 : : // bool has_outer_attribute;
55 : : // std::unique_ptr<Attribute> outer_attr;
56 : : AST::AttrVec outer_attrs;
57 : :
58 : : Identifier type_representation;
59 : :
60 : : // bool has_type_param_bounds;
61 : : // TypeParamBounds type_param_bounds;
62 : : std::vector<std::unique_ptr<TypeParamBound>>
63 : : type_param_bounds; // inlined form
64 : :
65 : : // bool has_type;
66 : : std::unique_ptr<Type> type;
67 : :
68 : : location_t locus;
69 : :
70 : : public:
71 : 16654 : Identifier get_type_representation () const { return type_representation; }
72 : :
73 : : // Returns whether the type of the type param has been specified.
74 : 93358 : bool has_type () const { return type != nullptr; }
75 : :
76 : : // Returns whether the type param has type param bounds.
77 : 13843 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
78 : :
79 : : // Returns whether the type param has an outer attribute.
80 : 0 : bool has_outer_attribute () const { return !outer_attrs.empty (); }
81 : :
82 : 75879 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
83 : :
84 : 7466 : TypeParam (Identifier type_representation, location_t locus = UNDEF_LOCATION,
85 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
86 : : = std::vector<std::unique_ptr<TypeParamBound>> (),
87 : : std::unique_ptr<Type> type = nullptr,
88 : : AST::AttrVec outer_attrs = {})
89 : 7466 : : GenericParam (Analysis::Mappings::get ().get_next_node_id ()),
90 : 7466 : outer_attrs (std::move (outer_attrs)),
91 : 7466 : type_representation (std::move (type_representation)),
92 : 7466 : type_param_bounds (std::move (type_param_bounds)),
93 : 7466 : type (std::move (type)), locus (locus)
94 : 7466 : {}
95 : :
96 : : // Copy constructor uses clone
97 : 16 : TypeParam (TypeParam const &other)
98 : 16 : : GenericParam (other.node_id), outer_attrs (other.outer_attrs),
99 : 16 : type_representation (other.type_representation), locus (other.locus)
100 : : {
101 : : // guard to prevent null pointer dereference
102 : 16 : if (other.type != nullptr)
103 : 0 : type = other.type->clone_type ();
104 : :
105 : 16 : type_param_bounds.reserve (other.type_param_bounds.size ());
106 : 16 : for (const auto &e : other.type_param_bounds)
107 : 0 : type_param_bounds.push_back (e->clone_type_param_bound ());
108 : 16 : }
109 : :
110 : : // Overloaded assignment operator to clone
111 : : TypeParam &operator= (TypeParam const &other)
112 : : {
113 : : type_representation = other.type_representation;
114 : : outer_attrs = other.outer_attrs;
115 : : locus = other.locus;
116 : : node_id = other.node_id;
117 : :
118 : : // guard to prevent null pointer dereference
119 : : if (other.type != nullptr)
120 : : type = other.type->clone_type ();
121 : : else
122 : : type = nullptr;
123 : :
124 : : type_param_bounds.reserve (other.type_param_bounds.size ());
125 : : for (const auto &e : other.type_param_bounds)
126 : : type_param_bounds.push_back (e->clone_type_param_bound ());
127 : :
128 : : return *this;
129 : : }
130 : :
131 : : // move constructors
132 : : TypeParam (TypeParam &&other) = default;
133 : : TypeParam &operator= (TypeParam &&other) = default;
134 : :
135 : : std::string as_string () const override;
136 : :
137 : 23918 : location_t get_locus () const override final { return locus; }
138 : :
139 : 4164 : Kind get_kind () const override final { return Kind::Type; }
140 : :
141 : : void accept_vis (ASTVisitor &vis) override;
142 : :
143 : : // TODO: is this better? Or is a "vis_block" better?
144 : 2363 : Type &get_type ()
145 : : {
146 : 2363 : rust_assert (type != nullptr);
147 : 2363 : return *type;
148 : : }
149 : :
150 : 321 : std::unique_ptr<Type> &get_type_ptr ()
151 : : {
152 : 321 : rust_assert (type != nullptr);
153 : 321 : return type;
154 : : }
155 : :
156 : : // TODO: mutable getter seems kinda dodgy
157 : 35 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
158 : : {
159 : 67788 : return type_param_bounds;
160 : : }
161 : : const std::vector<std::unique_ptr<TypeParamBound>> &
162 : : get_type_param_bounds () const
163 : : {
164 : : return type_param_bounds;
165 : : }
166 : :
167 : : protected:
168 : : // Clone function implementation as virtual method
169 : 12 : TypeParam *clone_generic_param_impl () const override
170 : : {
171 : 12 : return new TypeParam (*this);
172 : : }
173 : : };
174 : :
175 : : /* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
176 : : * TypeBoundWhereClauseItem */
177 : 129 : class WhereClauseItem
178 : : {
179 : : public:
180 : : virtual ~WhereClauseItem () {}
181 : :
182 : : // Unique pointer custom clone function
183 : 0 : std::unique_ptr<WhereClauseItem> clone_where_clause_item () const
184 : : {
185 : 0 : return std::unique_ptr<WhereClauseItem> (clone_where_clause_item_impl ());
186 : : }
187 : :
188 : : virtual std::string as_string () const = 0;
189 : :
190 : : virtual void accept_vis (ASTVisitor &vis) = 0;
191 : :
192 : : virtual NodeId get_node_id () const = 0;
193 : :
194 : : protected:
195 : : // Clone function implementation as pure virtual method
196 : : virtual WhereClauseItem *clone_where_clause_item_impl () const = 0;
197 : : };
198 : :
199 : : // A lifetime where clause item
200 : : class LifetimeWhereClauseItem : public WhereClauseItem
201 : : {
202 : : Lifetime lifetime;
203 : : std::vector<Lifetime> lifetime_bounds;
204 : : location_t locus;
205 : : NodeId node_id;
206 : :
207 : : public:
208 : 2 : LifetimeWhereClauseItem (Lifetime lifetime,
209 : : std::vector<Lifetime> lifetime_bounds,
210 : : location_t locus)
211 : 2 : : lifetime (std::move (lifetime)),
212 : 2 : lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
213 : 2 : node_id (Analysis::Mappings::get ().get_next_node_id ())
214 : 2 : {}
215 : :
216 : : std::string as_string () const override;
217 : :
218 : : void accept_vis (ASTVisitor &vis) override;
219 : :
220 : 2 : NodeId get_node_id () const override final { return node_id; }
221 : :
222 : 14 : Lifetime &get_lifetime () { return lifetime; }
223 : :
224 : 14 : std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
225 : :
226 : 2 : location_t get_locus () const { return locus; }
227 : :
228 : : protected:
229 : : // Clone function implementation as (not pure) virtual method
230 : 0 : LifetimeWhereClauseItem *clone_where_clause_item_impl () const override
231 : : {
232 : 0 : return new LifetimeWhereClauseItem (*this);
233 : : }
234 : : };
235 : :
236 : : // A type bound where clause item
237 : : class TypeBoundWhereClauseItem : public WhereClauseItem
238 : : {
239 : : std::vector<LifetimeParam> for_lifetimes;
240 : : std::unique_ptr<Type> bound_type;
241 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
242 : : NodeId node_id;
243 : : location_t locus;
244 : :
245 : : public:
246 : : // Returns whether the item has ForLifetimes
247 : 4 : bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
248 : :
249 : 1091 : std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
250 : :
251 : : // Returns whether the item has type param bounds
252 : 100 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
253 : :
254 : 127 : TypeBoundWhereClauseItem (
255 : : std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type,
256 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
257 : : location_t locus)
258 : 127 : : for_lifetimes (std::move (for_lifetimes)),
259 : 127 : bound_type (std::move (bound_type)),
260 : 127 : type_param_bounds (std::move (type_param_bounds)),
261 : 127 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
262 : 127 : {}
263 : :
264 : : // Copy constructor requires clone
265 : 0 : TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
266 : 0 : : for_lifetimes (other.for_lifetimes),
267 : 0 : bound_type (other.bound_type->clone_type ())
268 : : {
269 : 0 : node_id = other.node_id;
270 : 0 : type_param_bounds.reserve (other.type_param_bounds.size ());
271 : 0 : for (const auto &e : other.type_param_bounds)
272 : 0 : type_param_bounds.push_back (e->clone_type_param_bound ());
273 : 0 : }
274 : :
275 : : // Overload assignment operator to clone
276 : : TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other)
277 : : {
278 : : node_id = other.node_id;
279 : : for_lifetimes = other.for_lifetimes;
280 : : bound_type = other.bound_type->clone_type ();
281 : : type_param_bounds.reserve (other.type_param_bounds.size ());
282 : : for (const auto &e : other.type_param_bounds)
283 : : type_param_bounds.push_back (e->clone_type_param_bound ());
284 : :
285 : : return *this;
286 : : }
287 : :
288 : : // move constructors
289 : : TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default;
290 : : TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other)
291 : : = default;
292 : :
293 : : std::string as_string () const override;
294 : :
295 : : void accept_vis (ASTVisitor &vis) override;
296 : :
297 : 1420 : Type &get_type ()
298 : : {
299 : 1420 : rust_assert (bound_type != nullptr);
300 : 1420 : return *bound_type;
301 : : }
302 : :
303 : 209 : std::unique_ptr<Type> &get_type_ptr ()
304 : : {
305 : 209 : rust_assert (bound_type != nullptr);
306 : 209 : return bound_type;
307 : : }
308 : :
309 : : // TODO: this mutable getter seems really dodgy. Think up better way.
310 : 4 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
311 : : {
312 : 1304 : return type_param_bounds;
313 : : }
314 : :
315 : : const std::vector<std::unique_ptr<TypeParamBound>> &
316 : : get_type_param_bounds () const
317 : : {
318 : : return type_param_bounds;
319 : : }
320 : :
321 : 113 : NodeId get_node_id () const override final { return node_id; }
322 : :
323 : 113 : location_t get_locus () const { return locus; }
324 : :
325 : : protected:
326 : : // Clone function implementation as (not pure) virtual method
327 : 0 : TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
328 : : {
329 : 0 : return new TypeBoundWhereClauseItem (*this);
330 : : }
331 : : };
332 : :
333 : : // A where clause
334 : 60428 : class WhereClause
335 : : {
336 : : std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
337 : : NodeId node_id;
338 : :
339 : : public:
340 : 30248 : WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
341 : 30248 : : where_clause_items (std::move (where_clause_items)),
342 : 30248 : node_id (Analysis::Mappings::get ().get_next_node_id ())
343 : 30248 : {}
344 : :
345 : : // copy constructor with vector clone
346 : 34829 : WhereClause (WhereClause const &other)
347 : 34829 : {
348 : 34829 : node_id = other.node_id;
349 : 34829 : where_clause_items.reserve (other.where_clause_items.size ());
350 : 34829 : for (const auto &e : other.where_clause_items)
351 : 0 : where_clause_items.push_back (e->clone_where_clause_item ());
352 : 34829 : }
353 : :
354 : : // overloaded assignment operator with vector clone
355 : 0 : WhereClause &operator= (WhereClause const &other)
356 : : {
357 : 0 : node_id = other.node_id;
358 : 0 : where_clause_items.reserve (other.where_clause_items.size ());
359 : 0 : for (const auto &e : other.where_clause_items)
360 : 0 : where_clause_items.push_back (e->clone_where_clause_item ());
361 : :
362 : 0 : return *this;
363 : : }
364 : :
365 : : // move constructors
366 : 30387 : WhereClause (WhereClause &&other) = default;
367 : : WhereClause &operator= (WhereClause &&other) = default;
368 : :
369 : : // Creates a WhereClause with no items.
370 : 30125 : static WhereClause create_empty ()
371 : : {
372 : 30125 : return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
373 : : }
374 : :
375 : : // Returns whether the WhereClause has no items.
376 : 329297 : bool is_empty () const { return where_clause_items.empty (); }
377 : :
378 : : std::string as_string () const;
379 : :
380 : : NodeId get_node_id () const { return node_id; }
381 : :
382 : : // TODO: this mutable getter seems kinda dodgy
383 : 4 : std::vector<std::unique_ptr<WhereClauseItem>> &get_items ()
384 : : {
385 : 24846 : return where_clause_items;
386 : : }
387 : : const std::vector<std::unique_ptr<WhereClauseItem>> &get_items () const
388 : : {
389 : : return where_clause_items;
390 : : }
391 : : };
392 : :
393 : : // Abstract class Param
394 : 17880 : class Param : public Visitable
395 : : {
396 : : public:
397 : 54334 : Param (std::vector<Attribute> outer_attrs, location_t locus)
398 : 54334 : : outer_attrs (std::move (outer_attrs)), locus (locus),
399 : 54334 : node_id (Analysis::Mappings::get ().get_next_node_id ())
400 : 54334 : {}
401 : :
402 : : virtual ~Param () = default;
403 : :
404 : 25424 : std::unique_ptr<Param> clone_param () const
405 : : {
406 : 25424 : return std::unique_ptr<Param> (clone_param_impl ());
407 : : }
408 : :
409 : 65580 : virtual bool is_variadic () const { return false; }
410 : :
411 : 48241 : virtual bool is_self () const { return false; }
412 : :
413 : 8685 : NodeId get_node_id () const { return node_id; }
414 : :
415 : 12064 : location_t get_locus () const { return locus; }
416 : :
417 : 21076 : std::vector<Attribute> get_outer_attrs () const { return outer_attrs; }
418 : :
419 : 60067 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
420 : :
421 : : virtual Param *clone_param_impl () const = 0;
422 : :
423 : : virtual std::string as_string () const = 0;
424 : :
425 : : protected:
426 : : std::vector<Attribute> outer_attrs;
427 : : location_t locus;
428 : : NodeId node_id;
429 : : };
430 : :
431 : : // A self parameter in a method
432 : : class SelfParam : public Param
433 : : {
434 : : bool has_ref;
435 : : bool is_mut;
436 : : // bool has_lifetime; // only possible if also ref
437 : : tl::optional<Lifetime> lifetime;
438 : :
439 : : // bool has_type; // only possible if not ref
440 : : std::unique_ptr<Type> type;
441 : :
442 : : // Unrestricted constructor used for error state
443 : : SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut,
444 : : Type *type)
445 : : : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
446 : : lifetime (std::move (lifetime)), type (type)
447 : : {}
448 : : // this is ok as no outside classes can ever call this
449 : :
450 : : // TODO: self param can have outer attributes
451 : :
452 : : public:
453 : : // Returns whether the self-param has a type field.
454 : 105474 : bool has_type () const { return type != nullptr; }
455 : :
456 : : // Returns whether the self-param has a valid lifetime.
457 : 63392 : bool has_lifetime () const { return lifetime.has_value (); }
458 : :
459 : : // Returns whether the self-param is in an error state.
460 : 0 : bool is_error () const
461 : : {
462 : 0 : return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
463 : : // not having either is not an error
464 : : }
465 : :
466 : : // Creates an error state self-param.
467 : : static SelfParam create_error ()
468 : : {
469 : : // cannot have no ref but have a lifetime at the same time
470 : : return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
471 : : }
472 : :
473 : : // Type-based self parameter (not ref, no lifetime)
474 : 3175 : SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
475 : 6350 : : Param ({}, locus), has_ref (false), is_mut (is_mut),
476 : 3175 : lifetime (tl::nullopt), type (std::move (type))
477 : 3175 : {}
478 : :
479 : : // Lifetime-based self parameter (is ref, no type)
480 : 3010 : SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
481 : 6020 : : Param ({}, locus), has_ref (true), is_mut (is_mut),
482 : 3010 : lifetime (std::move (lifetime))
483 : 3010 : {}
484 : :
485 : : // Copy constructor requires clone
486 : 20222 : SelfParam (SelfParam const &other)
487 : 20222 : : Param (other.get_outer_attrs (), other.get_locus ()),
488 : 40444 : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime)
489 : : {
490 : 20222 : node_id = other.node_id;
491 : 20222 : if (other.type != nullptr)
492 : 2 : type = other.type->clone_type ();
493 : 20222 : }
494 : :
495 : : // Overload assignment operator to use clone
496 : : SelfParam &operator= (SelfParam const &other)
497 : : {
498 : : is_mut = other.is_mut;
499 : : has_ref = other.has_ref;
500 : : lifetime = other.lifetime;
501 : : locus = other.locus;
502 : : node_id = other.node_id;
503 : : outer_attrs = other.outer_attrs;
504 : :
505 : : if (other.type != nullptr)
506 : : type = other.type->clone_type ();
507 : : else
508 : : type = nullptr;
509 : :
510 : : return *this;
511 : : }
512 : :
513 : : // move constructors
514 : : SelfParam (SelfParam &&other) = default;
515 : : SelfParam &operator= (SelfParam &&other) = default;
516 : :
517 : : std::string as_string () const override;
518 : :
519 : 37499 : location_t get_locus () const { return locus; }
520 : :
521 : 62932 : bool is_self () const override { return true; }
522 : :
523 : 11950 : bool get_has_ref () const { return has_ref; };
524 : 11614 : bool get_is_mut () const { return is_mut; }
525 : :
526 : 0 : Lifetime get_lifetime () const { return lifetime.value (); }
527 : 30832 : Lifetime &get_lifetime () { return lifetime.value (); }
528 : :
529 : 12015 : NodeId get_node_id () const { return node_id; }
530 : :
531 : : // TODO: is this better? Or is a "vis_block" better?
532 : 32 : Type &get_type ()
533 : : {
534 : 32 : rust_assert (has_type ());
535 : 32 : return *type;
536 : : }
537 : :
538 : 3 : std::unique_ptr<Type> &get_type_ptr ()
539 : : {
540 : 3 : rust_assert (has_type ());
541 : 3 : return type;
542 : : }
543 : :
544 : : void accept_vis (ASTVisitor &vis) override;
545 : :
546 : 14238 : SelfParam *clone_param_impl () const override
547 : : {
548 : 14238 : return new SelfParam (*this);
549 : : }
550 : : };
551 : :
552 : : // Qualifiers for function, i.e. const, unsafe, extern etc.
553 : 35969 : class FunctionQualifiers
554 : : {
555 : : Async async_status;
556 : : Const const_status;
557 : : Unsafety unsafe_status;
558 : : bool has_extern;
559 : : std::string extern_abi;
560 : : location_t locus;
561 : :
562 : : public:
563 : 17217 : FunctionQualifiers (location_t locus, Async async_status, Const const_status,
564 : : Unsafety unsafe_status, bool has_extern = false,
565 : : std::string extern_abi = std::string ())
566 : 17217 : : async_status (async_status), const_status (const_status),
567 : 17217 : unsafe_status (unsafe_status), has_extern (has_extern),
568 : 17217 : extern_abi (std::move (extern_abi)), locus (locus)
569 : : {
570 : 17217 : if (!this->extern_abi.empty ())
571 : : {
572 : : // having extern is required; not having it is an implementation error
573 : 89 : rust_assert (has_extern);
574 : : }
575 : 17217 : }
576 : :
577 : : std::string as_string () const;
578 : :
579 : 15946 : bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; }
580 : 15946 : bool is_extern () const { return has_extern; }
581 : 18570 : bool is_const () const { return const_status == Const::Yes; }
582 : 35537 : bool is_async () const { return async_status == Async::Yes; }
583 : 244 : std::string get_extern_abi () const { return extern_abi; }
584 : 14404 : bool has_abi () const { return !extern_abi.empty (); }
585 : 14347 : Const get_const_status () const { return const_status; }
586 : 14347 : Async get_async_status () const { return async_status; }
587 : :
588 : 107 : location_t get_locus () const { return locus; }
589 : : };
590 : :
591 : : class VariadicParam : public Param
592 : : {
593 : : std::unique_ptr<Pattern> param_name;
594 : :
595 : : public:
596 : 15 : VariadicParam (std::unique_ptr<Pattern> param_name,
597 : : std::vector<Attribute> outer_attrs, location_t locus)
598 : 15 : : Param (std::move (outer_attrs), std::move (locus)),
599 : 15 : param_name (std::move (param_name))
600 : 15 : {}
601 : :
602 : 829 : VariadicParam (std::vector<Attribute> outer_attrs, location_t locus)
603 : 829 : : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr)
604 : 829 : {}
605 : :
606 : 854 : VariadicParam (VariadicParam const &other)
607 : 854 : : Param (other.get_outer_attrs (), other.locus)
608 : : {
609 : 854 : if (other.param_name != nullptr)
610 : 15 : param_name = other.param_name->clone_pattern ();
611 : 854 : }
612 : :
613 : : VariadicParam &operator= (VariadicParam const &other)
614 : : {
615 : : outer_attrs = other.outer_attrs;
616 : : locus = other.locus;
617 : : node_id = other.node_id;
618 : : if (other.param_name != nullptr)
619 : : param_name = other.param_name->clone_pattern ();
620 : : else
621 : : param_name = nullptr;
622 : :
623 : : return *this;
624 : : }
625 : :
626 : 4446 : bool is_variadic () const override { return true; }
627 : :
628 : 10 : VariadicParam *clone_param_impl () const override
629 : : {
630 : 10 : return new VariadicParam (*this);
631 : : }
632 : :
633 : 144 : Pattern &get_pattern ()
634 : : {
635 : 144 : rust_assert (param_name != nullptr);
636 : 144 : return *param_name;
637 : : }
638 : :
639 : 0 : const Pattern &get_pattern () const
640 : : {
641 : 0 : rust_assert (param_name != nullptr);
642 : 0 : return *param_name;
643 : : }
644 : :
645 : 7743 : bool has_pattern () const { return param_name != nullptr; }
646 : :
647 : : void accept_vis (ASTVisitor &vis) override;
648 : :
649 : : std::string as_string () const override;
650 : : };
651 : :
652 : : // A function parameter
653 : : class FunctionParam : public Param
654 : : {
655 : : std::unique_ptr<Pattern> param_name;
656 : : std::unique_ptr<Type> type;
657 : :
658 : : public:
659 : 8983 : FunctionParam (std::unique_ptr<Pattern> param_name,
660 : : std::unique_ptr<Type> param_type,
661 : : std::vector<Attribute> outer_attrs, location_t locus)
662 : 8983 : : Param (std::move (outer_attrs), locus),
663 : 8983 : param_name (std::move (param_name)), type (std::move (param_type))
664 : 8983 : {}
665 : :
666 : : // Copy constructor uses clone
667 : 17246 : FunctionParam (FunctionParam const &other)
668 : 17246 : : Param (other.get_outer_attrs (), other.locus)
669 : : {
670 : : // guard to prevent nullptr dereference
671 : 17246 : if (other.param_name != nullptr)
672 : 17246 : param_name = other.param_name->clone_pattern ();
673 : 17246 : if (other.type != nullptr)
674 : 17246 : type = other.type->clone_type ();
675 : 17246 : }
676 : :
677 : : // Overload assignment operator to use clone
678 : : FunctionParam &operator= (FunctionParam const &other)
679 : : {
680 : : locus = other.locus;
681 : : node_id = other.node_id;
682 : :
683 : : // guard to prevent nullptr dereference
684 : : if (other.param_name != nullptr)
685 : : param_name = other.param_name->clone_pattern ();
686 : : else
687 : : param_name = nullptr;
688 : : if (other.type != nullptr)
689 : : type = other.type->clone_type ();
690 : : else
691 : : type = nullptr;
692 : :
693 : : return *this;
694 : : }
695 : :
696 : : // move constructors
697 : 8940 : FunctionParam (FunctionParam &&other) = default;
698 : : FunctionParam &operator= (FunctionParam &&other) = default;
699 : :
700 : : // Returns whether FunctionParam is in an invalid state.
701 : : bool is_error () const { return param_name == nullptr || type == nullptr; }
702 : :
703 : : // Creates an error FunctionParam.
704 : : static FunctionParam create_error ()
705 : : {
706 : : return FunctionParam (nullptr, nullptr, {}, UNDEF_LOCATION);
707 : : }
708 : :
709 : : std::string as_string () const override;
710 : :
711 : : // TODO: seems kinda dodgy. Think of better way.
712 : 108328 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
713 : 17246 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
714 : :
715 : : // TODO: is this better? Or is a "vis_block" better?
716 : 127491 : Pattern &get_pattern ()
717 : : {
718 : 127491 : rust_assert (param_name != nullptr);
719 : 127491 : return *param_name;
720 : : }
721 : :
722 : 84857 : bool has_name () const { return param_name != nullptr; }
723 : :
724 : : // TODO: is this better? Or is a "vis_block" better?
725 : 124617 : Type &get_type ()
726 : : {
727 : 124617 : rust_assert (type != nullptr);
728 : 124617 : return *type;
729 : : }
730 : :
731 : 15283 : std::unique_ptr<Type> &get_type_ptr ()
732 : : {
733 : 15283 : rust_assert (type != nullptr);
734 : 15283 : return type;
735 : : }
736 : :
737 : 11176 : FunctionParam *clone_param_impl () const override
738 : : {
739 : 11176 : return new FunctionParam (*this);
740 : : }
741 : :
742 : : void accept_vis (ASTVisitor &vis) override;
743 : : };
744 : :
745 : : // Rust module item - abstract base class
746 : : class Module : public VisItem
747 : : {
748 : : public:
749 : : // Type of the current module. A module can be either loaded or unloaded,
750 : : // meaning that the items of the module can already be present or not. For
751 : : // example, the following module would be loaded: `mod foo { fn bar() {} }`.
752 : : // However, the module would be unloaded if it refers to an external file (i.e
753 : : // `mod foo;`) and then become loaded upon expansion.
754 : : enum ModuleKind
755 : : {
756 : : LOADED,
757 : : UNLOADED,
758 : : };
759 : :
760 : 4812 : Identifier get_name () const { return module_name; }
761 : :
762 : : private:
763 : : Identifier module_name;
764 : : location_t locus;
765 : : ModuleKind kind;
766 : : Unsafety safety;
767 : :
768 : : // Name of the file including the module
769 : : std::string outer_filename;
770 : : // bool has_inner_attrs;
771 : : std::vector<Attribute> inner_attrs;
772 : : // bool has_items;
773 : : std::vector<std::unique_ptr<Item>> items;
774 : : // Names of including inline modules (immediate parent is last in the list)
775 : : std::vector<std::string> module_scope;
776 : :
777 : : // Filename the module refers to. Empty string on LOADED modules or if an
778 : : // error occured when dealing with UNLOADED modules
779 : : std::string module_file;
780 : :
781 : 34 : void clone_items (const std::vector<std::unique_ptr<Item>> &other_items)
782 : : {
783 : 34 : items.reserve (other_items.size ());
784 : 106 : for (const auto &e : other_items)
785 : 72 : items.push_back (e->clone_item ());
786 : 34 : }
787 : :
788 : : public:
789 : : // Returns whether the module has items in its body.
790 : : bool has_items () const { return !items.empty (); }
791 : :
792 : : // Returns whether the module has any inner attributes.
793 : : bool has_inner_attrs () const { return !inner_attrs.empty (); }
794 : :
795 : : // Unloaded module constructor
796 : 77 : Module (Identifier module_name, Visibility visibility,
797 : : std::vector<Attribute> outer_attrs, location_t locus, Unsafety safety,
798 : : std::string outer_filename, std::vector<std::string> module_scope)
799 : 77 : : VisItem (std::move (visibility), std::move (outer_attrs)),
800 : 154 : module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
801 : 77 : safety (safety), outer_filename (outer_filename),
802 : 77 : inner_attrs (std::vector<Attribute> ()),
803 : 77 : items (std::vector<std::unique_ptr<Item>> ()),
804 : 77 : module_scope (std::move (module_scope))
805 : 77 : {}
806 : :
807 : : // Loaded module constructor, with items
808 : 992 : Module (Identifier name, location_t locus,
809 : : std::vector<std::unique_ptr<Item>> items,
810 : : Visibility visibility = Visibility::create_error (),
811 : : Unsafety safety = Unsafety::Normal,
812 : : std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
813 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
814 : 992 : : VisItem (std::move (visibility), std::move (outer_attrs)),
815 : 1984 : module_name (name), locus (locus), kind (ModuleKind::LOADED),
816 : 992 : safety (safety), outer_filename (std::string ()),
817 : 992 : inner_attrs (std::move (inner_attrs)), items (std::move (items))
818 : 992 : {}
819 : :
820 : : // Copy constructor with vector clone
821 : 34 : Module (Module const &other)
822 : 102 : : VisItem (other), module_name (other.module_name), locus (other.locus),
823 : 34 : kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs),
824 : 34 : module_scope (other.module_scope)
825 : : {
826 : : // We need to check whether we are copying a loaded module or an unloaded
827 : : // one. In the second case, clear the `items` vector.
828 : 34 : if (other.kind == LOADED)
829 : 34 : clone_items (other.items);
830 : : else
831 : 0 : items.clear ();
832 : 34 : }
833 : :
834 : : // Overloaded assignment operator with vector clone
835 : : Module &operator= (Module const &other)
836 : : {
837 : : VisItem::operator= (other);
838 : :
839 : : module_name = other.module_name;
840 : : locus = other.locus;
841 : : kind = other.kind;
842 : : inner_attrs = other.inner_attrs;
843 : : module_scope = other.module_scope;
844 : :
845 : : // Likewise, we need to clear the `items` vector in case the other module is
846 : : // unloaded
847 : : if (kind == LOADED)
848 : : clone_items (other.items);
849 : : else
850 : : items.clear ();
851 : :
852 : : return *this;
853 : : }
854 : :
855 : : // Search for the filename associated with an external module, storing it in
856 : : // module_file
857 : : void process_file_path ();
858 : : // Load the items contained in an external module
859 : : void load_items ();
860 : :
861 : : void accept_vis (ASTVisitor &vis) override;
862 : :
863 : : /* Override that runs the function recursively on all items contained within
864 : : * the module. */
865 : : void add_crate_name (std::vector<std::string> &names) const override;
866 : :
867 : : // Returns the kind of the module
868 : 3819 : enum ModuleKind get_kind () const { return kind; }
869 : :
870 : 1065 : Unsafety get_unsafety () const { return safety; }
871 : :
872 : : // TODO: think of better way to do this - mutable getter seems dodgy
873 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
874 : 10628 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
875 : :
876 : : const std::vector<std::unique_ptr<Item>> &get_items () const { return items; }
877 : 17393 : std::vector<std::unique_ptr<Item>> &get_items () { return items; }
878 : :
879 : 1268 : std::vector<std::unique_ptr<AST::Item>> take_items ()
880 : : {
881 : 1268 : return std::move (items);
882 : : }
883 : :
884 : 1268 : void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
885 : : {
886 : 1268 : items = std::move (new_items);
887 : : }
888 : :
889 : : // move constructors
890 : : Module (Module &&other) = default;
891 : : Module &operator= (Module &&other) = default;
892 : :
893 : : std::string as_string () const override;
894 : :
895 : 2589 : location_t get_locus () const override final { return locus; }
896 : :
897 : : // Invalid if name is empty, so base stripping on that.
898 : 0 : void mark_for_strip () override { module_name = {""}; }
899 : 2917 : bool is_marked_for_strip () const override { return module_name.empty (); }
900 : :
901 : 1282 : Item::Kind get_item_kind () const override { return Item::Kind::Module; }
902 : :
903 : : protected:
904 : : /* Use covariance to implement clone function as returning this object
905 : : * rather than base */
906 : 34 : Module *clone_item_impl () const override { return new Module (*this); }
907 : : };
908 : :
909 : : // Rust extern crate declaration AST node
910 : : class ExternCrate : public VisItem
911 : : {
912 : : // this is either an identifier or "self", with self parsed to string
913 : : std::string referenced_crate;
914 : : // bool has_as_clause;
915 : : // AsClause as_clause;
916 : : // this is either an identifier or "_", with _ parsed to string
917 : : std::string as_clause_name;
918 : :
919 : : location_t locus;
920 : :
921 : : /* e.g.
922 : : "extern crate foo as _"
923 : : "extern crate foo"
924 : : "extern crate std as cool_std" */
925 : : public:
926 : : std::string as_string () const override;
927 : :
928 : : // Returns whether extern crate declaration has an as clause.
929 : 24 : bool has_as_clause () const { return !as_clause_name.empty (); }
930 : :
931 : : /* Returns whether extern crate declaration references the current crate
932 : : * (i.e. self). */
933 : 57 : bool references_self () const { return referenced_crate == "self"; }
934 : :
935 : : // Constructor
936 : 4965 : ExternCrate (std::string referenced_crate, Visibility visibility,
937 : : std::vector<Attribute> outer_attrs, location_t locus,
938 : : std::string as_clause_name = std::string ())
939 : 4965 : : VisItem (std::move (visibility), std::move (outer_attrs)),
940 : 4965 : referenced_crate (std::move (referenced_crate)),
941 : 4965 : as_clause_name (std::move (as_clause_name)), locus (locus)
942 : 4965 : {}
943 : :
944 : 76 : location_t get_locus () const override final { return locus; }
945 : :
946 : : void accept_vis (ASTVisitor &vis) override;
947 : :
948 : 9 : const std::string &get_referenced_crate () const { return referenced_crate; }
949 : 0 : const std::string &get_as_clause () const { return as_clause_name; }
950 : :
951 : : // Override that adds extern crate name in decl to passed list of names.
952 : 0 : void add_crate_name (std::vector<std::string> &names) const override
953 : : {
954 : 0 : names.push_back (referenced_crate);
955 : 0 : }
956 : :
957 : : // Invalid if crate name is empty, so base stripping on that.
958 : 0 : void mark_for_strip () override { referenced_crate = ""; }
959 : 84 : bool is_marked_for_strip () const override
960 : : {
961 : 84 : return referenced_crate.empty ();
962 : : }
963 : :
964 : 27 : Item::Kind get_item_kind () const override { return Item::Kind::ExternCrate; }
965 : :
966 : : protected:
967 : : /* Use covariance to implement clone function as returning this object
968 : : * rather than base */
969 : 0 : ExternCrate *clone_item_impl () const override
970 : : {
971 : 0 : return new ExternCrate (*this);
972 : : }
973 : : };
974 : :
975 : : // The path-ish thing referred to in a use declaration - abstract base class
976 : : class UseTree
977 : : {
978 : : location_t locus;
979 : : NodeId node_id;
980 : :
981 : : public:
982 : : enum Kind
983 : : {
984 : : Glob,
985 : : Rebind,
986 : : List,
987 : : };
988 : :
989 : 2 : virtual ~UseTree () {}
990 : :
991 : : // Overload assignment operator to clone
992 : : UseTree &operator= (UseTree const &other)
993 : : {
994 : : locus = other.locus;
995 : :
996 : : return *this;
997 : : }
998 : :
999 : 0 : UseTree (const UseTree &other) = default;
1000 : :
1001 : : // move constructors
1002 : : UseTree (UseTree &&other) = default;
1003 : : UseTree &operator= (UseTree &&other) = default;
1004 : :
1005 : : // Unique pointer custom clone function
1006 : 3 : std::unique_ptr<UseTree> clone_use_tree () const
1007 : : {
1008 : 3 : return std::unique_ptr<UseTree> (clone_use_tree_impl ());
1009 : : }
1010 : :
1011 : : virtual std::string as_string () const = 0;
1012 : : virtual Kind get_kind () const = 0;
1013 : :
1014 : 0 : location_t get_locus () const { return locus; }
1015 : : NodeId get_node_id () const { return node_id; }
1016 : :
1017 : : virtual void accept_vis (ASTVisitor &vis) = 0;
1018 : :
1019 : : protected:
1020 : : // Clone function implementation as pure virtual method
1021 : : virtual UseTree *clone_use_tree_impl () const = 0;
1022 : :
1023 : 519 : UseTree (location_t locus)
1024 : 519 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1025 : 519 : {}
1026 : : };
1027 : :
1028 : : // Use tree with a glob (wildcard) operator
1029 : 2 : class UseTreeGlob : public UseTree
1030 : : {
1031 : : public:
1032 : : enum PathType
1033 : : {
1034 : : NO_PATH,
1035 : : GLOBAL,
1036 : : PATH_PREFIXED
1037 : : };
1038 : :
1039 : : private:
1040 : : PathType glob_type;
1041 : : SimplePath path;
1042 : :
1043 : : public:
1044 : 14 : UseTreeGlob (PathType glob_type, SimplePath path, location_t locus)
1045 : 14 : : UseTree (locus), glob_type (glob_type), path (std::move (path))
1046 : : {
1047 : 14 : if (this->glob_type != PATH_PREFIXED)
1048 : : {
1049 : : // compiler implementation error if there is a path with a
1050 : : // non-path-prefixed use tree glob
1051 : 0 : rust_assert (!has_path ());
1052 : : }
1053 : : // TODO: do path-prefixed paths also have to have a path? If so, have an
1054 : : // assert for that too.
1055 : 14 : }
1056 : :
1057 : : /* Returns whether has path. Should be made redundant by PathType
1058 : : * PATH_PREFIXED. */
1059 : 25 : bool has_path () const { return !path.is_empty (); }
1060 : :
1061 : : std::string as_string () const override;
1062 : :
1063 : : void accept_vis (ASTVisitor &vis) override;
1064 : :
1065 : 0 : PathType get_glob_type () { return glob_type; }
1066 : :
1067 : 23 : Kind get_kind () const override { return Glob; }
1068 : :
1069 : 25 : SimplePath get_path () const
1070 : : {
1071 : 25 : rust_assert (has_path ());
1072 : 25 : return path;
1073 : : }
1074 : :
1075 : 81 : SimplePath &get_path () { return path; }
1076 : :
1077 : : /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory
1078 : : * methods? */
1079 : : protected:
1080 : : /* Use covariance to implement clone function as returning this object
1081 : : * rather than base */
1082 : 0 : UseTreeGlob *clone_use_tree_impl () const override
1083 : : {
1084 : 0 : return new UseTreeGlob (*this);
1085 : : }
1086 : : };
1087 : :
1088 : : // Use tree with a list of paths with a common prefix
1089 : : class UseTreeList : public UseTree
1090 : : {
1091 : : public:
1092 : : enum PathType
1093 : : {
1094 : : NO_PATH,
1095 : : GLOBAL,
1096 : : PATH_PREFIXED
1097 : : };
1098 : :
1099 : : private:
1100 : : PathType path_type;
1101 : : SimplePath path;
1102 : :
1103 : : std::vector<std::unique_ptr<UseTree>> trees;
1104 : :
1105 : : public:
1106 : 75 : UseTreeList (PathType path_type, SimplePath path,
1107 : : std::vector<std::unique_ptr<UseTree>> trees, location_t locus)
1108 : 150 : : UseTree (locus), path_type (path_type), path (std::move (path)),
1109 : 75 : trees (std::move (trees))
1110 : : {
1111 : 75 : if (this->path_type != PATH_PREFIXED)
1112 : : {
1113 : : // compiler implementation error if there is a path with a
1114 : : // non-path-prefixed use tree glob
1115 : 0 : rust_assert (!has_path ());
1116 : : }
1117 : : // TODO: do path-prefixed paths also have to have a path? If so, have an
1118 : : // assert for that too.
1119 : 75 : }
1120 : :
1121 : : // copy constructor with vector clone
1122 : 0 : UseTreeList (UseTreeList const &other)
1123 : 0 : : UseTree (other), path_type (other.path_type), path (other.path)
1124 : : {
1125 : 0 : trees.reserve (other.trees.size ());
1126 : 0 : for (const auto &e : other.trees)
1127 : 0 : trees.push_back (e->clone_use_tree ());
1128 : 0 : }
1129 : :
1130 : : // overloaded assignment operator with vector clone
1131 : : UseTreeList &operator= (UseTreeList const &other)
1132 : : {
1133 : : UseTree::operator= (other);
1134 : : path_type = other.path_type;
1135 : : path = other.path;
1136 : :
1137 : : trees.reserve (other.trees.size ());
1138 : : for (const auto &e : other.trees)
1139 : : trees.push_back (e->clone_use_tree ());
1140 : :
1141 : : return *this;
1142 : : }
1143 : :
1144 : : // move constructors
1145 : : UseTreeList (UseTreeList &&other) = default;
1146 : : UseTreeList &operator= (UseTreeList &&other) = default;
1147 : :
1148 : : // Returns whether has path. Should be made redundant by path_type.
1149 : 109 : bool has_path () const { return !path.is_empty (); }
1150 : :
1151 : : // Returns whether has inner tree elements.
1152 : 0 : bool has_trees () const { return !trees.empty (); }
1153 : :
1154 : : std::string as_string () const override;
1155 : :
1156 : 0 : PathType get_path_type () { return path_type; }
1157 : :
1158 : : void accept_vis (ASTVisitor &vis) override;
1159 : :
1160 : 108 : Kind get_kind () const override { return List; }
1161 : 109 : SimplePath get_path () const
1162 : : {
1163 : 109 : rust_assert (has_path ());
1164 : 109 : return path;
1165 : : }
1166 : :
1167 : 445 : SimplePath &get_path () { return path; }
1168 : :
1169 : 0 : std::vector<std::unique_ptr<UseTree>> &get_trees () { return trees; }
1170 : :
1171 : : const std::vector<std::unique_ptr<UseTree>> &get_trees () const
1172 : : {
1173 : 109 : return trees;
1174 : : }
1175 : :
1176 : : // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1177 : : // methods?
1178 : : protected:
1179 : : /* Use covariance to implement clone function as returning this object
1180 : : * rather than base */
1181 : 0 : UseTreeList *clone_use_tree_impl () const override
1182 : : {
1183 : 0 : return new UseTreeList (*this);
1184 : : }
1185 : : };
1186 : :
1187 : : // Use tree where it rebinds the module name as something else
1188 : : class UseTreeRebind : public UseTree
1189 : : {
1190 : : public:
1191 : : enum NewBindType
1192 : : {
1193 : : NONE,
1194 : : IDENTIFIER,
1195 : : WILDCARD
1196 : : };
1197 : :
1198 : : private:
1199 : : SimplePath path;
1200 : :
1201 : : NewBindType bind_type;
1202 : : Identifier identifier; // only if NewBindType is IDENTIFIER
1203 : :
1204 : : public:
1205 : 430 : UseTreeRebind (NewBindType bind_type, SimplePath path, location_t locus,
1206 : : Identifier identifier = std::string ())
1207 : 860 : : UseTree (locus), path (std::move (path)), bind_type (bind_type),
1208 : 430 : identifier (std::move (identifier))
1209 : 430 : {}
1210 : :
1211 : : // Returns whether has path (this should always be true).
1212 : 581 : bool has_path () const { return !path.is_empty (); }
1213 : :
1214 : : // Returns whether has identifier (or, rather, is allowed to).
1215 : 335 : bool has_identifier () const { return bind_type == IDENTIFIER; }
1216 : :
1217 : : std::string as_string () const override;
1218 : :
1219 : 232 : NewBindType get_new_bind_type () const { return bind_type; }
1220 : :
1221 : : void accept_vis (ASTVisitor &vis) override;
1222 : :
1223 : 578 : Kind get_kind () const override { return Rebind; }
1224 : :
1225 : 581 : const SimplePath &get_path () const
1226 : : {
1227 : 581 : rust_assert (has_path ());
1228 : 581 : return path;
1229 : : }
1230 : :
1231 : 1223 : SimplePath &get_path () { return path; }
1232 : :
1233 : 16 : const Identifier &get_identifier () const
1234 : : {
1235 : 16 : rust_assert (has_identifier ());
1236 : 16 : return identifier;
1237 : : }
1238 : :
1239 : : // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1240 : : // methods?
1241 : : protected:
1242 : : /* Use covariance to implement clone function as returning this object
1243 : : * rather than base */
1244 : 3 : virtual UseTreeRebind *clone_use_tree_impl () const override
1245 : : {
1246 : 3 : return new UseTreeRebind (*this);
1247 : : }
1248 : : };
1249 : :
1250 : : // Rust use declaration (i.e. for modules) AST node
1251 : : class UseDeclaration : public VisItem
1252 : : {
1253 : : std::unique_ptr<UseTree> use_tree;
1254 : : location_t locus;
1255 : :
1256 : : public:
1257 : : std::string as_string () const override;
1258 : :
1259 : 299 : UseDeclaration (std::unique_ptr<UseTree> use_tree, Visibility visibility,
1260 : : std::vector<Attribute> outer_attrs, location_t locus)
1261 : 299 : : VisItem (std::move (visibility), std::move (outer_attrs)),
1262 : 299 : use_tree (std::move (use_tree)), locus (locus)
1263 : 299 : {}
1264 : :
1265 : : // Copy constructor with clone
1266 : 3 : UseDeclaration (UseDeclaration const &other)
1267 : 3 : : VisItem (other), locus (other.locus)
1268 : : {
1269 : : // guard to prevent null dereference (only required if error state)
1270 : 3 : if (other.use_tree != nullptr)
1271 : 3 : use_tree = other.use_tree->clone_use_tree ();
1272 : 3 : }
1273 : :
1274 : : // Overloaded assignment operator to clone
1275 : : UseDeclaration &operator= (UseDeclaration const &other)
1276 : : {
1277 : : VisItem::operator= (other);
1278 : : // visibility = other.visibility->clone_visibility();
1279 : : // outer_attrs = other.outer_attrs;
1280 : : locus = other.locus;
1281 : :
1282 : : // guard to prevent null dereference (only required if error state)
1283 : : if (other.use_tree != nullptr)
1284 : : use_tree = other.use_tree->clone_use_tree ();
1285 : : else
1286 : : use_tree = nullptr;
1287 : :
1288 : : return *this;
1289 : : }
1290 : :
1291 : : // move constructors
1292 : : UseDeclaration (UseDeclaration &&other) = default;
1293 : : UseDeclaration &operator= (UseDeclaration &&other) = default;
1294 : :
1295 : 177 : location_t get_locus () const override final { return locus; }
1296 : :
1297 : 1948 : std::unique_ptr<UseTree> &get_tree () { return use_tree; }
1298 : :
1299 : 214 : const std::unique_ptr<UseTree> &get_tree () const { return use_tree; }
1300 : :
1301 : : void accept_vis (ASTVisitor &vis) override;
1302 : :
1303 : : // Invalid if use tree is null, so base stripping on that.
1304 : 0 : void mark_for_strip () override { use_tree = nullptr; }
1305 : 1039 : bool is_marked_for_strip () const override { return use_tree == nullptr; }
1306 : :
1307 : 503 : Item::Kind get_item_kind () const override
1308 : : {
1309 : 503 : return Item::Kind::UseDeclaration;
1310 : : }
1311 : :
1312 : : protected:
1313 : : /* Use covariance to implement clone function as returning this object
1314 : : * rather than base */
1315 : 3 : UseDeclaration *clone_item_impl () const override
1316 : : {
1317 : 3 : return new UseDeclaration (*this);
1318 : : }
1319 : : };
1320 : :
1321 : : class LetStmt;
1322 : :
1323 : : // Rust function declaration AST node
1324 : : class Function : public VisItem, public AssociatedItem, public ExternalItem
1325 : : {
1326 : : FunctionQualifiers qualifiers;
1327 : : Identifier function_name;
1328 : : std::vector<std::unique_ptr<GenericParam>> generic_params;
1329 : : std::vector<std::unique_ptr<Param>> function_params;
1330 : : std::unique_ptr<Type> return_type;
1331 : : WhereClause where_clause;
1332 : : tl::optional<std::unique_ptr<BlockExpr>> function_body;
1333 : : location_t locus;
1334 : : bool has_default;
1335 : : bool is_external_function;
1336 : :
1337 : : public:
1338 : : std::string as_string () const override;
1339 : :
1340 : : // Returns whether function has generic parameters.
1341 : 32121 : bool has_generics () const { return !generic_params.empty (); }
1342 : :
1343 : : // Returns whether function has regular parameters.
1344 : 0 : bool has_function_params () const { return !function_params.empty (); }
1345 : :
1346 : : // Returns whether function has return type - if not, it is void.
1347 : 258492 : bool has_return_type () const { return return_type != nullptr; }
1348 : :
1349 : : // Returns whether function has a where clause.
1350 : 199902 : bool has_where_clause () const { return !where_clause.is_empty (); }
1351 : :
1352 : 39169 : bool has_self_param () const
1353 : : {
1354 : 39169 : return function_params.size () > 0 && function_params[0]->is_self ();
1355 : : }
1356 : :
1357 : 302595 : bool has_body () const { return function_body.has_value (); }
1358 : :
1359 : 12538 : bool is_default () const { return has_default; }
1360 : :
1361 : : // Mega-constructor with all possible fields
1362 : 17133 : Function (Identifier function_name, FunctionQualifiers qualifiers,
1363 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1364 : : std::vector<std::unique_ptr<Param>> function_params,
1365 : : std::unique_ptr<Type> return_type, WhereClause where_clause,
1366 : : tl::optional<std::unique_ptr<BlockExpr>> function_body,
1367 : : Visibility vis, std::vector<Attribute> outer_attrs,
1368 : : location_t locus, bool has_default = false,
1369 : : bool is_external_function = false)
1370 : 17133 : : VisItem (std::move (vis), std::move (outer_attrs)),
1371 : 17133 : ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
1372 : 17133 : function_name (std::move (function_name)),
1373 : 17133 : generic_params (std::move (generic_params)),
1374 : 17133 : function_params (std::move (function_params)),
1375 : 17133 : return_type (std::move (return_type)),
1376 : 17133 : where_clause (std::move (where_clause)),
1377 : 17133 : function_body (std::move (function_body)), locus (locus),
1378 : 17133 : has_default (has_default), is_external_function (is_external_function)
1379 : 17133 : {}
1380 : :
1381 : : // TODO: add constructor with less fields
1382 : :
1383 : : // Copy constructor with clone
1384 : : Function (Function const &other);
1385 : :
1386 : : // Overloaded assignment operator to clone
1387 : : Function &operator= (Function const &other);
1388 : :
1389 : : // move constructors
1390 : : Function (Function &&other) = default;
1391 : : Function &operator= (Function &&other) = default;
1392 : :
1393 : 55310 : location_t get_locus () const override final { return locus; }
1394 : :
1395 : : void accept_vis (ASTVisitor &vis) override;
1396 : :
1397 : 2504 : bool is_variadic () const
1398 : : {
1399 : 2504 : return function_params.size () != 0
1400 : 2504 : && function_params.back ()->is_variadic ();
1401 : : }
1402 : :
1403 : 33938 : bool is_external () const { return is_external_function; }
1404 : :
1405 : : // Invalid if block is null, so base stripping on that.
1406 : 33 : void mark_for_strip () override { function_body = nullptr; }
1407 : 63570 : bool is_marked_for_strip () const override
1408 : : {
1409 : 63570 : return function_body == nullptr;
1410 : : }
1411 : :
1412 : 69437 : std::vector<std::unique_ptr<Param>> &get_function_params ()
1413 : : {
1414 : 275461 : return function_params;
1415 : : }
1416 : : const std::vector<std::unique_ptr<Param>> &get_function_params () const
1417 : : {
1418 : : return function_params;
1419 : : }
1420 : :
1421 : 2966 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1422 : : {
1423 : 189087 : return generic_params;
1424 : : }
1425 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1426 : : {
1427 : : return generic_params;
1428 : : }
1429 : :
1430 : : // TODO: is this better? Or is a "vis_block" better?
1431 : 233387 : tl::optional<std::unique_ptr<BlockExpr>> &get_definition ()
1432 : : {
1433 : 233387 : return function_body;
1434 : : }
1435 : :
1436 : : const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
1437 : :
1438 : 191372 : FunctionQualifiers &get_qualifiers () { return qualifiers; }
1439 : :
1440 : 55105 : Identifier get_function_name () const { return function_name; }
1441 : :
1442 : : // TODO: is this better? Or is a "vis_block" better?
1443 : 285 : WhereClause &get_where_clause () { return where_clause; }
1444 : :
1445 : : // TODO: is this better? Or is a "vis_block" better?
1446 : 159428 : Type &get_return_type ()
1447 : : {
1448 : 159428 : rust_assert (has_return_type ());
1449 : 159428 : return *return_type;
1450 : : }
1451 : :
1452 : 19378 : std::unique_ptr<Type> &get_return_type_ptr ()
1453 : : {
1454 : 19378 : rust_assert (has_return_type ());
1455 : 19378 : return return_type;
1456 : : }
1457 : :
1458 : 10043 : Param &get_self_param ()
1459 : : {
1460 : 10043 : rust_assert (has_self_param ());
1461 : 10043 : return *function_params[0];
1462 : : }
1463 : : const Param &get_self_param () const
1464 : : {
1465 : : rust_assert (has_self_param ());
1466 : : return *function_params[0];
1467 : : }
1468 : :
1469 : : // ExternalItem::node_id is same as Stmt::node_id
1470 : 139227 : NodeId get_node_id () const override { return Stmt::node_id; }
1471 : :
1472 : 8132 : Item::Kind get_item_kind () const override { return Item::Kind::Function; }
1473 : :
1474 : : protected:
1475 : : /* Use covariance to implement clone function as returning this object
1476 : : * rather than base */
1477 : 37 : Function *clone_item_impl () const override { return new Function (*this); }
1478 : :
1479 : : /* Use covariance to implement clone function as returning this object
1480 : : * rather than base */
1481 : 17269 : Function *clone_associated_item_impl () const override
1482 : : {
1483 : 17269 : return new Function (*this);
1484 : : }
1485 : :
1486 : : /* Use covariance to implement clone function as returning this object
1487 : : * rather than base */
1488 : 32 : Function *clone_external_item_impl () const override
1489 : : {
1490 : 32 : return new Function (*this);
1491 : : }
1492 : : };
1493 : :
1494 : : // Rust type alias (i.e. typedef) AST node
1495 : : class TypeAlias : public VisItem, public AssociatedItem
1496 : : {
1497 : : Identifier new_type_name;
1498 : :
1499 : : // bool has_generics;
1500 : : // Generics generic_params;
1501 : : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1502 : :
1503 : : // bool has_where_clause;
1504 : : WhereClause where_clause;
1505 : :
1506 : : std::unique_ptr<Type> existing_type;
1507 : :
1508 : : location_t locus;
1509 : :
1510 : : public:
1511 : : std::string as_string () const override;
1512 : :
1513 : : // Returns whether type alias has generic parameters.
1514 : 2344 : bool has_generics () const { return !generic_params.empty (); }
1515 : :
1516 : : // Returns whether type alias has a where clause.
1517 : 17649 : bool has_where_clause () const { return !where_clause.is_empty (); }
1518 : :
1519 : : // Mega-constructor with all possible fields
1520 : 1401 : TypeAlias (Identifier new_type_name,
1521 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1522 : : WhereClause where_clause, std::unique_ptr<Type> existing_type,
1523 : : Visibility vis, std::vector<Attribute> outer_attrs,
1524 : : location_t locus)
1525 : 1401 : : VisItem (std::move (vis), std::move (outer_attrs)),
1526 : 1401 : new_type_name (std::move (new_type_name)),
1527 : 1401 : generic_params (std::move (generic_params)),
1528 : 1401 : where_clause (std::move (where_clause)),
1529 : 1401 : existing_type (std::move (existing_type)), locus (locus)
1530 : 1401 : {}
1531 : :
1532 : : // Copy constructor
1533 : 3022 : TypeAlias (TypeAlias const &other)
1534 : 3022 : : VisItem (other), new_type_name (other.new_type_name),
1535 : 3022 : where_clause (other.where_clause), locus (other.locus)
1536 : : {
1537 : : // guard to prevent null dereference (only required if error state)
1538 : 3022 : if (other.existing_type != nullptr)
1539 : 3022 : existing_type = other.existing_type->clone_type ();
1540 : :
1541 : 3022 : generic_params.reserve (other.generic_params.size ());
1542 : 3022 : for (const auto &e : other.generic_params)
1543 : 0 : generic_params.push_back (e->clone_generic_param ());
1544 : 3022 : }
1545 : :
1546 : : // Overloaded assignment operator to clone
1547 : : TypeAlias &operator= (TypeAlias const &other)
1548 : : {
1549 : : VisItem::operator= (other);
1550 : : new_type_name = other.new_type_name;
1551 : : where_clause = other.where_clause;
1552 : : // visibility = other.visibility->clone_visibility();
1553 : : // outer_attrs = other.outer_attrs;
1554 : : locus = other.locus;
1555 : :
1556 : : // guard to prevent null dereference (only required if error state)
1557 : : if (other.existing_type != nullptr)
1558 : : existing_type = other.existing_type->clone_type ();
1559 : : else
1560 : : existing_type = nullptr;
1561 : :
1562 : : generic_params.reserve (other.generic_params.size ());
1563 : : for (const auto &e : other.generic_params)
1564 : : generic_params.push_back (e->clone_generic_param ());
1565 : :
1566 : : return *this;
1567 : : }
1568 : :
1569 : : // move constructors
1570 : : TypeAlias (TypeAlias &&other) = default;
1571 : : TypeAlias &operator= (TypeAlias &&other) = default;
1572 : :
1573 : 3024 : location_t get_locus () const override final { return locus; }
1574 : :
1575 : : void accept_vis (ASTVisitor &vis) override;
1576 : :
1577 : : // Invalid if existing type is null, so base stripping on that.
1578 : 0 : void mark_for_strip () override { existing_type = nullptr; }
1579 : 5713 : bool is_marked_for_strip () const override
1580 : : {
1581 : 5713 : return existing_type == nullptr;
1582 : : }
1583 : :
1584 : 18 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1585 : : {
1586 : 16583 : return generic_params;
1587 : : }
1588 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1589 : : {
1590 : : return generic_params;
1591 : : }
1592 : :
1593 : : // TODO: is this better? Or is a "vis_block" better?
1594 : 0 : WhereClause &get_where_clause () { return where_clause; }
1595 : :
1596 : : // TODO: is this better? Or is a "vis_block" better?
1597 : 23535 : Type &get_type_aliased ()
1598 : : {
1599 : 23535 : rust_assert (existing_type != nullptr);
1600 : 23535 : return *existing_type;
1601 : : }
1602 : :
1603 : 5540 : Identifier get_new_type_name () const { return new_type_name; }
1604 : :
1605 : 50 : Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; }
1606 : :
1607 : : protected:
1608 : : /* Use covariance to implement clone function as returning this object
1609 : : * rather than base */
1610 : 0 : TypeAlias *clone_item_impl () const override { return new TypeAlias (*this); }
1611 : :
1612 : : /* Use covariance to implement clone function as returning this object
1613 : : * rather than base */
1614 : 3022 : TypeAlias *clone_associated_item_impl () const override
1615 : : {
1616 : 3022 : return new TypeAlias (*this);
1617 : : }
1618 : : };
1619 : :
1620 : : // Rust base struct declaration AST node - abstract base class
1621 : : class Struct : public VisItem
1622 : : {
1623 : : protected:
1624 : : // protected to enable access by derived classes - allows better as_string
1625 : : Identifier struct_name;
1626 : :
1627 : : // bool has_generics;
1628 : : // Generics generic_params;
1629 : : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1630 : :
1631 : : // bool has_where_clause;
1632 : : WhereClause where_clause;
1633 : :
1634 : : private:
1635 : : location_t locus;
1636 : :
1637 : : public:
1638 : : // Returns whether struct has generic parameters.
1639 : 4293 : bool has_generics () const { return !generic_params.empty (); }
1640 : :
1641 : : // Returns whether struct has a where clause.
1642 : 25263 : bool has_where_clause () const { return !where_clause.is_empty (); }
1643 : :
1644 : 7269 : location_t get_locus () const override final { return locus; }
1645 : :
1646 : : // Invalid if name is empty, so base stripping on that.
1647 : 8 : void mark_for_strip () override { struct_name = {""}; }
1648 : 5430 : bool is_marked_for_strip () const override { return struct_name.empty (); }
1649 : :
1650 : 3315 : Identifier get_struct_name () const { return struct_name; }
1651 : :
1652 : 1380 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1653 : : {
1654 : 25531 : return generic_params;
1655 : : }
1656 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1657 : : {
1658 : : return generic_params;
1659 : : }
1660 : :
1661 : : // TODO: is this better? Or is a "vis_block" better?
1662 : 42 : WhereClause &get_where_clause () { return where_clause; }
1663 : :
1664 : 6261 : Identifier get_identifier () const { return struct_name; }
1665 : :
1666 : 1890 : Item::Kind get_item_kind () const override { return Item::Kind::Struct; }
1667 : :
1668 : : protected:
1669 : 2696 : Struct (Identifier struct_name,
1670 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1671 : : WhereClause where_clause, Visibility vis, location_t locus,
1672 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1673 : 2696 : : VisItem (std::move (vis), std::move (outer_attrs)),
1674 : 5392 : struct_name (std::move (struct_name)),
1675 : 2696 : generic_params (std::move (generic_params)),
1676 : 2696 : where_clause (std::move (where_clause)), locus (locus)
1677 : 2696 : {}
1678 : :
1679 : : // Copy constructor with vector clone
1680 : 457 : Struct (Struct const &other)
1681 : 914 : : VisItem (other), struct_name (other.struct_name),
1682 : 457 : where_clause (other.where_clause), locus (other.locus)
1683 : : {
1684 : 457 : generic_params.reserve (other.generic_params.size ());
1685 : 460 : for (const auto &e : other.generic_params)
1686 : 3 : generic_params.push_back (e->clone_generic_param ());
1687 : 457 : }
1688 : :
1689 : : // Overloaded assignment operator with vector clone
1690 : : Struct &operator= (Struct const &other)
1691 : : {
1692 : : VisItem::operator= (other);
1693 : : struct_name = other.struct_name;
1694 : : where_clause = other.where_clause;
1695 : : locus = other.locus;
1696 : :
1697 : : generic_params.reserve (other.generic_params.size ());
1698 : : for (const auto &e : other.generic_params)
1699 : : generic_params.push_back (e->clone_generic_param ());
1700 : :
1701 : : return *this;
1702 : : }
1703 : :
1704 : : // move constructors
1705 : : Struct (Struct &&other) = default;
1706 : : Struct &operator= (Struct &&other) = default;
1707 : : };
1708 : :
1709 : : // A single field in a struct
1710 : : class StructField
1711 : : {
1712 : : // bool has_outer_attributes;
1713 : : std::vector<Attribute> outer_attrs;
1714 : :
1715 : : // bool has_visibility;
1716 : : Visibility visibility;
1717 : :
1718 : : Identifier field_name;
1719 : : std::unique_ptr<Type> field_type;
1720 : :
1721 : : NodeId node_id;
1722 : :
1723 : : location_t locus;
1724 : :
1725 : : public:
1726 : : // Returns whether struct field has any outer attributes.
1727 : : bool has_outer_attributes () const { return !outer_attrs.empty (); }
1728 : :
1729 : : // Returns whether struct field has a non-private (non-default) visibility.
1730 : 0 : bool has_visibility () const { return !visibility.is_error (); }
1731 : :
1732 : 2300 : StructField (Identifier field_name, std::unique_ptr<Type> field_type,
1733 : : Visibility vis, location_t locus,
1734 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1735 : 2300 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1736 : 2300 : field_name (std::move (field_name)), field_type (std::move (field_type)),
1737 : 2300 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
1738 : 2300 : {}
1739 : :
1740 : : // Copy constructor
1741 : 14 : StructField (StructField const &other)
1742 : 14 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
1743 : 14 : field_name (other.field_name), node_id (other.node_id),
1744 : 14 : locus (other.locus)
1745 : : {
1746 : : // guard to prevent null dereference
1747 : 14 : if (other.field_type != nullptr)
1748 : 14 : field_type = other.field_type->clone_type ();
1749 : 14 : }
1750 : :
1751 : 3686 : ~StructField () = default;
1752 : :
1753 : : // Overloaded assignment operator to clone
1754 : : StructField &operator= (StructField const &other)
1755 : : {
1756 : : field_name = other.field_name;
1757 : : visibility = other.visibility;
1758 : : outer_attrs = other.outer_attrs;
1759 : : node_id = other.node_id;
1760 : :
1761 : : // guard to prevent null dereference
1762 : : if (other.field_type != nullptr)
1763 : : field_type = other.field_type->clone_type ();
1764 : : else
1765 : : field_type = nullptr;
1766 : :
1767 : : return *this;
1768 : : }
1769 : :
1770 : : // move constructors
1771 : 3603 : StructField (StructField &&other) = default;
1772 : 0 : StructField &operator= (StructField &&other) = default;
1773 : :
1774 : : // Returns whether struct field is in an error state.
1775 : 2294 : bool is_error () const
1776 : : {
1777 : 2294 : return field_name.empty () && field_type == nullptr;
1778 : : // this should really be an or since neither are allowed
1779 : : }
1780 : :
1781 : : // Creates an error state struct field.
1782 : 49 : static StructField create_error ()
1783 : : {
1784 : 98 : return StructField (std::string (""), nullptr, Visibility::create_error (),
1785 : 147 : UNDEF_LOCATION);
1786 : : }
1787 : :
1788 : : std::string as_string () const;
1789 : :
1790 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1791 : 22117 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1792 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1793 : :
1794 : 2299 : Identifier get_field_name () const { return field_name; }
1795 : :
1796 : 2199 : location_t get_locus () const { return locus; }
1797 : :
1798 : : // TODO: is this better? Or is a "vis_block" better?
1799 : 27882 : Type &get_field_type ()
1800 : : {
1801 : 27882 : rust_assert (field_type != nullptr);
1802 : 27882 : return *field_type;
1803 : : }
1804 : :
1805 : 2740 : std::unique_ptr<Type> &get_field_type_ptr ()
1806 : : {
1807 : 2740 : rust_assert (field_type != nullptr);
1808 : 2740 : return field_type;
1809 : : }
1810 : :
1811 : 20458 : Visibility &get_visibility () { return visibility; }
1812 : : const Visibility &get_visibility () const { return visibility; }
1813 : :
1814 : 2183 : NodeId get_node_id () const { return node_id; }
1815 : : };
1816 : :
1817 : : // Rust struct declaration with true struct type AST node
1818 : : class StructStruct : public Struct
1819 : : {
1820 : : std::vector<StructField> fields;
1821 : : bool is_unit;
1822 : :
1823 : : public:
1824 : : std::string as_string () const override;
1825 : :
1826 : : // Mega-constructor with all possible fields
1827 : 926 : StructStruct (std::vector<StructField> fields, Identifier struct_name,
1828 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1829 : : WhereClause where_clause, bool is_unit, Visibility vis,
1830 : : std::vector<Attribute> outer_attrs, location_t locus)
1831 : 926 : : Struct (std::move (struct_name), std::move (generic_params),
1832 : : std::move (where_clause), std::move (vis), locus,
1833 : : std::move (outer_attrs)),
1834 : 926 : fields (std::move (fields)), is_unit (is_unit)
1835 : 926 : {}
1836 : :
1837 : : // Unit struct constructor
1838 : 729 : StructStruct (Identifier struct_name,
1839 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1840 : : WhereClause where_clause, Visibility vis,
1841 : : std::vector<Attribute> outer_attrs, location_t locus)
1842 : 729 : : Struct (std::move (struct_name), std::move (generic_params),
1843 : : std::move (where_clause), std::move (vis), locus,
1844 : : std::move (outer_attrs)),
1845 : 729 : is_unit (true)
1846 : 729 : {}
1847 : :
1848 : : /* Returns whether the struct is a unit struct - struct defined without
1849 : : * fields. This is important because it also means an implicit constant of its
1850 : : * type is defined. */
1851 : 3234 : bool is_unit_struct () const { return is_unit; }
1852 : :
1853 : : void accept_vis (ASTVisitor &vis) override;
1854 : :
1855 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1856 : 18424 : std::vector<StructField> &get_fields () { return fields; }
1857 : : const std::vector<StructField> &get_fields () const { return fields; }
1858 : :
1859 : : protected:
1860 : : /* Use covariance to implement clone function as returning this object
1861 : : * rather than base */
1862 : 352 : StructStruct *clone_item_impl () const override
1863 : : {
1864 : 352 : return new StructStruct (*this);
1865 : : }
1866 : : };
1867 : :
1868 : : // A single field in a tuple
1869 : : class TupleField
1870 : : {
1871 : : // bool has_outer_attributes;
1872 : : std::vector<Attribute> outer_attrs;
1873 : :
1874 : : // bool has_visibility;
1875 : : Visibility visibility;
1876 : :
1877 : : std::unique_ptr<Type> field_type;
1878 : :
1879 : : NodeId node_id;
1880 : :
1881 : : location_t locus;
1882 : :
1883 : : public:
1884 : : // Returns whether tuple field has outer attributes.
1885 : : bool has_outer_attributes () const { return !outer_attrs.empty (); }
1886 : :
1887 : : /* Returns whether tuple field has a non-default visibility (i.e. a public
1888 : : * one) */
1889 : 0 : bool has_visibility () const { return !visibility.is_error (); }
1890 : :
1891 : : // Complete constructor
1892 : 2207 : TupleField (std::unique_ptr<Type> field_type, Visibility vis,
1893 : : location_t locus,
1894 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1895 : 2207 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1896 : 2207 : field_type (std::move (field_type)),
1897 : 2207 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
1898 : 2207 : {}
1899 : :
1900 : : // Copy constructor with clone
1901 : 106 : TupleField (TupleField const &other)
1902 : 106 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
1903 : 106 : node_id (other.node_id), locus (other.locus)
1904 : : {
1905 : : // guard to prevent null dereference (only required if error)
1906 : 106 : if (other.field_type != nullptr)
1907 : 106 : field_type = other.field_type->clone_type ();
1908 : 106 : }
1909 : :
1910 : 3383 : ~TupleField () = default;
1911 : :
1912 : : // Overloaded assignment operator to clone
1913 : : TupleField &operator= (TupleField const &other)
1914 : : {
1915 : : visibility = other.visibility;
1916 : : outer_attrs = other.outer_attrs;
1917 : : node_id = other.node_id;
1918 : : locus = other.locus;
1919 : :
1920 : : // guard to prevent null dereference (only required if error)
1921 : : if (other.field_type != nullptr)
1922 : : field_type = other.field_type->clone_type ();
1923 : : else
1924 : : field_type = nullptr;
1925 : :
1926 : : return *this;
1927 : : }
1928 : :
1929 : : // move constructors
1930 : 3131 : TupleField (TupleField &&other) = default;
1931 : 0 : TupleField &operator= (TupleField &&other) = default;
1932 : :
1933 : : // Returns whether tuple field is in an error state.
1934 : 2207 : bool is_error () const { return field_type == nullptr; }
1935 : :
1936 : : // Creates an error state tuple field.
1937 : 0 : static TupleField create_error ()
1938 : : {
1939 : 0 : return TupleField (nullptr, Visibility::create_error (), UNDEF_LOCATION);
1940 : : }
1941 : :
1942 : : std::string as_string () const;
1943 : :
1944 : 2089 : NodeId get_node_id () const { return node_id; }
1945 : :
1946 : 21810 : Visibility &get_visibility () { return visibility; }
1947 : : const Visibility &get_visibility () const { return visibility; }
1948 : :
1949 : 2089 : location_t get_locus () const { return locus; }
1950 : :
1951 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1952 : 25720 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1953 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1954 : :
1955 : : // TODO: is this better? Or is a "vis_block" better?
1956 : 30573 : Type &get_field_type ()
1957 : : {
1958 : 30573 : rust_assert (field_type != nullptr);
1959 : 30573 : return *field_type;
1960 : : }
1961 : :
1962 : 3167 : std::unique_ptr<Type> &get_field_type_ptr ()
1963 : : {
1964 : 3167 : rust_assert (field_type != nullptr);
1965 : 3167 : return field_type;
1966 : : }
1967 : : };
1968 : :
1969 : : // Rust tuple declared using struct keyword AST node
1970 : : class TupleStruct : public Struct
1971 : : {
1972 : : std::vector<TupleField> fields;
1973 : :
1974 : : public:
1975 : : std::string as_string () const override;
1976 : :
1977 : : // Mega-constructor with all possible fields
1978 : 1041 : TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
1979 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
1980 : : WhereClause where_clause, Visibility vis,
1981 : : std::vector<Attribute> outer_attrs, location_t locus)
1982 : 1041 : : Struct (std::move (struct_name), std::move (generic_params),
1983 : : std::move (where_clause), std::move (vis), locus,
1984 : : std::move (outer_attrs)),
1985 : 1041 : fields (std::move (fields))
1986 : 1041 : {}
1987 : :
1988 : : void accept_vis (ASTVisitor &vis) override;
1989 : :
1990 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1991 : 13210 : std::vector<TupleField> &get_fields () { return fields; }
1992 : : const std::vector<TupleField> &get_fields () const { return fields; }
1993 : :
1994 : : protected:
1995 : : /* Use covariance to implement clone function as returning this object
1996 : : * rather than base */
1997 : 105 : TupleStruct *clone_item_impl () const override
1998 : : {
1999 : 105 : return new TupleStruct (*this);
2000 : : }
2001 : : };
2002 : :
2003 : : /* An item used in an "enum" tagged union - not abstract: base represents a
2004 : : * name-only enum. EnumItems (variants) syntactically allow a Visibility
2005 : : * annotation. */
2006 : : class EnumItem : public VisItem
2007 : : {
2008 : : Identifier variant_name;
2009 : :
2010 : : location_t locus;
2011 : :
2012 : : public:
2013 : : enum class Kind
2014 : : {
2015 : : Identifier,
2016 : : Tuple,
2017 : : Struct,
2018 : :
2019 : : // FIXME: In the future, we'll need to remove this possibility as well as
2020 : : // remove the EnumItemDiscriminant class. The feature for arbitrary
2021 : : // discriminants on all kinds of variants has been stabilized, and a
2022 : : // "discriminant" is no longer an enum item variant - it's simply an
2023 : : // optional part of all variants.
2024 : : //
2025 : : // Per the reference:
2026 : : //
2027 : : // EnumItem :
2028 : : // OuterAttribute* Visibility?
2029 : : // IDENTIFIER ( EnumItemTuple | EnumItemStruct )? EnumItemDiscriminant?
2030 : : //
2031 : : // EnumItemTuple :
2032 : : // ( TupleFields? )
2033 : : //
2034 : : // EnumItemStruct :
2035 : : // { StructFields? }
2036 : : //
2037 : : // EnumItemDiscriminant :
2038 : : // = Expression
2039 : : //
2040 : : // So we instead need to remove the class, and add an optional expression to
2041 : : // the base EnumItem class
2042 : : //
2043 : : // gccrs#3340
2044 : :
2045 : : Discriminant,
2046 : : };
2047 : :
2048 : 11 : virtual ~EnumItem () {}
2049 : :
2050 : 962 : EnumItem (Identifier variant_name, Visibility vis,
2051 : : std::vector<Attribute> outer_attrs, location_t locus)
2052 : 962 : : VisItem (std::move (vis), std::move (outer_attrs)),
2053 : 962 : variant_name (std::move (variant_name)), locus (locus)
2054 : 962 : {}
2055 : :
2056 : 13 : virtual Kind get_enum_item_kind () const { return Kind::Identifier; }
2057 : :
2058 : : // Unique pointer custom clone function
2059 : 2 : std::unique_ptr<EnumItem> clone_enum_item () const
2060 : : {
2061 : 2 : return std::unique_ptr<EnumItem> (clone_item_impl ());
2062 : : }
2063 : :
2064 : : virtual std::string as_string () const override;
2065 : :
2066 : : // not pure virtual as not abstract
2067 : : virtual void accept_vis (ASTVisitor &vis) override;
2068 : :
2069 : 2265 : location_t get_locus () const override { return locus; }
2070 : :
2071 : 2968 : Identifier get_identifier () const { return variant_name; }
2072 : :
2073 : : // Based on idea that name is never empty.
2074 : 0 : void mark_for_strip () override { variant_name = {""}; }
2075 : 3274 : bool is_marked_for_strip () const override { return variant_name.empty (); }
2076 : :
2077 : 0 : Item::Kind get_item_kind () const override { return Item::Kind::EnumItem; }
2078 : :
2079 : : protected:
2080 : 1 : EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
2081 : : };
2082 : :
2083 : : // A tuple item used in an "enum" tagged union
2084 : : class EnumItemTuple : public EnumItem
2085 : : {
2086 : : // bool has_tuple_fields;
2087 : : std::vector<TupleField> tuple_fields;
2088 : :
2089 : : public:
2090 : : // Returns whether tuple enum item has tuple fields.
2091 : 0 : bool has_tuple_fields () const { return !tuple_fields.empty (); }
2092 : :
2093 : 410 : EnumItemTuple (Identifier variant_name, Visibility vis,
2094 : : std::vector<TupleField> tuple_fields,
2095 : : std::vector<Attribute> outer_attrs, location_t locus)
2096 : 410 : : EnumItem (std::move (variant_name), std::move (vis),
2097 : : std::move (outer_attrs), locus),
2098 : 410 : tuple_fields (std::move (tuple_fields))
2099 : 410 : {}
2100 : :
2101 : 13 : EnumItem::Kind get_enum_item_kind () const override
2102 : : {
2103 : 13 : return EnumItem::Kind::Tuple;
2104 : : }
2105 : :
2106 : : std::string as_string () const override;
2107 : :
2108 : : void accept_vis (ASTVisitor &vis) override;
2109 : :
2110 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2111 : 5601 : std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
2112 : : const std::vector<TupleField> &get_tuple_fields () const
2113 : : {
2114 : : return tuple_fields;
2115 : : }
2116 : :
2117 : : protected:
2118 : : // Clone function implementation as (not pure) virtual method
2119 : 1 : EnumItemTuple *clone_item_impl () const override
2120 : : {
2121 : 1 : return new EnumItemTuple (*this);
2122 : : }
2123 : : };
2124 : :
2125 : : // A struct item used in an "enum" tagged union
2126 : : class EnumItemStruct : public EnumItem
2127 : : {
2128 : : // bool has_struct_fields;
2129 : : std::vector<StructField> struct_fields;
2130 : :
2131 : : public:
2132 : : // Returns whether struct enum item has struct fields.
2133 : 0 : bool has_struct_fields () const { return !struct_fields.empty (); }
2134 : :
2135 : 86 : EnumItemStruct (Identifier variant_name, Visibility vis,
2136 : : std::vector<StructField> struct_fields,
2137 : : std::vector<Attribute> outer_attrs, location_t locus)
2138 : 86 : : EnumItem (std::move (variant_name), std::move (vis),
2139 : : std::move (outer_attrs), locus),
2140 : 86 : struct_fields (std::move (struct_fields))
2141 : 86 : {}
2142 : :
2143 : 13 : EnumItem::Kind get_enum_item_kind () const override
2144 : : {
2145 : 13 : return EnumItem::Kind::Struct;
2146 : : }
2147 : :
2148 : : std::string as_string () const override;
2149 : :
2150 : : void accept_vis (ASTVisitor &vis) override;
2151 : :
2152 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2153 : 1054 : std::vector<StructField> &get_struct_fields () { return struct_fields; }
2154 : : const std::vector<StructField> &get_struct_fields () const
2155 : : {
2156 : 13 : return struct_fields;
2157 : : }
2158 : :
2159 : : protected:
2160 : : // Clone function implementation as (not pure) virtual method
2161 : 0 : EnumItemStruct *clone_item_impl () const override
2162 : : {
2163 : 0 : return new EnumItemStruct (*this);
2164 : : }
2165 : : };
2166 : :
2167 : : // A discriminant (numbered enum) item used in an "enum" tagged union
2168 : : class EnumItemDiscriminant : public EnumItem
2169 : : {
2170 : : std::unique_ptr<Expr> expression;
2171 : :
2172 : : public:
2173 : 38 : EnumItemDiscriminant (Identifier variant_name, Visibility vis,
2174 : : std::unique_ptr<Expr> expr,
2175 : : std::vector<Attribute> outer_attrs, location_t locus)
2176 : 38 : : EnumItem (std::move (variant_name), std::move (vis),
2177 : : std::move (outer_attrs), locus),
2178 : 38 : expression (std::move (expr))
2179 : 38 : {}
2180 : :
2181 : : // Copy constructor with clone
2182 : 0 : EnumItemDiscriminant (EnumItemDiscriminant const &other)
2183 : 0 : : EnumItem (other), expression (other.expression->clone_expr ())
2184 : 0 : {}
2185 : :
2186 : : // Overloaded assignment operator to clone
2187 : : EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other)
2188 : : {
2189 : : EnumItem::operator= (other);
2190 : : expression = other.expression->clone_expr ();
2191 : : // variant_name = other.variant_name;
2192 : : // outer_attrs = other.outer_attrs;
2193 : :
2194 : : return *this;
2195 : : }
2196 : :
2197 : : // move constructors
2198 : : EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
2199 : : EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
2200 : :
2201 : 0 : EnumItem::Kind get_enum_item_kind () const override
2202 : : {
2203 : 0 : return EnumItem::Kind::Discriminant;
2204 : : }
2205 : :
2206 : : std::string as_string () const override;
2207 : :
2208 : : void accept_vis (ASTVisitor &vis) override;
2209 : :
2210 : : bool has_expr () { return expression != nullptr; }
2211 : :
2212 : : // TODO: is this better? Or is a "vis_block" better?
2213 : 567 : Expr &get_expr ()
2214 : : {
2215 : 567 : rust_assert (expression != nullptr);
2216 : 567 : return *expression;
2217 : : }
2218 : :
2219 : 49 : std::unique_ptr<Expr> &get_expr_ptr ()
2220 : : {
2221 : 49 : rust_assert (expression != nullptr);
2222 : 49 : return expression;
2223 : : }
2224 : :
2225 : : protected:
2226 : : // Clone function implementation as (not pure) virtual method
2227 : 0 : EnumItemDiscriminant *clone_item_impl () const override
2228 : : {
2229 : 0 : return new EnumItemDiscriminant (*this);
2230 : : }
2231 : : };
2232 : :
2233 : : // AST node for Rust "enum" - tagged union
2234 : : class Enum : public VisItem
2235 : : {
2236 : : Identifier enum_name;
2237 : :
2238 : : // bool has_generics;
2239 : : // Generics generic_params;
2240 : : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2241 : :
2242 : : // bool has_where_clause;
2243 : : WhereClause where_clause;
2244 : :
2245 : : std::vector<std::unique_ptr<EnumItem>> items;
2246 : :
2247 : : location_t locus;
2248 : :
2249 : : public:
2250 : : std::string as_string () const override;
2251 : :
2252 : : // Returns whether "enum" has generic parameters.
2253 : 712 : bool has_generics () const { return !generic_params.empty (); }
2254 : :
2255 : : // Returns whether "enum" has a where clause.
2256 : 4818 : bool has_where_clause () const { return !where_clause.is_empty (); }
2257 : :
2258 : : /* Returns whether enum is a "zero-variant" (no possible variant) enum,
2259 : : * which cannot be instantiated. */
2260 : : bool is_zero_variant () const { return items.empty (); }
2261 : :
2262 : : // Mega-constructor
2263 : 434 : Enum (Identifier enum_name, Visibility vis,
2264 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
2265 : : WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
2266 : : std::vector<Attribute> outer_attrs, location_t locus)
2267 : 434 : : VisItem (std::move (vis), std::move (outer_attrs)),
2268 : 868 : enum_name (std::move (enum_name)),
2269 : 434 : generic_params (std::move (generic_params)),
2270 : 434 : where_clause (std::move (where_clause)), items (std::move (items)),
2271 : 434 : locus (locus)
2272 : 434 : {}
2273 : :
2274 : : // TODO: constructor with less arguments
2275 : :
2276 : : // Copy constructor with vector clone
2277 : 1 : Enum (Enum const &other)
2278 : 2 : : VisItem (other), enum_name (other.enum_name),
2279 : 1 : where_clause (other.where_clause), locus (other.locus)
2280 : : {
2281 : 1 : generic_params.reserve (other.generic_params.size ());
2282 : 2 : for (const auto &e : other.generic_params)
2283 : 1 : generic_params.push_back (e->clone_generic_param ());
2284 : :
2285 : 1 : items.reserve (other.items.size ());
2286 : 3 : for (const auto &e : other.items)
2287 : 2 : items.push_back (e->clone_enum_item ());
2288 : 1 : }
2289 : :
2290 : : // Overloaded assignment operator with vector clone
2291 : : Enum &operator= (Enum const &other)
2292 : : {
2293 : : VisItem::operator= (other);
2294 : : enum_name = other.enum_name;
2295 : : where_clause = other.where_clause;
2296 : : locus = other.locus;
2297 : :
2298 : : generic_params.reserve (other.generic_params.size ());
2299 : : for (const auto &e : other.generic_params)
2300 : : generic_params.push_back (e->clone_generic_param ());
2301 : :
2302 : : items.reserve (other.items.size ());
2303 : : for (const auto &e : other.items)
2304 : : items.push_back (e->clone_enum_item ());
2305 : :
2306 : : return *this;
2307 : : }
2308 : :
2309 : : // Move constructors
2310 : : Enum (Enum &&other) = default;
2311 : : Enum &operator= (Enum &&other) = default;
2312 : :
2313 : 1196 : location_t get_locus () const override final { return locus; }
2314 : :
2315 : : void accept_vis (ASTVisitor &vis) override;
2316 : :
2317 : 1946 : Identifier get_identifier () const { return enum_name; }
2318 : :
2319 : : // Invalid if name is empty, so base stripping on that.
2320 : 0 : void mark_for_strip () override { enum_name = {""}; }
2321 : 1061 : bool is_marked_for_strip () const override { return enum_name.empty (); }
2322 : :
2323 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2324 : 6324 : std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
2325 : : const std::vector<std::unique_ptr<EnumItem>> &get_variants () const
2326 : : {
2327 : : return items;
2328 : : }
2329 : :
2330 : 318 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2331 : : {
2332 : 4833 : return generic_params;
2333 : : }
2334 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2335 : : {
2336 : : return generic_params;
2337 : : }
2338 : :
2339 : : // TODO: is this better? Or is a "vis_block" better?
2340 : 0 : WhereClause &get_where_clause () { return where_clause; }
2341 : :
2342 : 425 : Item::Kind get_item_kind () const override { return Item::Kind::Enum; }
2343 : :
2344 : : protected:
2345 : : /* Use covariance to implement clone function as returning this object
2346 : : * rather than base */
2347 : 1 : Enum *clone_item_impl () const override { return new Enum (*this); }
2348 : : };
2349 : :
2350 : : // Rust untagged union used for C compat AST node
2351 : : class Union : public VisItem
2352 : : {
2353 : : Identifier union_name;
2354 : :
2355 : : // bool has_generics;
2356 : : // Generics generic_params;
2357 : : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2358 : :
2359 : : // bool has_where_clause;
2360 : : WhereClause where_clause;
2361 : :
2362 : : std::vector<StructField> variants;
2363 : :
2364 : : location_t locus;
2365 : :
2366 : : public:
2367 : : std::string as_string () const override;
2368 : :
2369 : : // Returns whether union has generic params.
2370 : 203 : bool has_generics () const { return !generic_params.empty (); }
2371 : :
2372 : : // Returns whether union has where clause.
2373 : 916 : bool has_where_clause () const { return !where_clause.is_empty (); }
2374 : :
2375 : 118 : Union (Identifier union_name, Visibility vis,
2376 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
2377 : : WhereClause where_clause, std::vector<StructField> variants,
2378 : : std::vector<Attribute> outer_attrs, location_t locus)
2379 : 118 : : VisItem (std::move (vis), std::move (outer_attrs)),
2380 : 236 : union_name (std::move (union_name)),
2381 : 118 : generic_params (std::move (generic_params)),
2382 : 118 : where_clause (std::move (where_clause)), variants (std::move (variants)),
2383 : 118 : locus (locus)
2384 : 118 : {}
2385 : :
2386 : : // copy constructor with vector clone
2387 : 1 : Union (Union const &other)
2388 : 2 : : VisItem (other), union_name (other.union_name),
2389 : 1 : where_clause (other.where_clause), variants (other.variants),
2390 : 1 : locus (other.locus)
2391 : : {
2392 : 1 : generic_params.reserve (other.generic_params.size ());
2393 : 2 : for (const auto &e : other.generic_params)
2394 : 1 : generic_params.push_back (e->clone_generic_param ());
2395 : 1 : }
2396 : :
2397 : : // overloaded assignment operator with vector clone
2398 : : Union &operator= (Union const &other)
2399 : : {
2400 : : VisItem::operator= (other);
2401 : : union_name = other.union_name;
2402 : : where_clause = other.where_clause;
2403 : : variants = other.variants;
2404 : : locus = other.locus;
2405 : :
2406 : : generic_params.reserve (other.generic_params.size ());
2407 : : for (const auto &e : other.generic_params)
2408 : : generic_params.push_back (e->clone_generic_param ());
2409 : :
2410 : : return *this;
2411 : : }
2412 : :
2413 : : // move constructors
2414 : : Union (Union &&other) = default;
2415 : : Union &operator= (Union &&other) = default;
2416 : :
2417 : 286 : location_t get_locus () const override final { return locus; }
2418 : :
2419 : : void accept_vis (ASTVisitor &vis) override;
2420 : :
2421 : : // Invalid if name is empty, so base stripping on that.
2422 : 0 : void mark_for_strip () override { union_name = {""}; }
2423 : 237 : bool is_marked_for_strip () const override { return union_name.empty (); }
2424 : :
2425 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2426 : 1412 : std::vector<StructField> &get_variants () { return variants; }
2427 : : const std::vector<StructField> &get_variants () const { return variants; }
2428 : :
2429 : 141 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2430 : : {
2431 : 1093 : return generic_params;
2432 : : }
2433 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2434 : : {
2435 : : return generic_params;
2436 : : }
2437 : :
2438 : : // TODO: is this better? Or is a "vis_block" better?
2439 : 0 : WhereClause &get_where_clause () { return where_clause; }
2440 : :
2441 : 437 : Identifier get_identifier () const { return union_name; }
2442 : :
2443 : 98 : Item::Kind get_item_kind () const override { return Item::Kind::Union; }
2444 : :
2445 : : protected:
2446 : : /* Use covariance to implement clone function as returning this object
2447 : : * rather than base */
2448 : 1 : Union *clone_item_impl () const override { return new Union (*this); }
2449 : : };
2450 : :
2451 : : /* "Constant item" AST node - used for constant, compile-time expressions
2452 : : * within module scope (like constexpr) */
2453 : : class ConstantItem : public VisItem, public AssociatedItem
2454 : : {
2455 : : // either has an identifier or "_" - maybe handle in identifier?
2456 : : // bool identifier_is_underscore;
2457 : : // if no identifier declared, identifier will be "_"
2458 : : std::string identifier;
2459 : :
2460 : : std::unique_ptr<Type> type;
2461 : : std::unique_ptr<Expr> const_expr;
2462 : :
2463 : : location_t locus;
2464 : :
2465 : : public:
2466 : : std::string as_string () const override;
2467 : :
2468 : 599 : ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
2469 : : std::unique_ptr<Expr> const_expr,
2470 : : std::vector<Attribute> outer_attrs, location_t locus)
2471 : 599 : : VisItem (std::move (vis), std::move (outer_attrs)),
2472 : 599 : identifier (std::move (ident)), type (std::move (type)),
2473 : 599 : const_expr (std::move (const_expr)), locus (locus)
2474 : 599 : {}
2475 : :
2476 : 6 : ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
2477 : : std::vector<Attribute> outer_attrs, location_t locus)
2478 : 6 : : VisItem (std::move (vis), std::move (outer_attrs)),
2479 : 6 : identifier (std::move (ident)), type (std::move (type)),
2480 : 6 : const_expr (nullptr), locus (locus)
2481 : 6 : {}
2482 : :
2483 : 35 : ConstantItem (ConstantItem const &other)
2484 : 70 : : VisItem (other), identifier (other.identifier), locus (other.locus)
2485 : : {
2486 : : // guard to prevent null dereference (only required if error state)
2487 : 35 : if (other.type != nullptr)
2488 : 35 : type = other.type->clone_type ();
2489 : 35 : if (other.const_expr != nullptr)
2490 : 35 : const_expr = other.const_expr->clone_expr ();
2491 : 35 : }
2492 : :
2493 : : // Overload assignment operator to clone
2494 : : ConstantItem &operator= (ConstantItem const &other)
2495 : : {
2496 : : VisItem::operator= (other);
2497 : : identifier = other.identifier;
2498 : : locus = other.locus;
2499 : :
2500 : : // guard to prevent null dereference (only required if error state)
2501 : : if (other.type != nullptr)
2502 : : type = other.type->clone_type ();
2503 : : else
2504 : : type = nullptr;
2505 : : if (other.const_expr != nullptr)
2506 : : const_expr = other.const_expr->clone_expr ();
2507 : : else
2508 : : const_expr = nullptr;
2509 : :
2510 : : return *this;
2511 : : }
2512 : :
2513 : : // move constructors
2514 : : ConstantItem (ConstantItem &&other) = default;
2515 : : ConstantItem &operator= (ConstantItem &&other) = default;
2516 : :
2517 : : /* Returns whether constant item is an "unnamed" (wildcard underscore used
2518 : : * as identifier) constant. */
2519 : 0 : bool is_unnamed () const { return identifier == "_"; }
2520 : :
2521 : 1440 : location_t get_locus () const override final { return locus; }
2522 : :
2523 : : void accept_vis (ASTVisitor &vis) override;
2524 : :
2525 : : // Invalid if type or expression are null, so base stripping on that.
2526 : 0 : void mark_for_strip () override
2527 : : {
2528 : 0 : type = nullptr;
2529 : 0 : const_expr = nullptr;
2530 : 0 : }
2531 : 1265 : bool is_marked_for_strip () const override
2532 : : {
2533 : 1265 : return type == nullptr && const_expr == nullptr;
2534 : : }
2535 : :
2536 : 7504 : bool has_expr () { return const_expr != nullptr; }
2537 : :
2538 : : // TODO: is this better? Or is a "vis_block" better?
2539 : 6655 : Expr &get_expr ()
2540 : : {
2541 : 6655 : rust_assert (const_expr != nullptr);
2542 : 6655 : return *const_expr;
2543 : : }
2544 : :
2545 : 683 : std::unique_ptr<Expr> &get_expr_ptr ()
2546 : : {
2547 : 683 : rust_assert (const_expr != nullptr);
2548 : 683 : return const_expr;
2549 : : }
2550 : :
2551 : : // TODO: is this better? Or is a "vis_block" better?
2552 : 6703 : Type &get_type ()
2553 : : {
2554 : 6703 : rust_assert (type != nullptr);
2555 : 6703 : return *type;
2556 : : }
2557 : :
2558 : 689 : std::unique_ptr<Type> &get_type_ptr ()
2559 : : {
2560 : 689 : rust_assert (type != nullptr);
2561 : 689 : return type;
2562 : : }
2563 : :
2564 : 3356 : std::string get_identifier () const { return identifier; }
2565 : :
2566 : 380 : Item::Kind get_item_kind () const override
2567 : : {
2568 : 380 : return Item::Kind::ConstantItem;
2569 : : }
2570 : :
2571 : : protected:
2572 : : /* Use covariance to implement clone function as returning this object
2573 : : * rather than base */
2574 : 0 : ConstantItem *clone_item_impl () const override
2575 : : {
2576 : 0 : return new ConstantItem (*this);
2577 : : }
2578 : :
2579 : : /* Use covariance to implement clone function as returning this object
2580 : : * rather than base */
2581 : 35 : ConstantItem *clone_associated_item_impl () const override
2582 : : {
2583 : 35 : return new ConstantItem (*this);
2584 : : }
2585 : : };
2586 : :
2587 : : /* Static item AST node - items within module scope with fixed storage
2588 : : * duration? */
2589 : : class StaticItem : public VisItem
2590 : : {
2591 : : bool has_mut;
2592 : : Identifier name;
2593 : : std::unique_ptr<Type> type;
2594 : : std::unique_ptr<Expr> expr;
2595 : : location_t locus;
2596 : :
2597 : : public:
2598 : : std::string as_string () const override;
2599 : :
2600 : 73 : StaticItem (Identifier name, bool is_mut, std::unique_ptr<Type> type,
2601 : : std::unique_ptr<Expr> expr, Visibility vis,
2602 : : std::vector<Attribute> outer_attrs, location_t locus)
2603 : 146 : : VisItem (std::move (vis), std::move (outer_attrs)), has_mut (is_mut),
2604 : 146 : name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
2605 : 73 : locus (locus)
2606 : 73 : {}
2607 : :
2608 : : // Copy constructor with clone
2609 : 0 : StaticItem (StaticItem const &other)
2610 : 0 : : VisItem (other), has_mut (other.has_mut), name (other.name),
2611 : 0 : locus (other.locus)
2612 : : {
2613 : : // guard to prevent null dereference (only required if error state)
2614 : 0 : if (other.type != nullptr)
2615 : 0 : type = other.type->clone_type ();
2616 : 0 : if (other.expr != nullptr)
2617 : 0 : expr = other.expr->clone_expr ();
2618 : 0 : }
2619 : :
2620 : : // Overloaded assignment operator to clone
2621 : : StaticItem &operator= (StaticItem const &other)
2622 : : {
2623 : : VisItem::operator= (other);
2624 : : name = other.name;
2625 : : has_mut = other.has_mut;
2626 : : locus = other.locus;
2627 : :
2628 : : // guard to prevent null dereference (only required if error state)
2629 : : if (other.type != nullptr)
2630 : : type = other.type->clone_type ();
2631 : : else
2632 : : type = nullptr;
2633 : : if (other.expr != nullptr)
2634 : : expr = other.expr->clone_expr ();
2635 : : else
2636 : : expr = nullptr;
2637 : :
2638 : : return *this;
2639 : : }
2640 : :
2641 : : // move constructors
2642 : : StaticItem (StaticItem &&other) = default;
2643 : : StaticItem &operator= (StaticItem &&other) = default;
2644 : :
2645 : 178 : location_t get_locus () const override final { return locus; }
2646 : :
2647 : : void accept_vis (ASTVisitor &vis) override;
2648 : :
2649 : : // Invalid if type or expression are null, so base stripping on that.
2650 : 0 : void mark_for_strip () override
2651 : : {
2652 : 0 : type = nullptr;
2653 : 0 : expr = nullptr;
2654 : 0 : }
2655 : 146 : bool is_marked_for_strip () const override
2656 : : {
2657 : 146 : return type == nullptr && expr == nullptr;
2658 : : }
2659 : :
2660 : 2 : bool has_expr () { return expr != nullptr; }
2661 : :
2662 : : // TODO: is this better? Or is a "vis_block" better?
2663 : 816 : Expr &get_expr ()
2664 : : {
2665 : 816 : rust_assert (expr != nullptr);
2666 : 816 : return *expr;
2667 : : }
2668 : :
2669 : 86 : std::unique_ptr<Expr> &get_expr_ptr ()
2670 : : {
2671 : 86 : rust_assert (expr != nullptr);
2672 : 86 : return expr;
2673 : : }
2674 : :
2675 : : // TODO: is this better? Or is a "vis_block" better?
2676 : 816 : Type &get_type ()
2677 : : {
2678 : 816 : rust_assert (type != nullptr);
2679 : 816 : return *type;
2680 : : }
2681 : :
2682 : 86 : std::unique_ptr<Type> &get_type_ptr ()
2683 : : {
2684 : 86 : rust_assert (type != nullptr);
2685 : 86 : return type;
2686 : : }
2687 : :
2688 : 65 : bool is_mutable () const { return has_mut; }
2689 : :
2690 : 202 : Identifier get_identifier () const { return name; }
2691 : :
2692 : 55 : Item::Kind get_item_kind () const override { return Item::Kind::StaticItem; }
2693 : :
2694 : : protected:
2695 : : /* Use covariance to implement clone function as returning this object
2696 : : * rather than base */
2697 : 0 : StaticItem *clone_item_impl () const override
2698 : : {
2699 : 0 : return new StaticItem (*this);
2700 : : }
2701 : : };
2702 : :
2703 : : // Constant item within traits
2704 : : class TraitItemConst : public TraitItem
2705 : : {
2706 : : std::vector<Attribute> outer_attrs;
2707 : : Identifier name;
2708 : : std::unique_ptr<Type> type;
2709 : :
2710 : : // bool has_expression;
2711 : : std::unique_ptr<Expr> expr;
2712 : :
2713 : : public:
2714 : : // Whether the constant item has an associated expression.
2715 : 194 : bool has_expression () const { return expr != nullptr; }
2716 : :
2717 : 52 : TraitItemConst (Identifier name, std::unique_ptr<Type> type,
2718 : : std::unique_ptr<Expr> expr,
2719 : : std::vector<Attribute> outer_attrs, location_t locus)
2720 : 104 : : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
2721 : 52 : name (std::move (name)), type (std::move (type)), expr (std::move (expr))
2722 : 52 : {}
2723 : :
2724 : : // Copy constructor with clones
2725 : 0 : TraitItemConst (TraitItemConst const &other)
2726 : 0 : : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2727 : 0 : name (other.name)
2728 : : {
2729 : 0 : node_id = other.node_id;
2730 : :
2731 : : // guard to prevent null dereference
2732 : 0 : if (other.expr != nullptr)
2733 : 0 : expr = other.expr->clone_expr ();
2734 : :
2735 : : // guard to prevent null dereference (only for error state)
2736 : 0 : if (other.type != nullptr)
2737 : 0 : type = other.type->clone_type ();
2738 : 0 : }
2739 : :
2740 : : // Overloaded assignment operator to clone
2741 : : TraitItemConst &operator= (TraitItemConst const &other)
2742 : : {
2743 : : TraitItem::operator= (other);
2744 : : outer_attrs = other.outer_attrs;
2745 : : name = other.name;
2746 : : locus = other.locus;
2747 : : node_id = other.node_id;
2748 : :
2749 : : // guard to prevent null dereference
2750 : : if (other.expr != nullptr)
2751 : : expr = other.expr->clone_expr ();
2752 : : else
2753 : : expr = nullptr;
2754 : :
2755 : : // guard to prevent null dereference (only for error state)
2756 : : if (other.type != nullptr)
2757 : : type = other.type->clone_type ();
2758 : : else
2759 : : type = nullptr;
2760 : :
2761 : : return *this;
2762 : : }
2763 : :
2764 : : // move constructors
2765 : : TraitItemConst (TraitItemConst &&other) = default;
2766 : : TraitItemConst &operator= (TraitItemConst &&other) = default;
2767 : :
2768 : : std::string as_string () const override;
2769 : :
2770 : 93 : location_t get_locus () const override { return locus; }
2771 : :
2772 : : void accept_vis (ASTVisitor &vis) override;
2773 : :
2774 : : // Invalid if type is null, so base stripping on that.
2775 : 0 : void mark_for_strip () override { type = nullptr; }
2776 : 158 : bool is_marked_for_strip () const override { return type == nullptr; }
2777 : :
2778 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2779 : 712 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2780 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2781 : :
2782 : 679 : bool has_expr () const { return expr != nullptr; }
2783 : :
2784 : : // TODO: is this better? Or is a "vis_block" better?
2785 : 205 : Expr &get_expr ()
2786 : : {
2787 : 205 : rust_assert (has_expr ());
2788 : 205 : return *expr;
2789 : : }
2790 : :
2791 : 19 : std::unique_ptr<Expr> &get_expr_ptr ()
2792 : : {
2793 : 19 : rust_assert (has_expr ());
2794 : 19 : return expr;
2795 : : }
2796 : :
2797 : : // TODO: is this better? Or is a "vis_block" better?
2798 : 751 : Type &get_type ()
2799 : : {
2800 : 751 : rust_assert (type != nullptr);
2801 : 751 : return *type;
2802 : : }
2803 : :
2804 : 73 : std::unique_ptr<Type> &get_type_ptr ()
2805 : : {
2806 : 73 : rust_assert (type != nullptr);
2807 : 73 : return type;
2808 : : }
2809 : :
2810 : 126 : Identifier get_identifier () const { return name; }
2811 : :
2812 : : protected:
2813 : : // Clone function implementation as (not pure) virtual method
2814 : 0 : TraitItemConst *clone_associated_item_impl () const override
2815 : : {
2816 : 0 : return new TraitItemConst (*this);
2817 : : }
2818 : : };
2819 : :
2820 : : // Type items within traits
2821 : : class TraitItemType : public TraitItem
2822 : : {
2823 : : std::vector<Attribute> outer_attrs;
2824 : :
2825 : : Identifier name;
2826 : :
2827 : : // bool has_type_param_bounds;
2828 : : // TypeParamBounds type_param_bounds;
2829 : : std::vector<std::unique_ptr<TypeParamBound>>
2830 : : type_param_bounds; // inlined form
2831 : :
2832 : : public:
2833 : : // Returns whether trait item type has type param bounds.
2834 : 0 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2835 : :
2836 : 736 : TraitItemType (Identifier name,
2837 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
2838 : : std::vector<Attribute> outer_attrs, Visibility vis,
2839 : : location_t locus)
2840 : 1472 : : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
2841 : 736 : name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
2842 : 736 : {}
2843 : :
2844 : : // Copy constructor with vector clone
2845 : 13 : TraitItemType (TraitItemType const &other)
2846 : 26 : : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2847 : 13 : name (other.name)
2848 : : {
2849 : 13 : node_id = other.node_id;
2850 : 13 : type_param_bounds.reserve (other.type_param_bounds.size ());
2851 : 14 : for (const auto &e : other.type_param_bounds)
2852 : 1 : type_param_bounds.push_back (e->clone_type_param_bound ());
2853 : 13 : }
2854 : :
2855 : : // Overloaded assignment operator with vector clone
2856 : : TraitItemType &operator= (TraitItemType const &other)
2857 : : {
2858 : : TraitItem::operator= (other);
2859 : : outer_attrs = other.outer_attrs;
2860 : : name = other.name;
2861 : : locus = other.locus;
2862 : : node_id = other.node_id;
2863 : :
2864 : : type_param_bounds.reserve (other.type_param_bounds.size ());
2865 : : for (const auto &e : other.type_param_bounds)
2866 : : type_param_bounds.push_back (e->clone_type_param_bound ());
2867 : :
2868 : : return *this;
2869 : : }
2870 : :
2871 : : // default move constructors
2872 : : TraitItemType (TraitItemType &&other) = default;
2873 : : TraitItemType &operator= (TraitItemType &&other) = default;
2874 : :
2875 : : std::string as_string () const override;
2876 : :
2877 : : void accept_vis (ASTVisitor &vis) override;
2878 : :
2879 : : // Invalid if name is empty, so base stripping on that.
2880 : 0 : void mark_for_strip () override { name = {""}; }
2881 : 2529 : bool is_marked_for_strip () const override { return name.empty (); }
2882 : :
2883 : : // TODO: this mutable getter seems really dodgy. Think up better way.
2884 : 11331 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2885 : 724 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2886 : :
2887 : : // TODO: mutable getter seems kinda dodgy
2888 : : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
2889 : : {
2890 : 8411 : return type_param_bounds;
2891 : : }
2892 : : const std::vector<std::unique_ptr<TypeParamBound>> &
2893 : : get_type_param_bounds () const
2894 : : {
2895 : : return type_param_bounds;
2896 : : }
2897 : :
2898 : 2750 : Identifier get_identifier () const { return name; }
2899 : :
2900 : : protected:
2901 : : // Clone function implementation as (not pure) virtual method
2902 : 13 : TraitItemType *clone_associated_item_impl () const override
2903 : : {
2904 : 13 : return new TraitItemType (*this);
2905 : : }
2906 : : };
2907 : :
2908 : : // Rust trait item declaration AST node
2909 : : class Trait : public VisItem
2910 : : {
2911 : : bool has_unsafe;
2912 : : bool has_auto;
2913 : : Identifier name;
2914 : : std::vector<std::unique_ptr<GenericParam>> generic_params;
2915 : : TypeParam self_param;
2916 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
2917 : : WhereClause where_clause;
2918 : : std::vector<Attribute> inner_attrs;
2919 : : std::vector<std::unique_ptr<AssociatedItem>> trait_items;
2920 : : location_t locus;
2921 : :
2922 : : public:
2923 : : std::string as_string () const override;
2924 : :
2925 : : // Returns whether trait has generic parameters.
2926 : 3203 : bool has_generics () const { return !generic_params.empty (); }
2927 : :
2928 : : // Returns whether trait has type parameter bounds.
2929 : 5878 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2930 : :
2931 : : // Returns whether trait has where clause.
2932 : 31486 : bool has_where_clause () const { return !where_clause.is_empty (); }
2933 : :
2934 : : // Returns whether trait has trait items.
2935 : 40 : bool has_trait_items () const { return !trait_items.empty (); }
2936 : :
2937 : : // Returns whether trait has inner attributes.
2938 : : bool has_inner_attrs () const { return !inner_attrs.empty (); }
2939 : :
2940 : 12509 : Identifier get_identifier () const { return name; }
2941 : :
2942 : 3163 : bool is_unsafe () const { return has_unsafe; }
2943 : 9675 : bool is_auto () const { return has_auto; }
2944 : :
2945 : : // Mega-constructor
2946 : 3290 : Trait (Identifier name, bool is_unsafe, bool is_auto,
2947 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
2948 : : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
2949 : : WhereClause where_clause,
2950 : : std::vector<std::unique_ptr<AssociatedItem>> trait_items,
2951 : : Visibility vis, std::vector<Attribute> outer_attrs,
2952 : : std::vector<Attribute> inner_attrs, location_t locus)
2953 : 3290 : : VisItem (std::move (vis), std::move (outer_attrs)),
2954 : 6580 : has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)),
2955 : 6580 : generic_params (std::move (generic_params)), self_param ({"Self"}, locus),
2956 : 3290 : type_param_bounds (std::move (type_param_bounds)),
2957 : 3290 : where_clause (std::move (where_clause)),
2958 : 3290 : inner_attrs (std::move (inner_attrs)),
2959 : 3290 : trait_items (std::move (trait_items)), locus (locus)
2960 : 3290 : {}
2961 : :
2962 : : // Copy constructor with vector clone
2963 : 4 : Trait (Trait const &other)
2964 : 8 : : VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto),
2965 : 4 : name (other.name), self_param (other.self_param),
2966 : 4 : where_clause (other.where_clause), inner_attrs (other.inner_attrs),
2967 : 8 : locus (other.locus)
2968 : : {
2969 : 4 : generic_params.reserve (other.generic_params.size ());
2970 : 4 : for (const auto &e : other.generic_params)
2971 : 0 : generic_params.push_back (e->clone_generic_param ());
2972 : :
2973 : 4 : type_param_bounds.reserve (other.type_param_bounds.size ());
2974 : 4 : for (const auto &e : other.type_param_bounds)
2975 : 0 : type_param_bounds.push_back (e->clone_type_param_bound ());
2976 : :
2977 : 4 : trait_items.reserve (other.trait_items.size ());
2978 : 9 : for (const auto &e : other.trait_items)
2979 : 5 : trait_items.push_back (e->clone_associated_item ());
2980 : 4 : }
2981 : :
2982 : : // Overloaded assignment operator with vector clone
2983 : : Trait &operator= (Trait const &other)
2984 : : {
2985 : : VisItem::operator= (other);
2986 : : name = other.name;
2987 : : self_param = other.self_param;
2988 : : has_unsafe = other.has_unsafe;
2989 : : has_auto = other.has_auto;
2990 : : where_clause = other.where_clause;
2991 : : inner_attrs = other.inner_attrs;
2992 : : locus = other.locus;
2993 : :
2994 : : generic_params.reserve (other.generic_params.size ());
2995 : : for (const auto &e : other.generic_params)
2996 : : generic_params.push_back (e->clone_generic_param ());
2997 : :
2998 : : type_param_bounds.reserve (other.type_param_bounds.size ());
2999 : : for (const auto &e : other.type_param_bounds)
3000 : : type_param_bounds.push_back (e->clone_type_param_bound ());
3001 : :
3002 : : trait_items.reserve (other.trait_items.size ());
3003 : : for (const auto &e : other.trait_items)
3004 : : trait_items.push_back (e->clone_associated_item ());
3005 : :
3006 : : return *this;
3007 : : }
3008 : :
3009 : : // default move constructors
3010 : : Trait (Trait &&other) = default;
3011 : : Trait &operator= (Trait &&other) = default;
3012 : :
3013 : 10567 : location_t get_locus () const override final { return locus; }
3014 : :
3015 : : void accept_vis (ASTVisitor &vis) override;
3016 : :
3017 : : // Invalid if trait name is empty, so base stripping on that.
3018 : 4 : void mark_for_strip () override { name = {""}; }
3019 : 7476 : bool is_marked_for_strip () const override { return name.empty (); }
3020 : :
3021 : : // TODO: think of better way to do this
3022 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3023 : 28841 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3024 : :
3025 : : const std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items () const
3026 : : {
3027 : : return trait_items;
3028 : : }
3029 : 11372 : std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items ()
3030 : : {
3031 : 47526 : return trait_items;
3032 : : }
3033 : :
3034 : 5175 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3035 : : {
3036 : 37339 : return generic_params;
3037 : : }
3038 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3039 : : {
3040 : : return generic_params;
3041 : : }
3042 : :
3043 : : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
3044 : : {
3045 : 28811 : return type_param_bounds;
3046 : : }
3047 : : const std::vector<std::unique_ptr<TypeParamBound>> &
3048 : : get_type_param_bounds () const
3049 : : {
3050 : : return type_param_bounds;
3051 : : }
3052 : :
3053 : 88 : WhereClause &get_where_clause () { return where_clause; }
3054 : :
3055 : 24158 : AST::TypeParam &get_implicit_self () { return self_param; }
3056 : :
3057 : 3347 : Item::Kind get_item_kind () const override { return Item::Kind::Trait; }
3058 : :
3059 : : protected:
3060 : : /* Use covariance to implement clone function as returning this object
3061 : : * rather than base */
3062 : 4 : Trait *clone_item_impl () const override { return new Trait (*this); }
3063 : : };
3064 : :
3065 : : // Implementation item declaration AST node - abstract base class
3066 : : class Impl : public VisItem
3067 : : {
3068 : : // must be protected to allow subclasses to access them properly
3069 : : protected:
3070 : : // bool has_generics;
3071 : : // Generics generic_params;
3072 : : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3073 : :
3074 : : std::unique_ptr<Type> trait_type;
3075 : :
3076 : : // bool has_where_clause;
3077 : : WhereClause where_clause;
3078 : :
3079 : : // bool has_inner_attrs;
3080 : : std::vector<Attribute> inner_attrs;
3081 : :
3082 : : private:
3083 : : // doesn't really need to be protected as write access probably not needed
3084 : : location_t locus;
3085 : :
3086 : : public:
3087 : : // Returns whether impl has generic parameters.
3088 : 9192 : bool has_generics () const { return !generic_params.empty (); }
3089 : :
3090 : : // Returns whether impl has where clause.
3091 : 49263 : bool has_where_clause () const { return !where_clause.is_empty (); }
3092 : :
3093 : : // Returns whether impl has inner attributes.
3094 : : bool has_inner_attrs () const { return !inner_attrs.empty (); }
3095 : :
3096 : 10289 : location_t get_locus () const override final { return locus; }
3097 : :
3098 : : // Invalid if trait type is null, so base stripping on that.
3099 : 2 : void mark_for_strip () override { trait_type = nullptr; }
3100 : 13785 : bool is_marked_for_strip () const override { return trait_type == nullptr; }
3101 : :
3102 : : // TODO: think of better way to do this
3103 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3104 : 57583 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3105 : :
3106 : 1895 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3107 : : {
3108 : 52662 : return generic_params;
3109 : : }
3110 : : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3111 : : {
3112 : : return generic_params;
3113 : : }
3114 : :
3115 : : // TODO: is this better? Or is a "vis_block" better?
3116 : 916 : WhereClause &get_where_clause () { return where_clause; }
3117 : :
3118 : : // TODO: is this better? Or is a "vis_block" better?
3119 : 95279 : Type &get_type ()
3120 : : {
3121 : 95279 : rust_assert (trait_type != nullptr);
3122 : 95279 : return *trait_type;
3123 : : }
3124 : :
3125 : 7772 : std::unique_ptr<Type> &get_type_ptr ()
3126 : : {
3127 : 7772 : rust_assert (trait_type != nullptr);
3128 : 7772 : return trait_type;
3129 : : }
3130 : :
3131 : 5764 : Item::Kind get_item_kind () const override { return Item::Kind::Impl; }
3132 : :
3133 : : protected:
3134 : : // Mega-constructor
3135 : 5160 : Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
3136 : : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3137 : : Visibility vis, std::vector<Attribute> inner_attrs,
3138 : : std::vector<Attribute> outer_attrs, location_t locus)
3139 : 5160 : : VisItem (std::move (vis), std::move (outer_attrs)),
3140 : 5160 : generic_params (std::move (generic_params)),
3141 : 5160 : trait_type (std::move (trait_type)),
3142 : 5160 : where_clause (std::move (where_clause)),
3143 : 5160 : inner_attrs (std::move (inner_attrs)), locus (locus)
3144 : 5160 : {}
3145 : :
3146 : : // Copy constructor
3147 : 13784 : Impl (Impl const &other)
3148 : 13784 : : VisItem (other), where_clause (other.where_clause),
3149 : 13784 : inner_attrs (other.inner_attrs), locus (other.locus)
3150 : : {
3151 : : // guard to prevent null dereference (only required if error state)
3152 : 13784 : if (other.trait_type != nullptr)
3153 : 13784 : trait_type = other.trait_type->clone_type ();
3154 : :
3155 : 13784 : generic_params.reserve (other.generic_params.size ());
3156 : 14888 : for (const auto &e : other.generic_params)
3157 : 1104 : generic_params.push_back (e->clone_generic_param ());
3158 : 13784 : }
3159 : :
3160 : : // Assignment operator overload with cloning
3161 : : Impl &operator= (Impl const &other)
3162 : : {
3163 : : VisItem::operator= (other);
3164 : : where_clause = other.where_clause;
3165 : : inner_attrs = other.inner_attrs;
3166 : : locus = other.locus;
3167 : :
3168 : : // guard to prevent null dereference (only required if error state)
3169 : : if (other.trait_type != nullptr)
3170 : : trait_type = other.trait_type->clone_type ();
3171 : : else
3172 : : trait_type = nullptr;
3173 : :
3174 : : generic_params.reserve (other.generic_params.size ());
3175 : : for (const auto &e : other.generic_params)
3176 : : generic_params.push_back (e->clone_generic_param ());
3177 : :
3178 : : return *this;
3179 : : }
3180 : :
3181 : : // move constructors
3182 : : Impl (Impl &&other) = default;
3183 : : Impl &operator= (Impl &&other) = default;
3184 : : };
3185 : :
3186 : : // Regular "impl foo" impl block declaration AST node
3187 : : class InherentImpl : public Impl
3188 : : {
3189 : : // bool has_impl_items;
3190 : : std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3191 : :
3192 : : public:
3193 : : std::string as_string () const override;
3194 : :
3195 : : // Returns whether inherent impl block has inherent impl items.
3196 : 0 : bool has_impl_items () const { return !impl_items.empty (); }
3197 : :
3198 : : // Mega-constructor
3199 : 1026 : InherentImpl (std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3200 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
3201 : : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3202 : : Visibility vis, std::vector<Attribute> inner_attrs,
3203 : : std::vector<Attribute> outer_attrs, location_t locus)
3204 : 1026 : : Impl (std::move (generic_params), std::move (trait_type),
3205 : : std::move (where_clause), std::move (vis), std::move (inner_attrs),
3206 : : std::move (outer_attrs), locus),
3207 : 1026 : impl_items (std::move (impl_items))
3208 : 1026 : {}
3209 : :
3210 : : // Copy constructor with vector clone
3211 : 1027 : InherentImpl (InherentImpl const &other) : Impl (other)
3212 : : {
3213 : 1027 : impl_items.reserve (other.impl_items.size ());
3214 : 9663 : for (const auto &e : other.impl_items)
3215 : 8636 : impl_items.push_back (e->clone_associated_item ());
3216 : 1027 : }
3217 : :
3218 : : // Overloaded assignment operator with vector clone
3219 : : InherentImpl &operator= (InherentImpl const &other)
3220 : : {
3221 : : Impl::operator= (other);
3222 : :
3223 : : impl_items.reserve (other.impl_items.size ());
3224 : : for (const auto &e : other.impl_items)
3225 : : impl_items.push_back (e->clone_associated_item ());
3226 : :
3227 : : return *this;
3228 : : }
3229 : :
3230 : : // default move constructors
3231 : : InherentImpl (InherentImpl &&other) = default;
3232 : : InherentImpl &operator= (InherentImpl &&other) = default;
3233 : :
3234 : : void accept_vis (ASTVisitor &vis) override;
3235 : :
3236 : : // TODO: think of better way to do this
3237 : : const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3238 : : {
3239 : : return impl_items;
3240 : : }
3241 : 2908 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3242 : : {
3243 : 14883 : return impl_items;
3244 : : }
3245 : :
3246 : : protected:
3247 : : /* Use covariance to implement clone function as returning this object
3248 : : * rather than base */
3249 : 1027 : InherentImpl *clone_item_impl () const override
3250 : : {
3251 : 1027 : return new InherentImpl (*this);
3252 : : }
3253 : : };
3254 : :
3255 : : // The "impl footrait for foo" impl block declaration AST node
3256 : : class TraitImpl : public Impl
3257 : : {
3258 : : bool has_unsafe;
3259 : : bool has_exclam;
3260 : : TypePath trait_path;
3261 : :
3262 : : // bool has_impl_items;
3263 : : std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3264 : :
3265 : : public:
3266 : : std::string as_string () const override;
3267 : :
3268 : : // Returns whether trait impl has impl items.
3269 : 0 : bool has_impl_items () const { return !impl_items.empty (); }
3270 : :
3271 : : // Mega-constructor
3272 : 4134 : TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
3273 : : std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3274 : : std::vector<std::unique_ptr<GenericParam>> generic_params,
3275 : : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3276 : : Visibility vis, std::vector<Attribute> inner_attrs,
3277 : : std::vector<Attribute> outer_attrs, location_t locus)
3278 : 4134 : : Impl (std::move (generic_params), std::move (trait_type),
3279 : : std::move (where_clause), std::move (vis), std::move (inner_attrs),
3280 : : std::move (outer_attrs), locus),
3281 : 4134 : has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path),
3282 : 4134 : impl_items (std::move (impl_items))
3283 : 4134 : {}
3284 : :
3285 : : // Copy constructor with vector clone
3286 : 12757 : TraitImpl (TraitImpl const &other)
3287 : 25514 : : Impl (other), has_unsafe (other.has_unsafe),
3288 : 12757 : has_exclam (other.has_exclam), trait_path (other.trait_path)
3289 : : {
3290 : 12757 : impl_items.reserve (other.impl_items.size ());
3291 : 23975 : for (const auto &e : other.impl_items)
3292 : 11218 : impl_items.push_back (e->clone_associated_item ());
3293 : 12757 : }
3294 : :
3295 : : // Overloaded assignment operator with vector clone
3296 : : TraitImpl &operator= (TraitImpl const &other)
3297 : : {
3298 : : Impl::operator= (other);
3299 : : trait_path = other.trait_path;
3300 : : has_unsafe = other.has_unsafe;
3301 : : has_exclam = other.has_exclam;
3302 : :
3303 : : impl_items.reserve (other.impl_items.size ());
3304 : : for (const auto &e : other.impl_items)
3305 : : impl_items.push_back (e->clone_associated_item ());
3306 : :
3307 : : return *this;
3308 : : }
3309 : :
3310 : : // move constructors
3311 : : TraitImpl (TraitImpl &&other) = default;
3312 : : TraitImpl &operator= (TraitImpl &&other) = default;
3313 : :
3314 : : void accept_vis (ASTVisitor &vis) override;
3315 : :
3316 : 3959 : bool is_unsafe () const { return has_unsafe; };
3317 : 8093 : bool is_exclam () const { return has_exclam; }
3318 : :
3319 : : // TODO: think of better way to do this
3320 : : const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3321 : : {
3322 : : return impl_items;
3323 : : }
3324 : 12524 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3325 : : {
3326 : 58870 : return impl_items;
3327 : : }
3328 : :
3329 : : // TODO: is this better? Or is a "vis_block" better?
3330 : 50738 : TypePath &get_trait_path () { return trait_path; }
3331 : :
3332 : : protected:
3333 : : /* Use covariance to implement clone function as returning this object
3334 : : * rather than base */
3335 : 12757 : TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
3336 : : };
3337 : :
3338 : : #if 0
3339 : : // Abstract base class for an item used inside an extern block
3340 : : class ExternalItem
3341 : : {
3342 : : // bool has_outer_attrs;
3343 : : std::vector<Attribute> outer_attrs;
3344 : :
3345 : : // bool has_visibility;
3346 : : Visibility visibility;
3347 : :
3348 : : Identifier item_name;
3349 : : location_t locus;
3350 : :
3351 : : public:
3352 : : virtual ~ExternalItem () {}
3353 : :
3354 : : /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
3355 : : * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
3356 : : * support would require a lot of refactoring. */
3357 : :
3358 : : // Returns whether item has outer attributes.
3359 : : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3360 : :
3361 : : // Returns whether item has non-default visibility.
3362 : : bool has_visibility () const { return !visibility.is_error (); }
3363 : :
3364 : : // Unique pointer custom clone function
3365 : : std::unique_ptr<ExternalItem> clone_external_item () const
3366 : : {
3367 : : return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
3368 : : }
3369 : :
3370 : : virtual std::string as_string () const;
3371 : :
3372 : : location_t get_locus () const override final { return locus; }
3373 : :
3374 : : virtual void accept_vis (ASTVisitor &vis) = 0;
3375 : :
3376 : : // TODO: make virtual? Would be more flexible.
3377 : : // Based on idea that name should never be empty.
3378 : : void mark_for_strip () { item_name = ""; };
3379 : : bool is_marked_for_strip () const { return item_name.empty (); };
3380 : :
3381 : : protected:
3382 : : ExternalItem (Identifier item_name, Visibility vis,
3383 : : std::vector<Attribute> outer_attrs, location_t locus)
3384 : : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
3385 : : item_name (std::move (item_name)), locus (locus)
3386 : : {}
3387 : :
3388 : : // Copy constructor
3389 : : ExternalItem (ExternalItem const &other)
3390 : : : outer_attrs (other.outer_attrs), visibility (other.visibility),
3391 : : item_name (other.item_name), locus (other.locus)
3392 : : {}
3393 : :
3394 : : // Overloaded assignment operator to clone
3395 : : ExternalItem &operator= (ExternalItem const &other)
3396 : : {
3397 : : item_name = other.item_name;
3398 : : visibility = other.visibility;
3399 : : outer_attrs = other.outer_attrs;
3400 : : locus = other.locus;
3401 : :
3402 : : return *this;
3403 : : }
3404 : :
3405 : : // move constructors
3406 : : ExternalItem (ExternalItem &&other) = default;
3407 : : ExternalItem &operator= (ExternalItem &&other) = default;
3408 : :
3409 : : // Clone function implementation as pure virtual method
3410 : : virtual ExternalItem *clone_external_item_impl () const = 0;
3411 : :
3412 : : // possibly make this public if required
3413 : : std::string get_item_name () const { return item_name; }
3414 : : };
3415 : : #endif
3416 : :
3417 : : // A foreign type defined outside the current crate.
3418 : : // https://rust-lang.github.io/rfcs/1861-extern-types.html
3419 : : class ExternalTypeItem : public ExternalItem
3420 : : {
3421 : : std::vector<Attribute> outer_attrs;
3422 : :
3423 : : Visibility visibility;
3424 : : Identifier item_name;
3425 : : location_t locus;
3426 : :
3427 : : bool marked_for_strip;
3428 : :
3429 : : public:
3430 : 6 : ExternalTypeItem (Identifier item_name, Visibility vis,
3431 : : std::vector<Attribute> outer_attrs, location_t locus)
3432 : 12 : : ExternalItem (), outer_attrs (std::move (outer_attrs)), visibility (vis),
3433 : 6 : item_name (std::move (item_name)), locus (locus), marked_for_strip (false)
3434 : 6 : {}
3435 : :
3436 : : // copy constructor
3437 : 0 : ExternalTypeItem (ExternalTypeItem const &other)
3438 : 0 : : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3439 : 0 : visibility (other.visibility), item_name (other.item_name),
3440 : 0 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3441 : : {
3442 : 0 : node_id = other.node_id;
3443 : 0 : }
3444 : :
3445 : : ExternalTypeItem &operator= (ExternalTypeItem const &other)
3446 : : {
3447 : : node_id = other.node_id;
3448 : : outer_attrs = other.outer_attrs;
3449 : : visibility = other.visibility;
3450 : : item_name = other.item_name;
3451 : : locus = other.locus;
3452 : : marked_for_strip = other.marked_for_strip;
3453 : :
3454 : : return *this;
3455 : : }
3456 : :
3457 : : // move constructors
3458 : : ExternalTypeItem (ExternalTypeItem &&other) = default;
3459 : : ExternalTypeItem &operator= (ExternalTypeItem &&other) = default;
3460 : :
3461 : : std::string as_string () const override;
3462 : :
3463 : : void accept_vis (ASTVisitor &vis) override;
3464 : :
3465 : : // Returns whether item has outer attributes.
3466 : : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3467 : :
3468 : : // Returns whether item has non-default visibility.
3469 : : bool has_visibility () const { return !visibility.is_error (); }
3470 : :
3471 : 3 : location_t get_locus () const { return locus; }
3472 : :
3473 : 0 : void mark_for_strip () override { marked_for_strip = true; };
3474 : 3 : bool is_marked_for_strip () const override { return marked_for_strip; };
3475 : :
3476 : : // TODO: this mutable getter seems really dodgy. Think up better way.
3477 : 16 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3478 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3479 : :
3480 : 1 : Identifier get_identifier () const { return item_name; }
3481 : :
3482 : 13 : Visibility &get_visibility () { return visibility; }
3483 : : const Visibility &get_visibility () const { return visibility; }
3484 : :
3485 : : protected:
3486 : : /* Use covariance to implement clone function as returning this object
3487 : : * rather than base */
3488 : 0 : ExternalTypeItem *clone_external_item_impl () const override
3489 : : {
3490 : 0 : return new ExternalTypeItem (*this);
3491 : : }
3492 : : };
3493 : :
3494 : : // A static item used in an extern block
3495 : : class ExternalStaticItem : public ExternalItem
3496 : : {
3497 : : // bool has_outer_attrs;
3498 : : std::vector<Attribute> outer_attrs;
3499 : :
3500 : : // bool has_visibility;
3501 : : Visibility visibility;
3502 : :
3503 : : Identifier item_name;
3504 : : location_t locus;
3505 : :
3506 : : bool has_mut;
3507 : : std::unique_ptr<Type> item_type;
3508 : :
3509 : : public:
3510 : 2 : ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
3511 : : bool is_mut, Visibility vis,
3512 : : std::vector<Attribute> outer_attrs, location_t locus)
3513 : 4 : : ExternalItem (), outer_attrs (std::move (outer_attrs)),
3514 : 2 : visibility (std::move (vis)), item_name (std::move (item_name)),
3515 : 2 : locus (locus), has_mut (is_mut), item_type (std::move (item_type))
3516 : 2 : {}
3517 : :
3518 : : // Copy constructor
3519 : 0 : ExternalStaticItem (ExternalStaticItem const &other)
3520 : 0 : : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3521 : 0 : visibility (other.visibility), item_name (other.item_name),
3522 : 0 : locus (other.locus), has_mut (other.has_mut)
3523 : : {
3524 : 0 : node_id = other.node_id;
3525 : : // guard to prevent null dereference (only required if error state)
3526 : 0 : if (other.item_type != nullptr)
3527 : 0 : item_type = other.item_type->clone_type ();
3528 : 0 : }
3529 : :
3530 : : // Overloaded assignment operator to clone
3531 : : ExternalStaticItem &operator= (ExternalStaticItem const &other)
3532 : : {
3533 : : node_id = other.node_id;
3534 : : outer_attrs = other.outer_attrs;
3535 : : visibility = other.visibility;
3536 : : item_name = other.item_name;
3537 : : locus = other.locus;
3538 : : has_mut = other.has_mut;
3539 : :
3540 : : // guard to prevent null dereference (only required if error state)
3541 : : if (other.item_type != nullptr)
3542 : : item_type = other.item_type->clone_type ();
3543 : : else
3544 : : item_type = nullptr;
3545 : :
3546 : : return *this;
3547 : : }
3548 : :
3549 : : // move constructors
3550 : : ExternalStaticItem (ExternalStaticItem &&other) = default;
3551 : : ExternalStaticItem &operator= (ExternalStaticItem &&other) = default;
3552 : :
3553 : : std::string as_string () const override;
3554 : :
3555 : : void accept_vis (ASTVisitor &vis) override;
3556 : :
3557 : : // Returns whether item has outer attributes.
3558 : : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3559 : :
3560 : : // Returns whether item has non-default visibility.
3561 : 0 : bool has_visibility () const { return !visibility.is_error (); }
3562 : :
3563 : 5 : location_t get_locus () const { return locus; }
3564 : :
3565 : : // Based on idea that type should never be null.
3566 : 0 : void mark_for_strip () override { item_type = nullptr; };
3567 : 5 : bool is_marked_for_strip () const override { return item_type == nullptr; };
3568 : :
3569 : : // TODO: this mutable getter seems really dodgy. Think up better way.
3570 : 24 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3571 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3572 : :
3573 : : // TODO: is this better? Or is a "vis_block" better?
3574 : 25 : Type &get_type ()
3575 : : {
3576 : 25 : rust_assert (item_type != nullptr);
3577 : 25 : return *item_type;
3578 : : }
3579 : :
3580 : 3 : std::unique_ptr<Type> &get_type_ptr ()
3581 : : {
3582 : 3 : rust_assert (item_type != nullptr);
3583 : 3 : return item_type;
3584 : : }
3585 : :
3586 : 5 : Identifier get_identifier () const { return item_name; }
3587 : :
3588 : 22 : Visibility &get_visibility () { return visibility; }
3589 : :
3590 : : const Visibility &get_visibility () const { return visibility; }
3591 : :
3592 : 2 : bool is_mut () const { return has_mut; }
3593 : :
3594 : : protected:
3595 : : /* Use covariance to implement clone function as returning this object
3596 : : * rather than base */
3597 : 0 : ExternalStaticItem *clone_external_item_impl () const override
3598 : : {
3599 : 0 : return new ExternalStaticItem (*this);
3600 : : }
3601 : : };
3602 : :
3603 : : // An extern block AST node
3604 : : class ExternBlock : public VisItem
3605 : : {
3606 : : // bool has_abi;
3607 : : std::string abi;
3608 : :
3609 : : // bool has_inner_attrs;
3610 : : std::vector<Attribute> inner_attrs;
3611 : :
3612 : : // bool has_extern_items;
3613 : : std::vector<std::unique_ptr<ExternalItem>> extern_items;
3614 : :
3615 : : location_t locus;
3616 : :
3617 : : // TODO: find another way to store this to save memory?
3618 : : bool marked_for_strip = false;
3619 : :
3620 : : public:
3621 : : std::string as_string () const override;
3622 : :
3623 : : // Returns whether extern block has inner attributes.
3624 : : bool has_inner_attrs () const { return !inner_attrs.empty (); }
3625 : :
3626 : : // Returns whether extern block has extern items.
3627 : 0 : bool has_extern_items () const { return !extern_items.empty (); }
3628 : :
3629 : : // Returns whether extern block has ABI name.
3630 : 3254 : bool has_abi () const { return !abi.empty (); }
3631 : :
3632 : 6508 : std::string get_abi () const { return abi; }
3633 : :
3634 : 1998 : ExternBlock (std::string abi,
3635 : : std::vector<std::unique_ptr<ExternalItem>> extern_items,
3636 : : Visibility vis, std::vector<Attribute> inner_attrs,
3637 : : std::vector<Attribute> outer_attrs, location_t locus)
3638 : 3996 : : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
3639 : 1998 : inner_attrs (std::move (inner_attrs)),
3640 : 1998 : extern_items (std::move (extern_items)), locus (locus)
3641 : 1998 : {}
3642 : :
3643 : : // Copy constructor with vector clone
3644 : 1 : ExternBlock (ExternBlock const &other)
3645 : 1 : : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
3646 : 2 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3647 : : {
3648 : 1 : extern_items.reserve (other.extern_items.size ());
3649 : 3 : for (const auto &e : other.extern_items)
3650 : 2 : extern_items.push_back (e->clone_external_item ());
3651 : 1 : }
3652 : :
3653 : : // Overloaded assignment operator with vector clone
3654 : : ExternBlock &operator= (ExternBlock const &other)
3655 : : {
3656 : : VisItem::operator= (other);
3657 : : abi = other.abi;
3658 : : inner_attrs = other.inner_attrs;
3659 : : locus = other.locus;
3660 : : marked_for_strip = other.marked_for_strip;
3661 : :
3662 : : extern_items.reserve (other.extern_items.size ());
3663 : : for (const auto &e : other.extern_items)
3664 : : extern_items.push_back (e->clone_external_item ());
3665 : :
3666 : : return *this;
3667 : : }
3668 : :
3669 : : // move constructors
3670 : : ExternBlock (ExternBlock &&other) = default;
3671 : : ExternBlock &operator= (ExternBlock &&other) = default;
3672 : :
3673 : 3152 : location_t get_locus () const override final { return locus; }
3674 : :
3675 : : void accept_vis (ASTVisitor &vis) override;
3676 : :
3677 : : // Can't think of any invalid invariants, so store boolean.
3678 : 0 : void mark_for_strip () override { marked_for_strip = true; }
3679 : 3169 : bool is_marked_for_strip () const override { return marked_for_strip; }
3680 : :
3681 : : // TODO: think of better way to do this
3682 : : const std::vector<std::unique_ptr<ExternalItem>> &get_extern_items () const
3683 : : {
3684 : : return extern_items;
3685 : : }
3686 : 4326 : std::vector<std::unique_ptr<ExternalItem>> &get_extern_items ()
3687 : : {
3688 : 16622 : return extern_items;
3689 : : }
3690 : :
3691 : : // TODO: think of better way to do this
3692 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3693 : 11800 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3694 : :
3695 : 1561 : Item::Kind get_item_kind () const override { return Item::Kind::ExternBlock; }
3696 : :
3697 : : protected:
3698 : : /* Use covariance to implement clone function as returning this object
3699 : : * rather than base */
3700 : 1 : ExternBlock *clone_item_impl () const override
3701 : : {
3702 : 1 : return new ExternBlock (*this);
3703 : : }
3704 : : };
3705 : :
3706 : : class MacroRulesDefinition;
3707 : : } // namespace AST
3708 : : } // namespace Rust
3709 : :
3710 : : #endif
|