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