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