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 307397 : Identifier get_type_representation () const { return type_representation; }
63 :
64 : // Returns whether the type of the type param has been specified.
65 2170493 : bool has_type () const { return type != nullptr; }
66 :
67 : // Returns whether the type param has type param bounds.
68 13201 : 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 1601118 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
74 :
75 16539 : 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 16539 : : GenericParam (Analysis::Mappings::get ().get_next_node_id ()),
81 16539 : outer_attrs (std::move (outer_attrs)),
82 16539 : type_representation (std::move (type_representation)),
83 16539 : type_param_bounds (std::move (type_param_bounds)),
84 16539 : type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait)
85 16539 : {}
86 :
87 : // Copy constructor uses clone
88 56904 : TypeParam (TypeParam const &other)
89 56904 : : GenericParam (other.node_id), outer_attrs (other.outer_attrs),
90 56904 : type_representation (other.type_representation), locus (other.locus),
91 113808 : was_impl_trait (other.was_impl_trait)
92 : {
93 : // guard to prevent null pointer dereference
94 56904 : if (other.type != nullptr)
95 1094 : type = other.type->clone_type ();
96 :
97 56904 : type_param_bounds.reserve (other.type_param_bounds.size ());
98 68341 : for (const auto &e : other.type_param_bounds)
99 11437 : type_param_bounds.push_back (e->clone_type_param_bound ());
100 56904 : }
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 307148 : location_t get_locus () const override final { return locus; }
131 :
132 12164 : 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 13142 : Type &get_type ()
138 : {
139 13142 : rust_assert (type != nullptr);
140 13142 : return *type;
141 : }
142 :
143 4137 : std::unique_ptr<Type> &get_type_ptr ()
144 : {
145 4137 : rust_assert (type != nullptr);
146 4137 : return type;
147 : }
148 :
149 969 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
150 : {
151 1837826 : 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 8700 : bool from_impl_trait () const { return was_impl_trait; }
161 :
162 : protected:
163 : // Clone function implementation as virtual method
164 47295 : TypeParam *clone_generic_param_impl () const override
165 : {
166 47295 : return new TypeParam (*this);
167 : }
168 : };
169 :
170 : /* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
171 : * TypeBoundWhereClauseItem */
172 6387 : class WhereClauseItem
173 : {
174 : public:
175 : virtual ~WhereClauseItem () {}
176 :
177 : // Unique pointer custom clone function
178 4973 : std::unique_ptr<WhereClauseItem> clone_where_clause_item () const
179 : {
180 4973 : 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 3 : LifetimeWhereClauseItem (Lifetime lifetime,
204 : std::vector<Lifetime> lifetime_bounds,
205 : location_t locus)
206 3 : : lifetime (std::move (lifetime)),
207 3 : lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
208 3 : node_id (Analysis::Mappings::get ().get_next_node_id ())
209 3 : {}
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 258 : Lifetime &get_lifetime () { return lifetime; }
218 :
219 258 : 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 4 : LifetimeWhereClauseItem *clone_where_clause_item_impl () const override
226 : {
227 4 : 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 310 : bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
243 :
244 223402 : 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 1415 : 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 1415 : : for_lifetimes (std::move (for_lifetimes)),
254 1415 : bound_type (std::move (bound_type)),
255 1415 : type_param_bounds (std::move (type_param_bounds)),
256 1415 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
257 1415 : {}
258 :
259 : // Copy constructor requires clone
260 4969 : TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
261 4969 : : for_lifetimes (other.for_lifetimes),
262 4969 : bound_type (other.bound_type->clone_type ())
263 : {
264 4969 : node_id = other.node_id;
265 4969 : type_param_bounds.reserve (other.type_param_bounds.size ());
266 10130 : for (const auto &e : other.type_param_bounds)
267 5161 : type_param_bounds.push_back (e->clone_type_param_bound ());
268 4969 : }
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 244523 : Type &get_type ()
293 : {
294 244523 : rust_assert (bound_type != nullptr);
295 244523 : return *bound_type;
296 : }
297 :
298 77178 : std::unique_ptr<Type> &get_type_ptr ()
299 : {
300 77178 : rust_assert (bound_type != nullptr);
301 77178 : return bound_type;
302 : }
303 :
304 : // TODO: this mutable getter seems really dodgy. Think up better way.
305 310 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
306 : {
307 261600 : 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 149 : NodeId get_node_id () const override final { return node_id; }
317 :
318 149 : location_t get_locus () const { return locus; }
319 :
320 : protected:
321 : // Clone function implementation as (not pure) virtual method
322 4969 : TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
323 : {
324 4969 : return new TypeBoundWhereClauseItem (*this);
325 : }
326 : };
327 :
328 : // A where clause
329 117747 : class WhereClause
330 : {
331 : std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
332 : NodeId node_id;
333 :
334 : public:
335 59072 : WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
336 59072 : : where_clause_items (std::move (where_clause_items)),
337 59072 : node_id (Analysis::Mappings::get ().get_next_node_id ())
338 59072 : {}
339 :
340 : // copy constructor with vector clone
341 216249 : WhereClause (WhereClause const &other)
342 216249 : {
343 216249 : node_id = other.node_id;
344 216249 : where_clause_items.reserve (other.where_clause_items.size ());
345 221222 : for (const auto &e : other.where_clause_items)
346 4973 : where_clause_items.push_back (e->clone_where_clause_item ());
347 216249 : }
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 60492 : WhereClause (WhereClause &&other) = default;
362 : WhereClause &operator= (WhereClause &&other) = default;
363 :
364 : // Creates a WhereClause with no items.
365 57969 : static WhereClause create_empty ()
366 : {
367 57969 : return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
368 : }
369 :
370 : // Returns whether the WhereClause has no items.
371 6080690 : 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 314 : std::vector<std::unique_ptr<WhereClauseItem>> &get_items ()
379 : {
380 219295 : 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 50898 : class Param : public Visitable
390 : {
391 : public:
392 228385 : Param (std::vector<Attribute> outer_attrs, location_t locus)
393 228385 : : outer_attrs (std::move (outer_attrs)), locus (locus),
394 228385 : node_id (Analysis::Mappings::get ().get_next_node_id ())
395 228385 : {}
396 :
397 : virtual ~Param () = default;
398 :
399 169924 : std::unique_ptr<Param> clone_param () const
400 : {
401 169924 : return std::unique_ptr<Param> (clone_param_impl ());
402 : }
403 :
404 933534 : virtual bool is_variadic () const { return false; }
405 :
406 870295 : virtual bool is_self () const { return false; }
407 :
408 11039 : NodeId get_node_id () const { return node_id; }
409 :
410 16339 : location_t get_locus () const { return locus; }
411 :
412 82371 : std::vector<Attribute> get_outer_attrs () const { return outer_attrs; }
413 :
414 1893370 : 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 2788984 : bool has_type () const { return type != nullptr; }
450 :
451 : // Returns whether the self-param has a valid lifetime.
452 1903220 : 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 7093 : SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
470 7093 : : Param ({}, locus), has_ref (false), is_mut (is_mut),
471 7093 : lifetime (tl::nullopt), type (std::move (type))
472 7093 : {}
473 :
474 : // Lifetime-based self parameter (is ref, no type)
475 9377 : SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
476 9377 : : Param ({}, locus), has_ref (true), is_mut (is_mut),
477 9377 : lifetime (std::move (lifetime))
478 9377 : {}
479 :
480 : // Copy constructor requires clone
481 79698 : SelfParam (SelfParam const &other)
482 79698 : : Param (other.get_outer_attrs (), other.get_locus ()),
483 159396 : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime)
484 : {
485 79698 : node_id = other.node_id;
486 79698 : if (other.type != nullptr)
487 44 : type = other.type->clone_type ();
488 79698 : }
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 104194 : location_t get_locus () const { return locus; }
515 :
516 650204 : bool is_self () const override { return true; }
517 :
518 16053 : bool get_has_ref () const { return has_ref; };
519 12983 : bool get_is_mut () const { return is_mut; }
520 :
521 0 : Lifetime get_lifetime () const { return lifetime.value (); }
522 893308 : Lifetime &get_lifetime () { return lifetime.value (); }
523 :
524 24496 : NodeId get_node_id () const { return node_id; }
525 :
526 : // TODO: is this better? Or is a "vis_block" better?
527 3488 : Type &get_type ()
528 : {
529 3488 : rust_assert (has_type ());
530 3488 : return *type;
531 : }
532 :
533 938 : std::unique_ptr<Type> &get_type_ptr ()
534 : {
535 938 : rust_assert (has_type ());
536 938 : return type;
537 : }
538 :
539 : void accept_vis (ASTVisitor &vis) override;
540 :
541 71554 : SelfParam *clone_param_impl () const override
542 : {
543 71554 : return new SelfParam (*this);
544 : }
545 : };
546 :
547 : // Qualifiers for function, i.e. const, unsafe, extern etc.
548 119652 : 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 34225 : 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 34225 : : default_status (default_status), async_status (async_status),
564 34225 : const_status (const_status), unsafe_status (unsafe_status),
565 34225 : has_extern (has_extern), extern_abi (std::move (extern_abi)),
566 34225 : locus (locus)
567 : {
568 34225 : if (!this->extern_abi.empty ())
569 : {
570 : // having extern is required; not having it is an implementation error
571 745 : rust_assert (has_extern);
572 : }
573 34225 : }
574 :
575 : std::string as_string () const;
576 :
577 45431 : bool is_default () const { return default_status == Default::Yes; }
578 36451 : bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; }
579 34742 : bool is_extern () const { return has_extern; }
580 49872 : bool is_const () const { return const_status == Const::Yes; }
581 81486 : bool is_async () const { return async_status == Async::Yes; }
582 300 : std::string get_extern_abi () const { return extern_abi; }
583 16556 : bool has_abi () const { return !extern_abi.empty (); }
584 16486 : Const get_const_status () const { return const_status; }
585 16486 : Async get_async_status () const { return async_status; }
586 :
587 1451 : 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 : : Param (std::move (outer_attrs), std::move (locus)),
598 11 : param_name (std::move (param_name))
599 11 : {}
600 :
601 878 : VariadicParam (std::vector<Attribute> outer_attrs, location_t locus)
602 878 : : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr)
603 878 : {}
604 :
605 2673 : VariadicParam (VariadicParam const &other)
606 2673 : : Param (other.get_outer_attrs (), other.locus)
607 : {
608 2673 : if (other.param_name != nullptr)
609 33 : param_name = other.param_name->clone_pattern ();
610 2673 : }
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 5424 : bool is_variadic () const override { return true; }
626 :
627 1784 : VariadicParam *clone_param_impl () const override
628 : {
629 1784 : return new VariadicParam (*this);
630 : }
631 :
632 185 : Pattern &get_pattern ()
633 : {
634 185 : rust_assert (param_name != nullptr);
635 185 : 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 20086 : 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 25990 : FunctionParam (std::unique_ptr<Pattern> param_name,
665 : std::unique_ptr<Type> param_type,
666 : std::vector<Attribute> outer_attrs, location_t locus)
667 : : Param (std::move (outer_attrs), locus),
668 25990 : param_name (std::move (param_name)), type (std::move (param_type))
669 25990 : {}
670 :
671 : // Copy constructor uses clone
672 102665 : FunctionParam (FunctionParam const &other)
673 102665 : : Param (other.get_outer_attrs (), other.locus)
674 : {
675 : // guard to prevent nullptr dereference
676 102665 : if (other.param_name != nullptr)
677 102665 : param_name = other.param_name->clone_pattern ();
678 102665 : if (other.type != nullptr)
679 102665 : type = other.type->clone_type ();
680 102665 : }
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 25449 : 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 3972089 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
718 102665 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
719 :
720 : // TODO: is this better? Or is a "vis_block" better?
721 3439562 : Pattern &get_pattern ()
722 : {
723 3439562 : rust_assert (param_name != nullptr);
724 3439562 : return *param_name;
725 : }
726 :
727 1081112 : std::unique_ptr<Pattern> &get_pattern_ptr ()
728 : {
729 1081112 : rust_assert (param_name != nullptr);
730 1081112 : return param_name;
731 : }
732 :
733 3143208 : bool has_name () const { return param_name != nullptr; }
734 :
735 : // TODO: is this better? Or is a "vis_block" better?
736 3455693 : Type &get_type ()
737 : {
738 3455693 : rust_assert (type != nullptr);
739 3455693 : return *type;
740 : }
741 :
742 1081373 : std::unique_ptr<Type> &get_type_ptr ()
743 : {
744 1081373 : rust_assert (type != nullptr);
745 1081373 : return type;
746 : }
747 :
748 96586 : FunctionParam *clone_param_impl () const override
749 : {
750 96586 : 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 67318 : 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 3519 : void clone_items (const std::vector<std::unique_ptr<Item>> &other_items)
793 : {
794 3519 : items.reserve (other_items.size ());
795 34597 : for (const auto &e : other_items)
796 31078 : items.push_back (e->clone_item ());
797 3519 : }
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 289 : 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 : : VisItem (std::move (visibility), std::move (outer_attrs)),
811 289 : module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
812 289 : safety (safety), outer_filename (outer_filename),
813 289 : inner_attrs (std::vector<Attribute> ()),
814 289 : items (std::vector<std::unique_ptr<Item>> ()),
815 289 : module_scope (std::move (module_scope))
816 289 : {}
817 :
818 : // Loaded module constructor, with items
819 1333 : 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 : : VisItem (std::move (visibility), std::move (outer_attrs)),
826 1333 : module_name (name), locus (locus), kind (ModuleKind::LOADED),
827 1333 : safety (safety), outer_filename (std::string ()),
828 1333 : inner_attrs (std::move (inner_attrs)), items (std::move (items))
829 1333 : {}
830 :
831 : // Copy constructor with vector clone
832 3689 : Module (Module const &other)
833 3689 : : VisItem (other), module_name (other.module_name), locus (other.locus),
834 3689 : kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs),
835 3689 : 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 3689 : if (other.kind == LOADED)
840 3519 : clone_items (other.items);
841 : else
842 170 : items.clear ();
843 3689 : }
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 12654 : enum ModuleKind get_kind () const { return kind; }
880 :
881 1551 : 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 74719 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
886 :
887 : const std::vector<std::unique_ptr<Item>> &get_items () const { return items; }
888 87514 : 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 15306 : location_t get_locus () const override final { return locus; }
907 :
908 : // Invalid if name is empty, so base stripping on that.
909 134 : void mark_for_strip () override { module_name = {""}; }
910 11574 : bool is_marked_for_strip () const override { return module_name.empty (); }
911 :
912 256 : 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 2138 : Module *clone_item_impl () const override { return new Module (*this); }
918 :
919 13648 : GlobContainer::Kind get_glob_container_kind () const override
920 : {
921 13648 : 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 565 : 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 173 : bool references_self () const { return referenced_crate == "self"; }
950 :
951 : // Constructor
952 68 : 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 : : VisItem (std::move (visibility), std::move (outer_attrs)),
956 68 : referenced_crate (std::move (referenced_crate)),
957 68 : as_clause_name (std::move (as_clause_name)), locus (locus)
958 68 : {}
959 :
960 363 : location_t get_locus () const override final { return locus; }
961 :
962 : void accept_vis (ASTVisitor &vis) override;
963 :
964 990 : const std::string &get_referenced_crate () const { return referenced_crate; }
965 82 : 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 133 : bool is_marked_for_strip () const override
976 : {
977 133 : 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 65 : ExternCrate *clone_item_impl () const override
986 : {
987 65 : 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 991 : 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 7106 : std::unique_ptr<UseTree> clone_use_tree () const
1023 : {
1024 7106 : 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 17 : location_t get_locus () const { return locus; }
1031 961 : 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 2899 : UseTree (location_t locus)
1040 2899 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1041 2899 : {}
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 193 : UseTreeGlob (PathType glob_type, SimplePath path, location_t locus)
1061 193 : : UseTree (locus), glob_type (glob_type), path (std::move (path))
1062 : {
1063 193 : 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 193 : }
1072 :
1073 : /* Returns whether has path. Should be made redundant by PathType
1074 : * PATH_PREFIXED. */
1075 3957 : 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 26 : PathType get_glob_type () const { return glob_type; }
1082 :
1083 6267 : Kind get_kind () const override { return Glob; }
1084 :
1085 3945 : SimplePath get_path () const
1086 : {
1087 3945 : rust_assert (has_path ());
1088 3945 : return path;
1089 : }
1090 :
1091 7459 : 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 430 : UseTreeGlob *clone_use_tree_impl () const override
1099 : {
1100 430 : 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 410 : UseTreeList (PathType path_type, SimplePath path,
1123 : std::vector<std::unique_ptr<UseTree>> trees, location_t locus)
1124 410 : : UseTree (locus), path_type (path_type), path (std::move (path)),
1125 410 : trees (std::move (trees))
1126 : {
1127 410 : 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 410 : }
1136 :
1137 : // copy constructor with vector clone
1138 991 : UseTreeList (UseTreeList const &other)
1139 991 : : UseTree (other), path_type (other.path_type), path (other.path)
1140 : {
1141 991 : trees.reserve (other.trees.size ());
1142 4258 : for (const auto &e : other.trees)
1143 3267 : trees.push_back (e->clone_use_tree ());
1144 991 : }
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 16277 : bool has_path () const { return !path.is_empty (); }
1166 :
1167 : // Returns whether has inner tree elements.
1168 156 : bool has_trees () const { return !trees.empty (); }
1169 :
1170 : std::string as_string () const override;
1171 :
1172 156 : PathType get_path_type () { return path_type; }
1173 :
1174 : void accept_vis (ASTVisitor &vis) override;
1175 :
1176 16275 : Kind get_kind () const override { return List; }
1177 8763 : SimplePath get_path () const
1178 : {
1179 8763 : rust_assert (has_path ());
1180 8763 : return path;
1181 : }
1182 :
1183 25230 : SimplePath &get_path () { return path; }
1184 :
1185 160 : std::vector<std::unique_ptr<UseTree>> &get_trees () { return trees; }
1186 :
1187 : const std::vector<std::unique_ptr<UseTree>> &get_trees () const
1188 : {
1189 8767 : 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 991 : UseTreeList *clone_use_tree_impl () const override
1198 : {
1199 991 : 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 2296 : UseTreeRebind (NewBindType bind_type, SimplePath path, location_t locus,
1222 : Identifier identifier = std::string ())
1223 2296 : : UseTree (locus), path (std::move (path)), bind_type (bind_type),
1224 2296 : identifier (std::move (identifier))
1225 2296 : {}
1226 :
1227 : // Returns whether has path (this should always be true).
1228 41964 : bool has_path () const { return !path.is_empty (); }
1229 :
1230 : // Returns whether has identifier (or, rather, is allowed to).
1231 395 : bool has_identifier () const { return bind_type == IDENTIFIER; }
1232 :
1233 : std::string as_string () const override;
1234 :
1235 48411 : NewBindType get_new_bind_type () const { return bind_type; }
1236 :
1237 : void accept_vis (ASTVisitor &vis) override;
1238 :
1239 57713 : Kind get_kind () const override { return Rebind; }
1240 :
1241 41964 : const SimplePath &get_path () const
1242 : {
1243 41964 : rust_assert (has_path ());
1244 41964 : return path;
1245 : }
1246 :
1247 69976 : SimplePath &get_path () { return path; }
1248 :
1249 395 : const Identifier &get_identifier () const
1250 : {
1251 395 : rust_assert (has_identifier ());
1252 395 : 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 5685 : virtual UseTreeRebind *clone_use_tree_impl () const override
1261 : {
1262 5685 : 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 1540 : UseDeclaration (std::unique_ptr<UseTree> use_tree, Visibility visibility,
1276 : std::vector<Attribute> outer_attrs, location_t locus)
1277 : : VisItem (std::move (visibility), std::move (outer_attrs)),
1278 1540 : use_tree (std::move (use_tree)), locus (locus)
1279 1540 : {}
1280 :
1281 : // Copy constructor with clone
1282 3839 : UseDeclaration (UseDeclaration const &other)
1283 3839 : : VisItem (other), locus (other.locus)
1284 : {
1285 : // guard to prevent null dereference (only required if error state)
1286 3839 : if (other.use_tree != nullptr)
1287 3839 : use_tree = other.use_tree->clone_use_tree ();
1288 3839 : }
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 689 : location_t get_locus () const override final { return locus; }
1312 :
1313 155887 : 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 46 : void mark_for_strip () override { use_tree = nullptr; }
1321 26844 : bool is_marked_for_strip () const override { return use_tree == nullptr; }
1322 :
1323 190 : Item::Kind get_item_kind () const override
1324 : {
1325 190 : return Item::Kind::UseDeclaration;
1326 : }
1327 :
1328 : protected:
1329 : /* Use covariance to implement clone function as returning this object
1330 : * rather than base */
1331 2459 : UseDeclaration *clone_item_impl () const override
1332 : {
1333 2459 : 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 37171 : bool has_generics () const { return !generic_params.empty (); }
1357 :
1358 : // Returns whether function has regular parameters.
1359 31381 : bool has_function_params () const { return !function_params.empty (); }
1360 :
1361 : // Returns whether function has return type - if not, it is void.
1362 4201817 : bool has_return_type () const { return return_type != nullptr; }
1363 :
1364 : // Returns whether function has a where clause.
1365 3379682 : bool has_where_clause () const { return !where_clause.is_empty (); }
1366 :
1367 32845 : bool has_self_param () const
1368 : {
1369 32845 : return function_params.size () > 0 && function_params[0]->is_self ();
1370 : }
1371 :
1372 4795610 : bool has_body () const { return function_body.has_value (); }
1373 :
1374 13816 : bool is_default () const { return qualifiers.is_default (); }
1375 :
1376 : // Mega-constructor with all possible fields
1377 33490 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
1385 33490 : ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
1386 33490 : function_name (std::move (function_name)),
1387 33490 : generic_params (std::move (generic_params)),
1388 33490 : function_params (std::move (function_params)),
1389 33490 : return_type (std::move (return_type)),
1390 33490 : where_clause (std::move (where_clause)),
1391 33490 : function_body (std::move (function_body)), locus (locus),
1392 33490 : is_external_function (is_external_function)
1393 33490 : {}
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 542878 : location_t get_locus () const override final { return locus; }
1408 :
1409 : void accept_vis (ASTVisitor &vis) override;
1410 :
1411 3454 : bool is_variadic () const
1412 : {
1413 3454 : return function_params.size () != 0
1414 3454 : && function_params.back ()->is_variadic ();
1415 : }
1416 :
1417 63230 : bool is_external () const { return is_external_function; }
1418 :
1419 : // Invalid if block is null, so base stripping on that.
1420 49 : void mark_for_strip () override { function_body = nullptr; }
1421 480688 : bool is_marked_for_strip () const override
1422 : {
1423 480688 : return function_body == nullptr;
1424 : }
1425 :
1426 1281260 : std::vector<std::unique_ptr<Param>> &get_function_params ()
1427 : {
1428 4301562 : return function_params;
1429 : }
1430 : const std::vector<std::unique_ptr<Param>> &get_function_params () const
1431 : {
1432 : return function_params;
1433 : }
1434 :
1435 3536 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1436 : {
1437 3365041 : 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 4238407 : tl::optional<std::unique_ptr<BlockExpr>> &get_definition ()
1446 : {
1447 4238407 : return function_body;
1448 : }
1449 :
1450 : const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
1451 :
1452 2967776 : FunctionQualifiers &get_qualifiers () { return qualifiers; }
1453 :
1454 2490339 : Identifier get_function_name () const { return function_name; }
1455 :
1456 : // TODO: is this better? Or is a "vis_block" better?
1457 110555 : WhereClause &get_where_clause () { return where_clause; }
1458 :
1459 : // TODO: is this better? Or is a "vis_block" better?
1460 2760655 : Type &get_return_type ()
1461 : {
1462 2760655 : rust_assert (has_return_type ());
1463 2760655 : return *return_type;
1464 : }
1465 :
1466 811927 : std::unique_ptr<Type> &get_return_type_ptr ()
1467 : {
1468 811927 : rust_assert (has_return_type ());
1469 811927 : return return_type;
1470 : }
1471 :
1472 8145 : Param &get_self_param ()
1473 : {
1474 8145 : rust_assert (has_self_param ());
1475 8145 : 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 3541772 : NodeId get_node_id () const override { return Stmt::node_id; }
1485 :
1486 61716 : 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 13352 : 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 83370 : Function *clone_associated_item_impl () const override
1496 : {
1497 83370 : return new Function (*this);
1498 : }
1499 :
1500 : /* Use covariance to implement clone function as returning this object
1501 : * rather than base */
1502 8607 : Function *clone_external_item_impl () const override
1503 : {
1504 8607 : 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 2494 : bool has_generics () const { return !generic_params.empty (); }
1529 :
1530 : // Returns whether type alias has a where clause.
1531 659847 : bool has_where_clause () const { return !where_clause.is_empty (); }
1532 :
1533 : // Mega-constructor with all possible fields
1534 3996 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
1540 3996 : new_type_name (std::move (new_type_name)),
1541 3996 : generic_params (std::move (generic_params)),
1542 3996 : where_clause (std::move (where_clause)),
1543 3996 : existing_type (std::move (existing_type)), locus (locus)
1544 3996 : {}
1545 :
1546 : // Copy constructor
1547 26178 : TypeAlias (TypeAlias const &other)
1548 26178 : : VisItem (other), new_type_name (other.new_type_name),
1549 26178 : where_clause (other.where_clause), locus (other.locus)
1550 : {
1551 : // guard to prevent null dereference (only required if error state)
1552 26178 : if (other.existing_type != nullptr)
1553 26178 : existing_type = other.existing_type->clone_type ();
1554 :
1555 26178 : generic_params.reserve (other.generic_params.size ());
1556 26250 : for (const auto &e : other.generic_params)
1557 72 : generic_params.push_back (e->clone_generic_param ());
1558 26178 : }
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 95996 : location_t get_locus () const override final { return locus; }
1588 :
1589 : // needed to override AssociatedItem::get_node_id
1590 558154 : 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 90721 : bool is_marked_for_strip () const override
1597 : {
1598 90721 : return existing_type == nullptr;
1599 : }
1600 :
1601 46 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1602 : {
1603 658655 : 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 656734 : Type &get_type_aliased ()
1615 : {
1616 656734 : rust_assert (existing_type != nullptr);
1617 656734 : return *existing_type;
1618 : }
1619 :
1620 182968 : std::unique_ptr<Type> &get_type_aliased_ptr ()
1621 : {
1622 182968 : rust_assert (existing_type != nullptr);
1623 182968 : return existing_type;
1624 : }
1625 :
1626 469756 : Identifier get_new_type_name () const { return new_type_name; }
1627 :
1628 41 : 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 163 : 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 22034 : TypeAlias *clone_associated_item_impl () const override
1638 : {
1639 22034 : 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 5124 : bool has_generics () const { return !generic_params.empty (); }
1663 :
1664 : // Returns whether struct has a where clause.
1665 300004 : bool has_where_clause () const { return !where_clause.is_empty (); }
1666 :
1667 60264 : location_t get_locus () const override final { return locus; }
1668 :
1669 : // Invalid if name is empty, so base stripping on that.
1670 14 : void mark_for_strip () override { struct_name = {""}; }
1671 66706 : bool is_marked_for_strip () const override { return struct_name.empty (); }
1672 :
1673 186730 : Identifier get_struct_name () const { return struct_name; }
1674 :
1675 2469 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1676 : {
1677 300004 : 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 2662 : WhereClause &get_where_clause () { return where_clause; }
1686 :
1687 5659 : Identifier get_identifier () const { return struct_name; }
1688 :
1689 4965 : Item::Kind get_item_kind () const override { return Item::Kind::Struct; }
1690 :
1691 : protected:
1692 3646 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
1697 7292 : struct_name (std::move (struct_name)),
1698 3646 : generic_params (std::move (generic_params)),
1699 3646 : where_clause (std::move (where_clause)), locus (locus)
1700 3646 : {}
1701 :
1702 : // Copy constructor with vector clone
1703 10286 : Struct (Struct const &other)
1704 10286 : : VisItem (other), struct_name (other.struct_name),
1705 10286 : where_clause (other.where_clause), locus (other.locus)
1706 : {
1707 10286 : generic_params.reserve (other.generic_params.size ());
1708 13308 : for (const auto &e : other.generic_params)
1709 3022 : generic_params.push_back (e->clone_generic_param ());
1710 10286 : }
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 2916 : 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 2916 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1759 2916 : field_name (std::move (field_name)), field_type (std::move (field_type)),
1760 2916 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
1761 2916 : {}
1762 :
1763 : // Copy constructor
1764 6379 : StructField (StructField const &other)
1765 6379 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
1766 6379 : field_name (other.field_name), node_id (other.node_id),
1767 6379 : locus (other.locus)
1768 : {
1769 : // guard to prevent null dereference
1770 6379 : if (other.field_type != nullptr)
1771 6379 : field_type = other.field_type->clone_type ();
1772 6379 : }
1773 :
1774 10838 : ~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 4373 : StructField (StructField &&other) = default;
1795 2 : StructField &operator= (StructField &&other) = default;
1796 :
1797 : // Returns whether struct field is in an error state.
1798 2809 : bool is_error () const
1799 : {
1800 2809 : 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 56 : static StructField create_error ()
1806 : {
1807 112 : return StructField (std::string (""), nullptr,
1808 168 : 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 175627 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1815 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1816 :
1817 5232 : Identifier get_field_name () const { return field_name; }
1818 :
1819 4659 : location_t get_locus () const { return locus; }
1820 :
1821 : // TODO: is this better? Or is a "vis_block" better?
1822 137655 : Type &get_field_type ()
1823 : {
1824 137655 : rust_assert (field_type != nullptr);
1825 137655 : return *field_type;
1826 : }
1827 :
1828 40358 : std::unique_ptr<Type> &get_field_type_ptr ()
1829 : {
1830 40358 : rust_assert (field_type != nullptr);
1831 40358 : return field_type;
1832 : }
1833 :
1834 150070 : Visibility &get_visibility () { return visibility; }
1835 : const Visibility &get_visibility () const { return visibility; }
1836 :
1837 2411 : 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 1330 : 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 : : Struct (std::move (struct_name), std::move (generic_params),
1855 : std::move (where_clause), std::move (vis), locus,
1856 : std::move (outer_attrs)),
1857 1330 : fields (std::move (fields)), is_unit (is_unit)
1858 1330 : {}
1859 :
1860 : // Unit struct constructor
1861 1197 : 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 : : Struct (std::move (struct_name), std::move (generic_params),
1866 : std::move (where_clause), std::move (vis), locus,
1867 : std::move (outer_attrs)),
1868 1197 : is_unit (true)
1869 1197 : {}
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 29476 : 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 369011 : 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 5230 : StructStruct *clone_item_impl () const override
1886 : {
1887 5230 : 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 2716 : TupleField (std::unique_ptr<Type> field_type, Visibility vis,
1916 : location_t locus,
1917 : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1918 2716 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1919 2716 : field_type (std::move (field_type)),
1920 2716 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
1921 2716 : {}
1922 :
1923 : // Copy constructor with clone
1924 8029 : TupleField (TupleField const &other)
1925 8029 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
1926 8029 : node_id (other.node_id), locus (other.locus)
1927 : {
1928 : // guard to prevent null dereference (only required if error)
1929 8029 : if (other.field_type != nullptr)
1930 8029 : field_type = other.field_type->clone_type ();
1931 8029 : }
1932 :
1933 12038 : ~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 3993 : TupleField (TupleField &&other) = default;
1954 0 : TupleField &operator= (TupleField &&other) = default;
1955 :
1956 : // Returns whether tuple field is in an error state.
1957 2716 : 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 2154 : NodeId get_node_id () const { return node_id; }
1968 :
1969 157283 : Visibility &get_visibility () { return visibility; }
1970 : const Visibility &get_visibility () const { return visibility; }
1971 :
1972 2154 : location_t get_locus () const { return locus; }
1973 :
1974 : // TODO: this mutable getter seems really dodgy. Think up better way.
1975 183063 : 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 138710 : Type &get_field_type ()
1980 : {
1981 138710 : rust_assert (field_type != nullptr);
1982 138710 : return *field_type;
1983 : }
1984 :
1985 46112 : std::unique_ptr<Type> &get_field_type_ptr ()
1986 : {
1987 46112 : rust_assert (field_type != nullptr);
1988 46112 : 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 1119 : 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 : : Struct (std::move (struct_name), std::move (generic_params),
2006 : std::move (where_clause), std::move (vis), locus,
2007 : std::move (outer_attrs)),
2008 1119 : fields (std::move (fields))
2009 1119 : {}
2010 :
2011 : void accept_vis (ASTVisitor &vis) override;
2012 :
2013 : // TODO: this mutable getter seems really dodgy. Think up better way.
2014 52120 : 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 1599 : TupleStruct *clone_item_impl () const override
2021 : {
2022 1599 : 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 4971 : virtual ~EnumItem () {}
2072 :
2073 1410 : EnumItem (Identifier variant_name, Visibility vis,
2074 : std::vector<Attribute> outer_attrs, location_t locus)
2075 : : VisItem (std::move (vis), std::move (outer_attrs)),
2076 1410 : variant_name (std::move (variant_name)), locus (locus)
2077 1410 : {}
2078 :
2079 195 : virtual Kind get_enum_item_kind () const { return Kind::Identifier; }
2080 :
2081 : // Unique pointer custom clone function
2082 3650 : std::unique_ptr<EnumItem> clone_enum_item () const
2083 : {
2084 3650 : 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 10069 : location_t get_locus () const override { return locus; }
2093 :
2094 25634 : 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 7580 : 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 1315 : 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 477 : EnumItemTuple (Identifier variant_name, Visibility vis,
2117 : std::vector<TupleField> tuple_fields,
2118 : std::vector<Attribute> outer_attrs, location_t locus)
2119 : : EnumItem (std::move (variant_name), std::move (vis),
2120 : std::move (outer_attrs), locus),
2121 477 : tuple_fields (std::move (tuple_fields))
2122 477 : {}
2123 :
2124 136 : EnumItem::Kind get_enum_item_kind () const override
2125 : {
2126 136 : 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 19610 : 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 1198 : EnumItemTuple *clone_item_impl () const override
2143 : {
2144 1198 : 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 : : 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 2529 : 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 290 : EnumItemDiscriminant (Identifier variant_name, Visibility vis,
2197 : std::unique_ptr<Expr> expr,
2198 : std::vector<Attribute> outer_attrs, location_t locus)
2199 : : EnumItem (std::move (variant_name), std::move (vis),
2200 : std::move (outer_attrs), locus),
2201 290 : expression (std::move (expr))
2202 290 : {}
2203 :
2204 : // Copy constructor with clone
2205 947 : EnumItemDiscriminant (EnumItemDiscriminant const &other)
2206 947 : : EnumItem (other), expression (other.expression->clone_expr ())
2207 947 : {}
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 9 : EnumItem::Kind get_enum_item_kind () const override
2225 : {
2226 9 : 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 8543 : Expr &get_expr ()
2237 : {
2238 8543 : rust_assert (expression != nullptr);
2239 8543 : return *expression;
2240 : }
2241 :
2242 1886 : std::unique_ptr<Expr> &get_expr_ptr ()
2243 : {
2244 1886 : rust_assert (expression != nullptr);
2245 1886 : return expression;
2246 : }
2247 :
2248 : protected:
2249 : // Clone function implementation as (not pure) virtual method
2250 947 : EnumItemDiscriminant *clone_item_impl () const override
2251 : {
2252 947 : 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 1047 : bool has_generics () const { return !generic_params.empty (); }
2277 :
2278 : // Returns whether "enum" has a where clause.
2279 20315 : 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 604 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
2291 604 : enum_name (std::move (enum_name)),
2292 604 : generic_params (std::move (generic_params)),
2293 604 : where_clause (std::move (where_clause)), items (std::move (items)),
2294 604 : locus (locus)
2295 604 : {}
2296 :
2297 : // TODO: constructor with less arguments
2298 :
2299 : // Copy constructor with vector clone
2300 1550 : Enum (Enum const &other)
2301 1550 : : VisItem (other), enum_name (other.enum_name),
2302 1550 : where_clause (other.where_clause), locus (other.locus)
2303 : {
2304 1550 : generic_params.reserve (other.generic_params.size ());
2305 2358 : for (const auto &e : other.generic_params)
2306 808 : generic_params.push_back (e->clone_generic_param ());
2307 :
2308 1550 : items.reserve (other.items.size ());
2309 5200 : for (const auto &e : other.items)
2310 3650 : items.push_back (e->clone_enum_item ());
2311 1550 : }
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 4256 : location_t get_locus () const override final { return locus; }
2337 :
2338 : void accept_vis (ASTVisitor &vis) override;
2339 :
2340 16333 : 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 2415 : 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 23445 : 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 628 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2354 : {
2355 20444 : 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 513 : Item::Kind get_item_kind () const override { return Item::Kind::Enum; }
2366 :
2367 1208 : GlobContainer::Kind get_glob_container_kind () const override
2368 : {
2369 1208 : return GlobContainer::Kind::Enum;
2370 : }
2371 :
2372 : protected:
2373 : /* Use covariance to implement clone function as returning this object
2374 : * rather than base */
2375 949 : 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 208 : bool has_generics () const { return !generic_params.empty (); }
2399 :
2400 : // Returns whether union has where clause.
2401 2914 : bool has_where_clause () const { return !where_clause.is_empty (); }
2402 :
2403 114 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
2408 228 : union_name (std::move (union_name)),
2409 114 : generic_params (std::move (generic_params)),
2410 114 : where_clause (std::move (where_clause)), variants (std::move (variants)),
2411 114 : locus (locus)
2412 114 : {}
2413 :
2414 : // copy constructor with vector clone
2415 236 : Union (Union const &other)
2416 236 : : VisItem (other), union_name (other.union_name),
2417 236 : where_clause (other.where_clause), variants (other.variants),
2418 236 : locus (other.locus)
2419 : {
2420 236 : generic_params.reserve (other.generic_params.size ());
2421 403 : for (const auto &e : other.generic_params)
2422 167 : generic_params.push_back (e->clone_generic_param ());
2423 236 : }
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 645 : 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 300 : 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 3437 : std::vector<StructField> &get_variants () { return variants; }
2455 : const std::vector<StructField> &get_variants () const { return variants; }
2456 :
2457 152 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2458 : {
2459 2965 : 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 2272 : Identifier get_identifier () const { return union_name; }
2470 :
2471 263 : 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 122 : 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 1326 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
2500 1326 : identifier (std::move (ident)), type (std::move (type)),
2501 1326 : const_expr (std::move (const_expr)), locus (locus)
2502 1326 : {}
2503 :
2504 4 : ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
2505 : std::vector<Attribute> outer_attrs, location_t locus)
2506 : : 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 4426 : ConstantItem (ConstantItem const &other)
2512 4426 : : VisItem (other), identifier (other.identifier), locus (other.locus)
2513 : {
2514 : // guard to prevent null dereference (only required if error state)
2515 4426 : if (other.type != nullptr)
2516 4426 : type = other.type->clone_type ();
2517 4426 : if (other.const_expr != nullptr)
2518 4235 : const_expr = other.const_expr->clone_expr ();
2519 4426 : }
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 542 : bool is_unnamed () const { return identifier.as_string () == "_"; }
2548 :
2549 28180 : location_t get_locus () const override final { return locus; }
2550 :
2551 : // needed to override AssociatedItem::get_node_id
2552 108047 : 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 1 : void mark_for_strip () override
2558 : {
2559 1 : type = nullptr;
2560 1 : const_expr = nullptr;
2561 1 : }
2562 26287 : bool is_marked_for_strip () const override
2563 : {
2564 26287 : return type == nullptr && const_expr == nullptr;
2565 : }
2566 :
2567 208980 : bool has_expr () const { return const_expr != nullptr; }
2568 :
2569 : // TODO: is this better? Or is a "vis_block" better?
2570 149540 : Expr &get_expr ()
2571 : {
2572 149540 : rust_assert (const_expr != nullptr);
2573 149540 : return *const_expr;
2574 : }
2575 :
2576 51070 : std::unique_ptr<Expr> &get_expr_ptr ()
2577 : {
2578 51070 : rust_assert (const_expr != nullptr);
2579 51070 : return const_expr;
2580 : }
2581 :
2582 : // TODO: is this better? Or is a "vis_block" better?
2583 155142 : Type &get_type ()
2584 : {
2585 155142 : rust_assert (type != nullptr);
2586 155142 : return *type;
2587 : }
2588 :
2589 52593 : std::unique_ptr<Type> &get_type_ptr ()
2590 : {
2591 52593 : rust_assert (type != nullptr);
2592 52593 : return type;
2593 : }
2594 :
2595 81980 : const Identifier &get_identifier () const { return identifier; }
2596 :
2597 1100 : Item::Kind get_item_kind () const override
2598 : {
2599 1100 : return Item::Kind::ConstantItem;
2600 : }
2601 :
2602 : protected:
2603 : /* Use covariance to implement clone function as returning this object
2604 : * rather than base */
2605 2034 : ConstantItem *clone_item_impl () const override
2606 : {
2607 2034 : return new ConstantItem (*this);
2608 : }
2609 :
2610 : /* Use covariance to implement clone function as returning this object
2611 : * rather than base */
2612 1076 : ConstantItem *clone_associated_item_impl () const override
2613 : {
2614 1076 : 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 107 : 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 107 : : VisItem (std::move (vis), std::move (outer_attrs)), has_mut (is_mut),
2635 214 : name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
2636 107 : locus (locus)
2637 107 : {}
2638 :
2639 : // Copy constructor with clone
2640 178 : StaticItem (StaticItem const &other)
2641 178 : : VisItem (other), has_mut (other.has_mut), name (other.name),
2642 178 : locus (other.locus)
2643 : {
2644 : // guard to prevent null dereference (only required if error state)
2645 178 : if (other.type != nullptr)
2646 178 : type = other.type->clone_type ();
2647 178 : if (other.expr != nullptr)
2648 178 : expr = other.expr->clone_expr ();
2649 178 : }
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 1594 : 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 1363 : bool is_marked_for_strip () const override
2687 : {
2688 1363 : return type == nullptr && expr == nullptr;
2689 : }
2690 :
2691 52 : bool has_expr () { return expr != nullptr; }
2692 :
2693 : // TODO: is this better? Or is a "vis_block" better?
2694 7730 : Expr &get_expr ()
2695 : {
2696 7730 : rust_assert (expr != nullptr);
2697 7730 : return *expr;
2698 : }
2699 :
2700 2824 : std::unique_ptr<Expr> &get_expr_ptr ()
2701 : {
2702 2824 : rust_assert (expr != nullptr);
2703 2824 : return expr;
2704 : }
2705 :
2706 : // TODO: is this better? Or is a "vis_block" better?
2707 7730 : Type &get_type ()
2708 : {
2709 7730 : rust_assert (type != nullptr);
2710 7730 : return *type;
2711 : }
2712 :
2713 2824 : std::unique_ptr<Type> &get_type_ptr ()
2714 : {
2715 2824 : rust_assert (type != nullptr);
2716 2824 : return type;
2717 : }
2718 :
2719 109 : bool is_mutable () const { return has_mut; }
2720 :
2721 4506 : Identifier get_identifier () const { return name; }
2722 :
2723 16 : 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 178 : StaticItem *clone_item_impl () const override
2729 : {
2730 178 : 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 790 : 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 790 : : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
2761 790 : name (std::move (name)), generic_params (std::move (generic_params)),
2762 790 : type_param_bounds (std::move (type_param_bounds))
2763 790 : {}
2764 :
2765 : // Copy constructor with vector clone
2766 1767 : TraitItemType (TraitItemType const &other)
2767 3534 : : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2768 1767 : name (other.name)
2769 : {
2770 1767 : node_id = other.node_id;
2771 1767 : generic_params.reserve (other.generic_params.size ());
2772 1803 : for (const auto &e : other.generic_params)
2773 36 : generic_params.push_back (e->clone_generic_param ());
2774 1767 : type_param_bounds.reserve (other.type_param_bounds.size ());
2775 1900 : for (const auto &e : other.type_param_bounds)
2776 133 : type_param_bounds.push_back (e->clone_type_param_bound ());
2777 1767 : }
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 3891 : bool is_marked_for_strip () const override { return name.empty (); }
2809 :
2810 : // TODO: this mutable getter seems really dodgy. Think up better way.
2811 37543 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2812 788 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2813 :
2814 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2815 : {
2816 29755 : 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 29755 : 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 5383 : Identifier get_identifier () const { return name; }
2834 :
2835 : protected:
2836 : // Clone function implementation as (not pure) virtual method
2837 1767 : TraitItemType *clone_associated_item_impl () const override
2838 : {
2839 1767 : 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 7807 : bool has_generics () const { return !generic_params.empty (); }
2862 :
2863 : // Returns whether trait has type parameter bounds.
2864 4042 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2865 :
2866 : // Returns whether trait has where clause.
2867 125448 : bool has_where_clause () const { return !where_clause.is_empty (); }
2868 :
2869 : // Returns whether trait has trait items.
2870 27 : 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 98601 : Identifier get_identifier () const { return name; }
2876 :
2877 4015 : bool is_unsafe () const { return has_unsafe; }
2878 12405 : bool is_auto () const { return has_auto; }
2879 :
2880 : // Mega-constructor
2881 4231 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
2889 8462 : has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)),
2890 8462 : generic_params (std::move (generic_params)), self_param ({"Self"}, locus),
2891 4231 : type_param_bounds (std::move (type_param_bounds)),
2892 4231 : where_clause (std::move (where_clause)),
2893 4231 : inner_attrs (std::move (inner_attrs)),
2894 4231 : trait_items (std::move (trait_items)), locus (locus)
2895 4231 : {}
2896 :
2897 : // Copy constructor with vector clone
2898 9609 : Trait (Trait const &other)
2899 9609 : : VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto),
2900 9609 : name (other.name), self_param (other.self_param),
2901 9609 : where_clause (other.where_clause), inner_attrs (other.inner_attrs),
2902 19218 : locus (other.locus)
2903 : {
2904 9609 : generic_params.reserve (other.generic_params.size ());
2905 11415 : for (const auto &e : other.generic_params)
2906 1806 : generic_params.push_back (e->clone_generic_param ());
2907 :
2908 9609 : type_param_bounds.reserve (other.type_param_bounds.size ());
2909 11527 : for (const auto &e : other.type_param_bounds)
2910 1918 : type_param_bounds.push_back (e->clone_type_param_bound ());
2911 :
2912 9609 : trait_items.reserve (other.trait_items.size ());
2913 19208 : for (const auto &e : other.trait_items)
2914 9599 : trait_items.push_back (e->clone_associated_item ());
2915 9609 : }
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 29485 : 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 13954 : 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 125479 : 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 31680 : std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items ()
2965 : {
2966 147202 : return trait_items;
2967 : }
2968 :
2969 1250 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2970 : {
2971 126698 : return generic_params;
2972 : }
2973 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2974 : {
2975 : return generic_params;
2976 : }
2977 :
2978 3765 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
2979 : {
2980 130863 : 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 196 : WhereClause &get_where_clause () { return where_clause; }
2989 :
2990 111506 : AST::TypeParam &get_implicit_self () { return self_param; }
2991 :
2992 8674 : 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 5414 : 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 5763 : bool has_generics () const { return !generic_params.empty (); }
3024 :
3025 : // Returns whether impl has where clause.
3026 1592480 : 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 11302 : location_t get_locus () const override final { return locus; }
3032 :
3033 : // Invalid if trait type is null, so base stripping on that.
3034 19 : void mark_for_strip () override { trait_type = nullptr; }
3035 246152 : 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 1839146 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3040 :
3041 6458 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3042 : {
3043 1593484 : 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 79032 : WhereClause &get_where_clause () { return where_clause; }
3052 :
3053 : // TODO: is this better? Or is a "vis_block" better?
3054 1614676 : Type &get_type ()
3055 : {
3056 1614676 : rust_assert (trait_type != nullptr);
3057 1614676 : return *trait_type;
3058 : }
3059 :
3060 506362 : std::unique_ptr<Type> &get_type_ptr ()
3061 : {
3062 506362 : rust_assert (trait_type != nullptr);
3063 506362 : return trait_type;
3064 : }
3065 :
3066 6538 : Item::Kind get_item_kind () const override { return Item::Kind::Impl; }
3067 :
3068 : protected:
3069 : // Mega-constructor
3070 12944 : 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 : : VisItem (std::move (vis), std::move (outer_attrs)),
3075 12944 : generic_params (std::move (generic_params)),
3076 12944 : trait_type (std::move (trait_type)),
3077 12944 : where_clause (std::move (where_clause)),
3078 12944 : inner_attrs (std::move (inner_attrs)), locus (locus)
3079 12944 : {}
3080 :
3081 : // Copy constructor
3082 61028 : Impl (Impl const &other)
3083 61028 : : VisItem (other), where_clause (other.where_clause),
3084 61028 : inner_attrs (other.inner_attrs), locus (other.locus)
3085 : {
3086 : // guard to prevent null dereference (only required if error state)
3087 61028 : if (other.trait_type != nullptr)
3088 61028 : trait_type = other.trait_type->clone_type ();
3089 :
3090 61028 : generic_params.reserve (other.generic_params.size ());
3091 100643 : for (const auto &e : other.generic_params)
3092 39615 : generic_params.push_back (e->clone_generic_param ());
3093 61028 : }
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 1316 : 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 : : 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 1316 : impl_items (std::move (impl_items))
3143 1316 : {}
3144 :
3145 : // Copy constructor with vector clone
3146 3980 : InherentImpl (InherentImpl const &other) : Impl (other)
3147 : {
3148 3980 : impl_items.reserve (other.impl_items.size ());
3149 21678 : for (const auto &e : other.impl_items)
3150 17698 : impl_items.push_back (e->clone_associated_item ());
3151 3980 : }
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 25683 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3177 : {
3178 100514 : return impl_items;
3179 : }
3180 :
3181 : protected:
3182 : /* Use covariance to implement clone function as returning this object
3183 : * rather than base */
3184 2676 : InherentImpl *clone_item_impl () const override
3185 : {
3186 2676 : 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 11628 : 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 : : 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 11628 : has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path),
3217 11628 : impl_items (std::move (impl_items))
3218 11628 : {}
3219 :
3220 : // Copy constructor with vector clone
3221 57048 : TraitImpl (TraitImpl const &other)
3222 57048 : : Impl (other), has_unsafe (other.has_unsafe),
3223 57048 : has_exclam (other.has_exclam), trait_path (other.trait_path)
3224 : {
3225 57048 : impl_items.reserve (other.impl_items.size ());
3226 133580 : for (const auto &e : other.impl_items)
3227 76532 : impl_items.push_back (e->clone_associated_item ());
3228 57048 : }
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 4779 : bool is_unsafe () const { return has_unsafe; };
3252 20892 : 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 473539 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3260 : {
3261 1744086 : return impl_items;
3262 : }
3263 :
3264 : // TODO: is this better? Or is a "vis_block" better?
3265 1755691 : 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 45443 : 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 5 : ExternalTypeItem (Identifier item_name, Visibility vis,
3366 : std::vector<Attribute> outer_attrs, location_t locus)
3367 5 : : ExternalItem (), outer_attrs (std::move (outer_attrs)), visibility (vis),
3368 5 : item_name (std::move (item_name)), locus (locus), marked_for_strip (false)
3369 5 : {}
3370 :
3371 : // copy constructor
3372 6 : ExternalTypeItem (ExternalTypeItem const &other)
3373 6 : : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3374 6 : visibility (other.visibility), item_name (other.item_name),
3375 6 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3376 : {
3377 6 : node_id = other.node_id;
3378 6 : }
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 46 : location_t get_locus () const { return locus; }
3407 :
3408 0 : void mark_for_strip () override { marked_for_strip = true; };
3409 40 : 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 218 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3413 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3414 :
3415 43 : Identifier get_identifier () const { return item_name; }
3416 :
3417 180 : 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 6 : ExternalTypeItem *clone_external_item_impl () const override
3424 : {
3425 6 : 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 1 : : 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 24 : 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 19 : Type &get_type ()
3510 : {
3511 19 : rust_assert (item_type != nullptr);
3512 19 : 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 22 : 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 6744 : bool has_abi () const { return !abi.empty (); }
3566 :
3567 10116 : std::string get_abi () const { return abi; }
3568 :
3569 1740 : 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 1740 : : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
3574 1740 : inner_attrs (std::move (inner_attrs)),
3575 1740 : extern_items (std::move (extern_items)), locus (locus)
3576 1740 : {}
3577 :
3578 : // Copy constructor with vector clone
3579 3864 : ExternBlock (ExternBlock const &other)
3580 3864 : : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
3581 7728 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3582 : {
3583 3864 : extern_items.reserve (other.extern_items.size ());
3584 12469 : for (const auto &e : other.extern_items)
3585 8605 : extern_items.push_back (e->clone_external_item ());
3586 3864 : }
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 4610 : 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 5281 : 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 12370 : std::vector<std::unique_ptr<ExternalItem>> &get_extern_items ()
3622 : {
3623 50710 : 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 49071 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3629 :
3630 33 : 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 2125 : ExternBlock *clone_item_impl () const override
3636 : {
3637 2125 : return new ExternBlock (*this);
3638 : }
3639 : };
3640 :
3641 : class MacroRulesDefinition;
3642 : } // namespace AST
3643 : } // namespace Rust
3644 :
3645 : #endif
|