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 330483 : Identifier get_type_representation () const { return type_representation; }
63 :
64 : // Returns whether the type of the type param has been specified.
65 2270675 : bool has_type () const { return type != nullptr; }
66 :
67 : // Returns whether the type param has type param bounds.
68 23879 : 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 1684682 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
74 :
75 19142 : 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 19142 : : GenericParam (Analysis::Mappings::get ().get_next_node_id ()),
81 19142 : outer_attrs (std::move (outer_attrs)),
82 19142 : type_representation (std::move (type_representation)),
83 19142 : type_param_bounds (std::move (type_param_bounds)),
84 19142 : type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait)
85 19142 : {}
86 :
87 : // Copy constructor uses clone
88 64631 : TypeParam (TypeParam const &other)
89 64631 : : GenericParam (other.node_id), outer_attrs (other.outer_attrs),
90 64631 : type_representation (other.type_representation), locus (other.locus),
91 129262 : was_impl_trait (other.was_impl_trait)
92 : {
93 : // guard to prevent null pointer dereference
94 64631 : if (other.type != nullptr)
95 1236 : type = other.type->clone_type ();
96 :
97 64631 : type_param_bounds.reserve (other.type_param_bounds.size ());
98 79444 : for (const auto &e : other.type_param_bounds)
99 14813 : type_param_bounds.push_back (e->clone_type_param_bound ());
100 64631 : }
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 330060 : location_t get_locus () const override final { return locus; }
131 :
132 14371 : 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 14728 : Type &get_type ()
138 : {
139 14728 : rust_assert (type != nullptr);
140 14728 : return *type;
141 : }
142 :
143 4587 : std::unique_ptr<Type> &get_type_ptr ()
144 : {
145 4587 : rust_assert (type != nullptr);
146 4587 : return type;
147 : }
148 :
149 1055 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
150 : {
151 1923177 : 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 18975 : bool from_impl_trait () const { return was_impl_trait; }
161 :
162 : protected:
163 : // Clone function implementation as virtual method
164 54202 : TypeParam *clone_generic_param_impl () const override
165 : {
166 54202 : return new TypeParam (*this);
167 : }
168 : };
169 :
170 : /* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
171 : * TypeBoundWhereClauseItem */
172 7536 : class WhereClauseItem
173 : {
174 : public:
175 : virtual ~WhereClauseItem () {}
176 :
177 : // Unique pointer custom clone function
178 5846 : std::unique_ptr<WhereClauseItem> clone_where_clause_item () const
179 : {
180 5846 : 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 3 : NodeId get_node_id () const override final { return node_id; }
216 :
217 259 : Lifetime &get_lifetime () { return lifetime; }
218 :
219 259 : std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
220 :
221 3 : 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 345 : bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
243 :
244 232795 : 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 1691 : 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 1691 : : for_lifetimes (std::move (for_lifetimes)),
254 1691 : bound_type (std::move (bound_type)),
255 1691 : type_param_bounds (std::move (type_param_bounds)),
256 1691 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
257 1691 : {}
258 :
259 : // Copy constructor requires clone
260 5842 : TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
261 5842 : : for_lifetimes (other.for_lifetimes),
262 5842 : bound_type (other.bound_type->clone_type ())
263 : {
264 5842 : node_id = other.node_id;
265 5842 : type_param_bounds.reserve (other.type_param_bounds.size ());
266 11952 : for (const auto &e : other.type_param_bounds)
267 6110 : type_param_bounds.push_back (e->clone_type_param_bound ());
268 5842 : }
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 254219 : Type &get_type ()
293 : {
294 254219 : rust_assert (bound_type != nullptr);
295 254219 : return *bound_type;
296 : }
297 :
298 79482 : std::unique_ptr<Type> &get_type_ptr ()
299 : {
300 79482 : rust_assert (bound_type != nullptr);
301 79482 : return bound_type;
302 : }
303 :
304 : // TODO: this mutable getter seems really dodgy. Think up better way.
305 345 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
306 : {
307 272043 : 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 1684 : NodeId get_node_id () const override final { return node_id; }
317 :
318 1684 : location_t get_locus () const { return locus; }
319 :
320 : protected:
321 : // Clone function implementation as (not pure) virtual method
322 5842 : TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
323 : {
324 5842 : return new TypeBoundWhereClauseItem (*this);
325 : }
326 : };
327 :
328 : // A where clause
329 130487 : class WhereClause
330 : {
331 : std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
332 : NodeId node_id;
333 :
334 : public:
335 65491 : WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
336 65491 : : where_clause_items (std::move (where_clause_items)),
337 65491 : node_id (Analysis::Mappings::get ().get_next_node_id ())
338 65491 : {}
339 :
340 : // copy constructor with vector clone
341 238823 : WhereClause (WhereClause const &other)
342 238823 : {
343 238823 : node_id = other.node_id;
344 238823 : where_clause_items.reserve (other.where_clause_items.size ());
345 244669 : for (const auto &e : other.where_clause_items)
346 5846 : where_clause_items.push_back (e->clone_where_clause_item ());
347 238823 : }
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 67261 : WhereClause (WhereClause &&other) = default;
362 : WhereClause &operator= (WhereClause &&other) = default;
363 :
364 : // Creates a WhereClause with no items.
365 64181 : static WhereClause create_empty ()
366 : {
367 64181 : return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
368 : }
369 :
370 : // Returns whether the WhereClause has no items.
371 6277859 : 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 346 : std::vector<std::unique_ptr<WhereClauseItem>> &get_items ()
379 : {
380 253797 : 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 55766 : class Param : public Visitable
390 : {
391 : public:
392 271106 : Param (std::vector<Attribute> outer_attrs, location_t locus)
393 271106 : : outer_attrs (std::move (outer_attrs)), locus (locus),
394 271106 : node_id (Analysis::Mappings::get ().get_next_node_id ())
395 271106 : {}
396 :
397 : virtual ~Param () = default;
398 :
399 187122 : std::unique_ptr<Param> clone_param () const
400 : {
401 187122 : return std::unique_ptr<Param> (clone_param_impl ());
402 : }
403 :
404 980450 : virtual bool is_variadic () const { return false; }
405 :
406 909029 : virtual bool is_self () const { return false; }
407 :
408 28244 : NodeId get_node_id () const { return node_id; }
409 :
410 42222 : location_t get_locus () const { return locus; }
411 :
412 102015 : std::vector<Attribute> get_outer_attrs () const { return outer_attrs; }
413 :
414 1964194 : 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 2897144 : bool has_type () const { return type != nullptr; }
450 :
451 : // Returns whether the self-param has a valid lifetime.
452 1980357 : 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 7883 : SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
470 7883 : : Param ({}, locus), has_ref (false), is_mut (is_mut),
471 7883 : lifetime (tl::nullopt), type (std::move (type))
472 7883 : {}
473 :
474 : // Lifetime-based self parameter (is ref, no type)
475 11046 : SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
476 11046 : : Param ({}, locus), has_ref (true), is_mut (is_mut),
477 11046 : lifetime (std::move (lifetime))
478 11046 : {}
479 :
480 : // Copy constructor requires clone
481 99315 : SelfParam (SelfParam const &other)
482 99315 : : Param (other.get_outer_attrs (), other.get_locus ()),
483 198630 : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime)
484 : {
485 99315 : node_id = other.node_id;
486 99315 : if (other.type != nullptr)
487 98 : type = other.type->clone_type ();
488 99315 : }
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 136902 : location_t get_locus () const { return locus; }
515 :
516 716787 : bool is_self () const override { return true; }
517 :
518 27512 : bool get_has_ref () const { return has_ref; };
519 23969 : bool get_is_mut () const { return is_mut; }
520 :
521 0 : Lifetime get_lifetime () const { return lifetime.value (); }
522 942107 : Lifetime &get_lifetime () { return lifetime.value (); }
523 :
524 37587 : NodeId get_node_id () const { return node_id; }
525 :
526 : // TODO: is this better? Or is a "vis_block" better?
527 3933 : Type &get_type ()
528 : {
529 3933 : rust_assert (has_type ());
530 3933 : return *type;
531 : }
532 :
533 1046 : std::unique_ptr<Type> &get_type_ptr ()
534 : {
535 1046 : rust_assert (has_type ());
536 1046 : return type;
537 : }
538 :
539 : void accept_vis (ASTVisitor &vis) override;
540 :
541 80536 : SelfParam *clone_param_impl () const override
542 : {
543 80536 : return new SelfParam (*this);
544 : }
545 : };
546 :
547 : // Qualifiers for function, i.e. const, unsafe, extern etc.
548 131040 : 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 37674 : 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 37674 : : default_status (default_status), async_status (async_status),
564 37674 : const_status (const_status), unsafe_status (unsafe_status),
565 37674 : has_extern (has_extern), extern_abi (std::move (extern_abi)),
566 37674 : locus (locus)
567 : {
568 37674 : if (!this->extern_abi.empty ())
569 : {
570 : // having extern is required; not having it is an implementation error
571 756 : rust_assert (has_extern);
572 : }
573 37674 : }
574 :
575 : std::string as_string () const;
576 :
577 62920 : bool is_default () const { return default_status == Default::Yes; }
578 53056 : bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; }
579 51347 : bool is_extern () const { return has_extern; }
580 54642 : bool is_const () const { return const_status == Const::Yes; }
581 89684 : bool is_async () const { return async_status == Async::Yes; }
582 1470 : std::string get_extern_abi () const { return extern_abi; }
583 31824 : bool has_abi () const { return !extern_abi.empty (); }
584 31749 : Const get_const_status () const { return const_status; }
585 31749 : Async get_async_status () const { return async_status; }
586 :
587 1631 : 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 887 : VariadicParam (std::vector<Attribute> outer_attrs, location_t locus)
602 887 : : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr)
603 887 : {}
604 :
605 2700 : VariadicParam (VariadicParam const &other)
606 2700 : : Param (other.get_outer_attrs (), other.locus)
607 : {
608 2700 : if (other.param_name != nullptr)
609 33 : param_name = other.param_name->clone_pattern ();
610 2700 : }
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 5494 : bool is_variadic () const override { return true; }
626 :
627 1802 : VariadicParam *clone_param_impl () const override
628 : {
629 1802 : 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 20379 : 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 28548 : 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 28548 : param_name (std::move (param_name)), type (std::move (param_type))
669 28548 : {}
670 :
671 : // Copy constructor uses clone
672 120716 : FunctionParam (FunctionParam const &other)
673 120716 : : Param (other.get_outer_attrs (), other.locus)
674 : {
675 : // guard to prevent nullptr dereference
676 120716 : if (other.param_name != nullptr)
677 120716 : param_name = other.param_name->clone_pattern ();
678 120716 : if (other.type != nullptr)
679 120716 : type = other.type->clone_type ();
680 120716 : }
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 27883 : 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 4060684 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
718 120716 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
719 :
720 : // TODO: is this better? Or is a "vis_block" better?
721 3536697 : Pattern &get_pattern ()
722 : {
723 3536697 : rust_assert (param_name != nullptr);
724 3536697 : return *param_name;
725 : }
726 :
727 1101354 : std::unique_ptr<Pattern> &get_pattern_ptr ()
728 : {
729 1101354 : rust_assert (param_name != nullptr);
730 1101354 : return param_name;
731 : }
732 :
733 3221129 : bool has_name () const { return param_name != nullptr; }
734 :
735 : // TODO: is this better? Or is a "vis_block" better?
736 3552707 : Type &get_type ()
737 : {
738 3552707 : rust_assert (type != nullptr);
739 3552707 : return *type;
740 : }
741 :
742 1101637 : std::unique_ptr<Type> &get_type_ptr ()
743 : {
744 1101637 : rust_assert (type != nullptr);
745 1101637 : return type;
746 : }
747 :
748 104784 : FunctionParam *clone_param_impl () const override
749 : {
750 104784 : 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 72234 : 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 3937 : void clone_items (const std::vector<std::unique_ptr<Item>> &other_items)
793 : {
794 3937 : items.reserve (other_items.size ());
795 39989 : for (const auto &e : other_items)
796 36052 : items.push_back (e->clone_item ());
797 3937 : }
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 335 : 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 335 : module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
812 335 : safety (safety), outer_filename (outer_filename),
813 335 : inner_attrs (std::vector<Attribute> ()),
814 335 : items (std::vector<std::unique_ptr<Item>> ()),
815 335 : module_scope (std::move (module_scope))
816 335 : {}
817 :
818 : // Loaded module constructor, with items
819 1480 : 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 1480 : module_name (name), locus (locus), kind (ModuleKind::LOADED),
827 1480 : safety (safety), outer_filename (std::string ()),
828 1480 : inner_attrs (std::move (inner_attrs)), items (std::move (items))
829 1480 : {}
830 :
831 : // Copy constructor with vector clone
832 4125 : Module (Module const &other)
833 4125 : : VisItem (other), module_name (other.module_name), locus (other.locus),
834 4125 : kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs),
835 4125 : 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 4125 : if (other.kind == LOADED)
840 3937 : clone_items (other.items);
841 : else
842 188 : items.clear ();
843 4125 : }
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 13418 : enum ModuleKind get_kind () const { return kind; }
880 :
881 1732 : 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 80350 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
886 :
887 : const std::vector<std::unique_ptr<Item>> &get_items () const { return items; }
888 93939 : 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 16666 : location_t get_locus () const override final { return locus; }
907 :
908 : // Invalid if name is empty, so base stripping on that.
909 158 : void mark_for_strip () override { module_name = {""}; }
910 12294 : bool is_marked_for_strip () const override { return module_name.empty (); }
911 :
912 542 : 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 2393 : Module *clone_item_impl () const override { return new Module (*this); }
918 :
919 14076 : GlobContainer::Kind get_glob_container_kind () const override
920 : {
921 14076 : 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 70 : 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 70 : referenced_crate (std::move (referenced_crate)),
957 70 : as_clause_name (std::move (as_clause_name)), locus (locus)
958 70 : {}
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 2 : void mark_for_strip () override { referenced_crate = ""; }
975 135 : bool is_marked_for_strip () const override
976 : {
977 135 : return referenced_crate.empty ();
978 : }
979 :
980 6 : 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 67 : ExternCrate *clone_item_impl () const override
986 : {
987 67 : 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 1451 : 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 9901 : std::unique_ptr<UseTree> clone_use_tree () const
1023 : {
1024 9901 : 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 22 : location_t get_locus () const { return locus; }
1031 966 : 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 3932 : UseTree (location_t locus)
1040 3932 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1041 3932 : {}
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 245 : UseTreeGlob (PathType glob_type, SimplePath path, location_t locus)
1061 245 : : UseTree (locus), glob_type (glob_type), path (std::move (path))
1062 : {
1063 245 : 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 245 : }
1072 :
1073 : /* Returns whether has path. Should be made redundant by PathType
1074 : * PATH_PREFIXED. */
1075 4216 : 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 32 : PathType get_glob_type () const { return glob_type; }
1082 :
1083 6695 : Kind get_kind () const override { return Glob; }
1084 :
1085 4198 : SimplePath get_path () const
1086 : {
1087 4198 : rust_assert (has_path ());
1088 4198 : return path;
1089 : }
1090 :
1091 8228 : 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 596 : UseTreeGlob *clone_use_tree_impl () const override
1099 : {
1100 596 : 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 587 : UseTreeList (PathType path_type, SimplePath path,
1123 : std::vector<std::unique_ptr<UseTree>> trees, location_t locus)
1124 587 : : UseTree (locus), path_type (path_type), path (std::move (path)),
1125 587 : trees (std::move (trees))
1126 : {
1127 587 : 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 587 : }
1136 :
1137 : // copy constructor with vector clone
1138 1451 : UseTreeList (UseTreeList const &other)
1139 1451 : : UseTree (other), path_type (other.path_type), path (other.path)
1140 : {
1141 1451 : trees.reserve (other.trees.size ());
1142 6067 : for (const auto &e : other.trees)
1143 4616 : trees.push_back (e->clone_use_tree ());
1144 1451 : }
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 17868 : bool has_path () const { return !path.is_empty (); }
1166 :
1167 : // Returns whether has inner tree elements.
1168 171 : bool has_trees () const { return !trees.empty (); }
1169 :
1170 : std::string as_string () const override;
1171 :
1172 171 : PathType get_path_type () { return path_type; }
1173 :
1174 : void accept_vis (ASTVisitor &vis) override;
1175 :
1176 17866 : Kind get_kind () const override { return List; }
1177 9647 : SimplePath get_path () const
1178 : {
1179 9647 : rust_assert (has_path ());
1180 9647 : return path;
1181 : }
1182 :
1183 28607 : SimplePath &get_path () { return path; }
1184 :
1185 175 : std::vector<std::unique_ptr<UseTree>> &get_trees () { return trees; }
1186 :
1187 : const std::vector<std::unique_ptr<UseTree>> &get_trees () const
1188 : {
1189 9651 : 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 1451 : UseTreeList *clone_use_tree_impl () const override
1198 : {
1199 1451 : 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 3100 : UseTreeRebind (NewBindType bind_type, SimplePath path, location_t locus,
1222 : Identifier identifier = std::string ())
1223 3100 : : UseTree (locus), path (std::move (path)), bind_type (bind_type),
1224 3100 : identifier (std::move (identifier))
1225 3100 : {}
1226 :
1227 : // Returns whether has path (this should always be true).
1228 45944 : bool has_path () const { return !path.is_empty (); }
1229 :
1230 : // Returns whether has identifier (or, rather, is allowed to).
1231 396 : bool has_identifier () const { return bind_type == IDENTIFIER; }
1232 :
1233 : std::string as_string () const override;
1234 :
1235 52681 : NewBindType get_new_bind_type () const { return bind_type; }
1236 :
1237 : void accept_vis (ASTVisitor &vis) override;
1238 :
1239 62816 : Kind get_kind () const override { return Rebind; }
1240 :
1241 45944 : const SimplePath &get_path () const
1242 : {
1243 45944 : rust_assert (has_path ());
1244 45944 : return path;
1245 : }
1246 :
1247 76464 : SimplePath &get_path () { return path; }
1248 :
1249 396 : const Identifier &get_identifier () const
1250 : {
1251 396 : rust_assert (has_identifier ());
1252 396 : 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 7854 : virtual UseTreeRebind *clone_use_tree_impl () const override
1261 : {
1262 7854 : 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 2048 : 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 2048 : use_tree (std::move (use_tree)), locus (locus)
1279 2048 : {}
1280 :
1281 : // Copy constructor with clone
1282 5285 : UseDeclaration (UseDeclaration const &other)
1283 5285 : : VisItem (other), locus (other.locus)
1284 : {
1285 : // guard to prevent null dereference (only required if error state)
1286 5285 : if (other.use_tree != nullptr)
1287 5285 : use_tree = other.use_tree->clone_use_tree ();
1288 5285 : }
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 720 : location_t get_locus () const override final { return locus; }
1312 :
1313 171095 : 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 51 : void mark_for_strip () override { use_tree = nullptr; }
1321 28865 : bool is_marked_for_strip () const override { return use_tree == nullptr; }
1322 :
1323 502 : Item::Kind get_item_kind () const override
1324 : {
1325 502 : return Item::Kind::UseDeclaration;
1326 : }
1327 :
1328 : protected:
1329 : /* Use covariance to implement clone function as returning this object
1330 : * rather than base */
1331 3403 : UseDeclaration *clone_item_impl () const override
1332 : {
1333 3403 : 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 54174 : bool has_generics () const { return !generic_params.empty (); }
1357 :
1358 : // Returns whether function has regular parameters.
1359 34806 : bool has_function_params () const { return !function_params.empty (); }
1360 :
1361 : // Returns whether function has return type - if not, it is void.
1362 4350221 : bool has_return_type () const { return return_type != nullptr; }
1363 :
1364 : // Returns whether function has a where clause.
1365 3490135 : bool has_where_clause () const { return !where_clause.is_empty (); }
1366 :
1367 56934 : bool has_self_param () const
1368 : {
1369 56934 : return function_params.size () > 0 && function_params[0]->is_self ();
1370 : }
1371 :
1372 5033612 : bool has_body () const { return function_body.has_value (); }
1373 :
1374 27877 : bool is_default () const { return qualifiers.is_default (); }
1375 :
1376 : // Mega-constructor with all possible fields
1377 36931 : 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 36931 : ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
1386 36931 : function_name (std::move (function_name)),
1387 36931 : generic_params (std::move (generic_params)),
1388 36931 : function_params (std::move (function_params)),
1389 36931 : return_type (std::move (return_type)),
1390 36931 : where_clause (std::move (where_clause)),
1391 36931 : function_body (std::move (function_body)), locus (locus),
1392 36931 : is_external_function (is_external_function)
1393 36931 : {}
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 589122 : location_t get_locus () const override final { return locus; }
1408 :
1409 : void accept_vis (ASTVisitor &vis) override;
1410 :
1411 4445 : bool is_variadic () const
1412 : {
1413 4445 : return function_params.size () != 0
1414 4445 : && function_params.back ()->is_variadic ();
1415 : }
1416 :
1417 70086 : bool is_external () const { return is_external_function; }
1418 :
1419 : // Invalid if block is null, so base stripping on that.
1420 62 : void mark_for_strip () override { function_body = nullptr; }
1421 508305 : bool is_marked_for_strip () const override
1422 : {
1423 508305 : return function_body == nullptr;
1424 : }
1425 :
1426 1316853 : std::vector<std::unique_ptr<Param>> &get_function_params ()
1427 : {
1428 4461631 : return function_params;
1429 : }
1430 : const std::vector<std::unique_ptr<Param>> &get_function_params () const
1431 : {
1432 : return function_params;
1433 : }
1434 :
1435 5181 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1436 : {
1437 3475800 : 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 4380150 : tl::optional<std::unique_ptr<BlockExpr>> &get_definition ()
1446 : {
1447 4380150 : return function_body;
1448 : }
1449 :
1450 : const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
1451 :
1452 3084397 : FunctionQualifiers &get_qualifiers () { return qualifiers; }
1453 :
1454 1571557 : Identifier get_function_name () const { return function_name; }
1455 :
1456 : // TODO: is this better? Or is a "vis_block" better?
1457 114058 : WhereClause &get_where_clause () { return where_clause; }
1458 :
1459 : // TODO: is this better? Or is a "vis_block" better?
1460 2862883 : Type &get_return_type ()
1461 : {
1462 2862883 : rust_assert (has_return_type ());
1463 2862883 : return *return_type;
1464 : }
1465 :
1466 834670 : std::unique_ptr<Type> &get_return_type_ptr ()
1467 : {
1468 834670 : rust_assert (has_return_type ());
1469 834670 : return return_type;
1470 : }
1471 :
1472 18780 : Param &get_self_param ()
1473 : {
1474 18780 : rust_assert (has_self_param ());
1475 18780 : 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 3676607 : NodeId get_node_id () const override { return Stmt::node_id; }
1485 :
1486 144261 : 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 13927 : 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 93711 : Function *clone_associated_item_impl () const override
1496 : {
1497 93711 : return new Function (*this);
1498 : }
1499 :
1500 : /* Use covariance to implement clone function as returning this object
1501 : * rather than base */
1502 9008 : Function *clone_external_item_impl () const override
1503 : {
1504 9008 : 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 5744 : bool has_generics () const { return !generic_params.empty (); }
1529 :
1530 : // Returns whether type alias has a where clause.
1531 671257 : bool has_where_clause () const { return !where_clause.is_empty (); }
1532 :
1533 : // Mega-constructor with all possible fields
1534 4367 : 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 4367 : new_type_name (std::move (new_type_name)),
1541 4367 : generic_params (std::move (generic_params)),
1542 4367 : where_clause (std::move (where_clause)),
1543 4367 : existing_type (std::move (existing_type)), locus (locus)
1544 4367 : {}
1545 :
1546 : // Copy constructor
1547 27964 : TypeAlias (TypeAlias const &other)
1548 27964 : : VisItem (other), new_type_name (other.new_type_name),
1549 27964 : where_clause (other.where_clause), locus (other.locus)
1550 : {
1551 : // guard to prevent null dereference (only required if error state)
1552 27964 : if (other.existing_type != nullptr)
1553 27964 : existing_type = other.existing_type->clone_type ();
1554 :
1555 27964 : generic_params.reserve (other.generic_params.size ());
1556 28038 : for (const auto &e : other.generic_params)
1557 74 : generic_params.push_back (e->clone_generic_param ());
1558 27964 : }
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 100785 : location_t get_locus () const override final { return locus; }
1588 :
1589 : // needed to override AssociatedItem::get_node_id
1590 570068 : 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 94898 : bool is_marked_for_strip () const override
1597 : {
1598 94898 : return existing_type == nullptr;
1599 : }
1600 :
1601 48 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1602 : {
1603 669840 : 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 670778 : Type &get_type_aliased ()
1615 : {
1616 670778 : rust_assert (existing_type != nullptr);
1617 670778 : return *existing_type;
1618 : }
1619 :
1620 185675 : std::unique_ptr<Type> &get_type_aliased_ptr ()
1621 : {
1622 185675 : rust_assert (existing_type != nullptr);
1623 185675 : return existing_type;
1624 : }
1625 :
1626 480701 : Identifier get_new_type_name () const { return new_type_name; }
1627 :
1628 94 : 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 172 : 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 23440 : TypeAlias *clone_associated_item_impl () const override
1638 : {
1639 23440 : return new TypeAlias (*this);
1640 : }
1641 : };
1642 :
1643 : // Rust trait alias AST node
1644 : // like a type alias, but for traits
1645 : // unstable but used in core
1646 : class TraitAlias : public VisItem
1647 : {
1648 : Identifier alias_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 : std::vector<std::unique_ptr<TypeParamBound>> alias_bounds;
1658 :
1659 : location_t locus;
1660 :
1661 : bool m_mark_for_strip;
1662 :
1663 : public:
1664 : std::string as_string () const override;
1665 :
1666 : // Returns whether type alias has generic parameters.
1667 0 : bool has_generics () const { return !generic_params.empty (); }
1668 :
1669 : // Returns whether type alias has a where clause.
1670 44 : bool has_where_clause () const { return !where_clause.is_empty (); }
1671 :
1672 : // Mega-constructor with all possible fields
1673 2 : TraitAlias (Identifier alias_name,
1674 : std::vector<std::unique_ptr<GenericParam>> generic_params,
1675 : WhereClause where_clause,
1676 : std::vector<std::unique_ptr<TypeParamBound>> alias_bounds,
1677 : Visibility vis, std::vector<Attribute> outer_attrs,
1678 : location_t locus)
1679 : : VisItem (std::move (vis), std::move (outer_attrs)),
1680 4 : alias_name (std::move (alias_name)),
1681 2 : generic_params (std::move (generic_params)),
1682 2 : where_clause (std::move (where_clause)),
1683 2 : alias_bounds (std::move (alias_bounds)), locus (locus),
1684 2 : m_mark_for_strip (false)
1685 2 : {}
1686 :
1687 : // Copy constructor
1688 2 : TraitAlias (TraitAlias const &other)
1689 2 : : VisItem (other), alias_name (other.alias_name),
1690 2 : where_clause (other.where_clause), locus (other.locus)
1691 : {
1692 2 : generic_params.reserve (other.generic_params.size ());
1693 2 : for (const auto &e : other.generic_params)
1694 0 : generic_params.push_back (e->clone_generic_param ());
1695 :
1696 2 : alias_bounds.reserve (other.alias_bounds.size ());
1697 4 : for (const auto &b : other.alias_bounds)
1698 2 : alias_bounds.push_back (b->clone_type_param_bound ());
1699 2 : }
1700 :
1701 : // Overloaded assignment operator to clone
1702 : TraitAlias &operator= (TraitAlias const &other)
1703 : {
1704 : VisItem::operator= (other);
1705 : alias_name = other.alias_name;
1706 : where_clause = other.where_clause;
1707 : // visibility = other.visibility->clone_visibility();
1708 : // outer_attrs = other.outer_attrs;
1709 : locus = other.locus;
1710 :
1711 : generic_params.clear ();
1712 : generic_params.reserve (other.generic_params.size ());
1713 : for (const auto &e : other.generic_params)
1714 : generic_params.push_back (e->clone_generic_param ());
1715 :
1716 : alias_bounds.clear ();
1717 : alias_bounds.reserve (other.alias_bounds.size ());
1718 : for (const auto &b : other.alias_bounds)
1719 : alias_bounds.push_back (b->clone_type_param_bound ());
1720 :
1721 : return *this;
1722 : }
1723 :
1724 : // move constructors
1725 : TraitAlias (TraitAlias &&other) = default;
1726 : TraitAlias &operator= (TraitAlias &&other) = default;
1727 :
1728 8 : location_t get_locus () const override final { return locus; }
1729 :
1730 : // needed to override AssociatedItem::get_node_id
1731 22 : NodeId get_node_id () const override final { return VisItem::get_node_id (); }
1732 :
1733 : void accept_vis (ASTVisitor &vis) override;
1734 :
1735 0 : void mark_for_strip () override { m_mark_for_strip = true; }
1736 4 : bool is_marked_for_strip () const override { return m_mark_for_strip; }
1737 :
1738 0 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1739 : {
1740 44 : return generic_params;
1741 : }
1742 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1743 : {
1744 : return generic_params;
1745 : }
1746 :
1747 : // TODO: is this better? Or is a "vis_block" better?
1748 0 : WhereClause &get_where_clause () { return where_clause; }
1749 :
1750 0 : std::vector<std::unique_ptr<TypeParamBound>> &get_alias_bounds ()
1751 : {
1752 44 : return alias_bounds;
1753 : }
1754 : const std::vector<std::unique_ptr<TypeParamBound>> &get_alias_bounds () const
1755 : {
1756 : return alias_bounds;
1757 : }
1758 :
1759 30 : const Identifier &get_alias_name () const { return alias_name; }
1760 :
1761 0 : Item::Kind get_item_kind () const override { return Item::Kind::TraitAlias; }
1762 :
1763 : protected:
1764 : /* Use covariance to implement clone function as returning this object
1765 : * rather than base */
1766 2 : TraitAlias *clone_item_impl () const override
1767 : {
1768 2 : return new TraitAlias (*this);
1769 : }
1770 : };
1771 :
1772 : // Rust base struct declaration AST node - abstract base class
1773 : class Struct : public VisItem
1774 : {
1775 : protected:
1776 : // protected to enable access by derived classes - allows better as_string
1777 : Identifier struct_name;
1778 :
1779 : // bool has_generics;
1780 : // Generics generic_params;
1781 : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1782 :
1783 : // bool has_where_clause;
1784 : WhereClause where_clause;
1785 :
1786 : private:
1787 : location_t locus;
1788 :
1789 : public:
1790 : // Returns whether struct has generic parameters.
1791 6276 : bool has_generics () const { return !generic_params.empty (); }
1792 :
1793 : // Returns whether struct has a where clause.
1794 311197 : bool has_where_clause () const { return !where_clause.is_empty (); }
1795 :
1796 63520 : location_t get_locus () const override final { return locus; }
1797 :
1798 : // Invalid if name is empty, so base stripping on that.
1799 16 : void mark_for_strip () override { struct_name = {""}; }
1800 68075 : bool is_marked_for_strip () const override { return struct_name.empty (); }
1801 :
1802 195408 : Identifier get_struct_name () const { return struct_name; }
1803 :
1804 3132 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1805 : {
1806 311755 : return generic_params;
1807 : }
1808 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1809 : {
1810 : return generic_params;
1811 : }
1812 :
1813 : // TODO: is this better? Or is a "vis_block" better?
1814 3235 : WhereClause &get_where_clause () { return where_clause; }
1815 :
1816 6898 : Identifier get_identifier () const { return struct_name; }
1817 :
1818 11719 : Item::Kind get_item_kind () const override { return Item::Kind::Struct; }
1819 :
1820 : protected:
1821 4017 : Struct (Identifier struct_name,
1822 : std::vector<std::unique_ptr<GenericParam>> generic_params,
1823 : WhereClause where_clause, Visibility vis, location_t locus,
1824 : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1825 : : VisItem (std::move (vis), std::move (outer_attrs)),
1826 8034 : struct_name (std::move (struct_name)),
1827 4017 : generic_params (std::move (generic_params)),
1828 4017 : where_clause (std::move (where_clause)), locus (locus)
1829 4017 : {}
1830 :
1831 : // Copy constructor with vector clone
1832 11437 : Struct (Struct const &other)
1833 11437 : : VisItem (other), struct_name (other.struct_name),
1834 11437 : where_clause (other.where_clause), locus (other.locus)
1835 : {
1836 11437 : generic_params.reserve (other.generic_params.size ());
1837 15805 : for (const auto &e : other.generic_params)
1838 4368 : generic_params.push_back (e->clone_generic_param ());
1839 11437 : }
1840 :
1841 : // Overloaded assignment operator with vector clone
1842 : Struct &operator= (Struct const &other)
1843 : {
1844 : VisItem::operator= (other);
1845 : struct_name = other.struct_name;
1846 : where_clause = other.where_clause;
1847 : locus = other.locus;
1848 :
1849 : generic_params.reserve (other.generic_params.size ());
1850 : for (const auto &e : other.generic_params)
1851 : generic_params.push_back (e->clone_generic_param ());
1852 :
1853 : return *this;
1854 : }
1855 :
1856 : // move constructors
1857 : Struct (Struct &&other) = default;
1858 : Struct &operator= (Struct &&other) = default;
1859 : };
1860 :
1861 : // A single field in a struct
1862 : class StructField
1863 : {
1864 : // bool has_outer_attributes;
1865 : std::vector<Attribute> outer_attrs;
1866 :
1867 : // bool has_visibility;
1868 : Visibility visibility;
1869 :
1870 : Identifier field_name;
1871 : std::unique_ptr<Type> field_type;
1872 :
1873 : NodeId node_id;
1874 :
1875 : location_t locus;
1876 :
1877 : public:
1878 : // Returns whether struct field has any outer attributes.
1879 : bool has_outer_attributes () const { return !outer_attrs.empty (); }
1880 :
1881 : // Returns whether struct field has a non-private (non-default) visibility.
1882 : bool has_visibility () const { return true; }
1883 :
1884 3391 : StructField (Identifier field_name, std::unique_ptr<Type> field_type,
1885 : Visibility vis, location_t locus,
1886 : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1887 3391 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1888 3391 : field_name (std::move (field_name)), field_type (std::move (field_type)),
1889 3391 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
1890 3391 : {}
1891 :
1892 : // Copy constructor
1893 7931 : StructField (StructField const &other)
1894 7931 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
1895 7931 : field_name (other.field_name), node_id (other.node_id),
1896 7931 : locus (other.locus)
1897 : {
1898 : // guard to prevent null dereference
1899 7931 : if (other.field_type != nullptr)
1900 7931 : field_type = other.field_type->clone_type ();
1901 7931 : }
1902 :
1903 13103 : ~StructField () = default;
1904 :
1905 : // Overloaded assignment operator to clone
1906 : StructField &operator= (StructField const &other)
1907 : {
1908 : field_name = other.field_name;
1909 : visibility = other.visibility;
1910 : outer_attrs = other.outer_attrs;
1911 : node_id = other.node_id;
1912 :
1913 : // guard to prevent null dereference
1914 : if (other.field_type != nullptr)
1915 : field_type = other.field_type->clone_type ();
1916 : else
1917 : field_type = nullptr;
1918 :
1919 : return *this;
1920 : }
1921 :
1922 : // move constructors
1923 5079 : StructField (StructField &&other) = default;
1924 2 : StructField &operator= (StructField &&other) = default;
1925 :
1926 : // Returns whether struct field is in an error state.
1927 3256 : bool is_error () const
1928 : {
1929 3256 : return field_name.empty () && field_type == nullptr;
1930 : // this should really be an or since neither are allowed
1931 : }
1932 :
1933 : // Creates an error state struct field.
1934 59 : static StructField create_error ()
1935 : {
1936 118 : return StructField (std::string (""), nullptr,
1937 177 : Visibility::create_private (), UNDEF_LOCATION);
1938 : }
1939 :
1940 : std::string as_string () const;
1941 :
1942 : // TODO: this mutable getter seems really dodgy. Think up better way.
1943 193159 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1944 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1945 :
1946 6279 : Identifier get_field_name () const { return field_name; }
1947 :
1948 5580 : location_t get_locus () const { return locus; }
1949 :
1950 : // TODO: is this better? Or is a "vis_block" better?
1951 152167 : Type &get_field_type ()
1952 : {
1953 152167 : rust_assert (field_type != nullptr);
1954 152167 : return *field_type;
1955 : }
1956 :
1957 44248 : std::unique_ptr<Type> &get_field_type_ptr ()
1958 : {
1959 44248 : rust_assert (field_type != nullptr);
1960 44248 : return field_type;
1961 : }
1962 :
1963 165474 : Visibility &get_visibility () { return visibility; }
1964 : const Visibility &get_visibility () const { return visibility; }
1965 :
1966 3264 : NodeId get_node_id () const { return node_id; }
1967 : };
1968 :
1969 : // Rust struct declaration with true struct type AST node
1970 : class StructStruct : public Struct
1971 : {
1972 : std::vector<StructField> fields;
1973 : bool is_unit;
1974 :
1975 : public:
1976 : std::string as_string () const override;
1977 :
1978 : // Mega-constructor with all possible fields
1979 1585 : StructStruct (std::vector<StructField> fields, Identifier struct_name,
1980 : std::vector<std::unique_ptr<GenericParam>> generic_params,
1981 : WhereClause where_clause, bool is_unit, Visibility vis,
1982 : std::vector<Attribute> outer_attrs, location_t locus)
1983 : : Struct (std::move (struct_name), std::move (generic_params),
1984 : std::move (where_clause), std::move (vis), locus,
1985 : std::move (outer_attrs)),
1986 1585 : fields (std::move (fields)), is_unit (is_unit)
1987 1585 : {}
1988 :
1989 : // Unit struct constructor
1990 1239 : StructStruct (Identifier struct_name,
1991 : std::vector<std::unique_ptr<GenericParam>> generic_params,
1992 : WhereClause where_clause, Visibility vis,
1993 : std::vector<Attribute> outer_attrs, location_t locus)
1994 : : Struct (std::move (struct_name), std::move (generic_params),
1995 : std::move (where_clause), std::move (vis), locus,
1996 : std::move (outer_attrs)),
1997 1239 : is_unit (true)
1998 1239 : {}
1999 :
2000 : /* Returns whether the struct is a unit struct - struct defined without
2001 : * fields. This is important because it also means an implicit constant of its
2002 : * type is defined. */
2003 31782 : bool is_unit_struct () const { return is_unit; }
2004 :
2005 : void accept_vis (ASTVisitor &vis) override;
2006 :
2007 : // TODO: this mutable getter seems really dodgy. Think up better way.
2008 380285 : std::vector<StructField> &get_fields () { return fields; }
2009 : const std::vector<StructField> &get_fields () const { return fields; }
2010 :
2011 : protected:
2012 : /* Use covariance to implement clone function as returning this object
2013 : * rather than base */
2014 5882 : StructStruct *clone_item_impl () const override
2015 : {
2016 5882 : return new StructStruct (*this);
2017 : }
2018 : };
2019 :
2020 : // A single field in a tuple
2021 : class TupleField
2022 : {
2023 : // bool has_outer_attributes;
2024 : std::vector<Attribute> outer_attrs;
2025 :
2026 : // bool has_visibility;
2027 : Visibility visibility;
2028 :
2029 : std::unique_ptr<Type> field_type;
2030 :
2031 : NodeId node_id;
2032 :
2033 : location_t locus;
2034 :
2035 : public:
2036 : // Returns whether tuple field has outer attributes.
2037 : bool has_outer_attributes () const { return !outer_attrs.empty (); }
2038 :
2039 : /* Returns whether tuple field has a non-default visibility (i.e. a public
2040 : * one) */
2041 : bool has_visibility () const { return true; }
2042 :
2043 : // Complete constructor
2044 2944 : TupleField (std::unique_ptr<Type> field_type, Visibility vis,
2045 : location_t locus,
2046 : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
2047 2944 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
2048 2944 : field_type (std::move (field_type)),
2049 2944 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
2050 2944 : {}
2051 :
2052 : // Copy constructor with clone
2053 8684 : TupleField (TupleField const &other)
2054 8684 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
2055 8684 : node_id (other.node_id), locus (other.locus)
2056 : {
2057 : // guard to prevent null dereference (only required if error)
2058 8684 : if (other.field_type != nullptr)
2059 8684 : field_type = other.field_type->clone_type ();
2060 8684 : }
2061 :
2062 12998 : ~TupleField () = default;
2063 :
2064 : // Overloaded assignment operator to clone
2065 : TupleField &operator= (TupleField const &other)
2066 : {
2067 : visibility = other.visibility;
2068 : outer_attrs = other.outer_attrs;
2069 : node_id = other.node_id;
2070 : locus = other.locus;
2071 :
2072 : // guard to prevent null dereference (only required if error)
2073 : if (other.field_type != nullptr)
2074 : field_type = other.field_type->clone_type ();
2075 : else
2076 : field_type = nullptr;
2077 :
2078 : return *this;
2079 : }
2080 :
2081 : // move constructors
2082 4298 : TupleField (TupleField &&other) = default;
2083 0 : TupleField &operator= (TupleField &&other) = default;
2084 :
2085 : // Returns whether tuple field is in an error state.
2086 2944 : bool is_error () const { return field_type == nullptr; }
2087 :
2088 : // Creates an error state tuple field.
2089 1 : static TupleField create_error ()
2090 : {
2091 1 : return TupleField (nullptr, Visibility::create_private (), UNDEF_LOCATION);
2092 : }
2093 :
2094 : std::string as_string () const;
2095 :
2096 2863 : NodeId get_node_id () const { return node_id; }
2097 :
2098 164718 : Visibility &get_visibility () { return visibility; }
2099 : const Visibility &get_visibility () const { return visibility; }
2100 :
2101 2863 : location_t get_locus () const { return locus; }
2102 :
2103 : // TODO: this mutable getter seems really dodgy. Think up better way.
2104 191920 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2105 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2106 :
2107 : // TODO: is this better? Or is a "vis_block" better?
2108 146430 : Type &get_field_type ()
2109 : {
2110 146430 : rust_assert (field_type != nullptr);
2111 146430 : return *field_type;
2112 : }
2113 :
2114 47849 : std::unique_ptr<Type> &get_field_type_ptr ()
2115 : {
2116 47849 : rust_assert (field_type != nullptr);
2117 47849 : return field_type;
2118 : }
2119 : };
2120 :
2121 : // Rust tuple declared using struct keyword AST node
2122 : class TupleStruct : public Struct
2123 : {
2124 : std::vector<TupleField> fields;
2125 :
2126 : public:
2127 : std::string as_string () const override;
2128 :
2129 : // Mega-constructor with all possible fields
2130 1193 : TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
2131 : std::vector<std::unique_ptr<GenericParam>> generic_params,
2132 : WhereClause where_clause, Visibility vis,
2133 : std::vector<Attribute> outer_attrs, location_t locus)
2134 : : Struct (std::move (struct_name), std::move (generic_params),
2135 : std::move (where_clause), std::move (vis), locus,
2136 : std::move (outer_attrs)),
2137 1193 : fields (std::move (fields))
2138 1193 : {}
2139 :
2140 : void accept_vis (ASTVisitor &vis) override;
2141 :
2142 : // TODO: this mutable getter seems really dodgy. Think up better way.
2143 54899 : std::vector<TupleField> &get_fields () { return fields; }
2144 : const std::vector<TupleField> &get_fields () const { return fields; }
2145 :
2146 : protected:
2147 : /* Use covariance to implement clone function as returning this object
2148 : * rather than base */
2149 1728 : TupleStruct *clone_item_impl () const override
2150 : {
2151 1728 : return new TupleStruct (*this);
2152 : }
2153 : };
2154 :
2155 : /* An item used in an "enum" tagged union - not abstract: base represents a
2156 : * name-only enum. EnumItems (variants) syntactically allow a Visibility
2157 : * annotation. */
2158 : class EnumItem : public VisItem
2159 : {
2160 : Identifier variant_name;
2161 :
2162 : location_t locus;
2163 :
2164 : public:
2165 : enum class Kind
2166 : {
2167 : Identifier,
2168 : Tuple,
2169 : Struct,
2170 :
2171 : // FIXME: In the future, we'll need to remove this possibility as well as
2172 : // remove the EnumItemDiscriminant class. The feature for arbitrary
2173 : // discriminants on all kinds of variants has been stabilized, and a
2174 : // "discriminant" is no longer an enum item variant - it's simply an
2175 : // optional part of all variants.
2176 : //
2177 : // Per the reference:
2178 : //
2179 : // EnumItem :
2180 : // OuterAttribute* Visibility?
2181 : // IDENTIFIER ( EnumItemTuple | EnumItemStruct )? EnumItemDiscriminant?
2182 : //
2183 : // EnumItemTuple :
2184 : // ( TupleFields? )
2185 : //
2186 : // EnumItemStruct :
2187 : // { StructFields? }
2188 : //
2189 : // EnumItemDiscriminant :
2190 : // = Expression
2191 : //
2192 : // So we instead need to remove the class, and add an optional expression to
2193 : // the base EnumItem class
2194 : //
2195 : // gccrs#3340
2196 :
2197 : Discriminant,
2198 : };
2199 :
2200 5541 : virtual ~EnumItem () {}
2201 :
2202 1550 : EnumItem (Identifier variant_name, Visibility vis,
2203 : std::vector<Attribute> outer_attrs, location_t locus)
2204 : : VisItem (std::move (vis), std::move (outer_attrs)),
2205 1550 : variant_name (std::move (variant_name)), locus (locus)
2206 1550 : {}
2207 :
2208 249 : virtual Kind get_enum_item_kind () const { return Kind::Identifier; }
2209 :
2210 : // Unique pointer custom clone function
2211 4078 : std::unique_ptr<EnumItem> clone_enum_item () const
2212 : {
2213 4078 : return std::unique_ptr<EnumItem> (clone_item_impl ());
2214 : }
2215 :
2216 : virtual std::string as_string () const override;
2217 :
2218 : // not pure virtual as not abstract
2219 : virtual void accept_vis (ASTVisitor &vis) override;
2220 :
2221 10981 : location_t get_locus () const override { return locus; }
2222 :
2223 27864 : Identifier get_identifier () const { return variant_name; }
2224 :
2225 : // Based on idea that name is never empty.
2226 0 : void mark_for_strip () override { variant_name = {""}; }
2227 8282 : bool is_marked_for_strip () const override { return variant_name.empty (); }
2228 :
2229 0 : Item::Kind get_item_kind () const override { return Item::Kind::EnumItem; }
2230 :
2231 : protected:
2232 1457 : EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
2233 : };
2234 :
2235 : // A tuple item used in an "enum" tagged union
2236 : class EnumItemTuple : public EnumItem
2237 : {
2238 : // bool has_tuple_fields;
2239 : std::vector<TupleField> tuple_fields;
2240 :
2241 : public:
2242 : // Returns whether tuple enum item has tuple fields.
2243 0 : bool has_tuple_fields () const { return !tuple_fields.empty (); }
2244 :
2245 558 : EnumItemTuple (Identifier variant_name, Visibility vis,
2246 : std::vector<TupleField> tuple_fields,
2247 : std::vector<Attribute> outer_attrs, location_t locus)
2248 : : EnumItem (std::move (variant_name), std::move (vis),
2249 : std::move (outer_attrs), locus),
2250 558 : tuple_fields (std::move (tuple_fields))
2251 558 : {}
2252 :
2253 187 : EnumItem::Kind get_enum_item_kind () const override
2254 : {
2255 187 : return EnumItem::Kind::Tuple;
2256 : }
2257 :
2258 : std::string as_string () const override;
2259 :
2260 : void accept_vis (ASTVisitor &vis) override;
2261 :
2262 : // TODO: this mutable getter seems really dodgy. Think up better way.
2263 22404 : std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
2264 : const std::vector<TupleField> &get_tuple_fields () const
2265 : {
2266 : return tuple_fields;
2267 : }
2268 :
2269 : protected:
2270 : // Clone function implementation as (not pure) virtual method
2271 1448 : EnumItemTuple *clone_item_impl () const override
2272 : {
2273 1448 : return new EnumItemTuple (*this);
2274 : }
2275 : };
2276 :
2277 : // A struct item used in an "enum" tagged union
2278 : class EnumItemStruct : public EnumItem
2279 : {
2280 : // bool has_struct_fields;
2281 : std::vector<StructField> struct_fields;
2282 :
2283 : public:
2284 : // Returns whether struct enum item has struct fields.
2285 0 : bool has_struct_fields () const { return !struct_fields.empty (); }
2286 :
2287 100 : EnumItemStruct (Identifier variant_name, Visibility vis,
2288 : std::vector<StructField> struct_fields,
2289 : std::vector<Attribute> outer_attrs, location_t locus)
2290 : : EnumItem (std::move (variant_name), std::move (vis),
2291 : std::move (outer_attrs), locus),
2292 100 : struct_fields (std::move (struct_fields))
2293 100 : {}
2294 :
2295 36 : EnumItem::Kind get_enum_item_kind () const override
2296 : {
2297 36 : return EnumItem::Kind::Struct;
2298 : }
2299 :
2300 : std::string as_string () const override;
2301 :
2302 : void accept_vis (ASTVisitor &vis) override;
2303 :
2304 : // TODO: this mutable getter seems really dodgy. Think up better way.
2305 2716 : std::vector<StructField> &get_struct_fields () { return struct_fields; }
2306 : const std::vector<StructField> &get_struct_fields () const
2307 : {
2308 11 : return struct_fields;
2309 : }
2310 :
2311 : protected:
2312 : // Clone function implementation as (not pure) virtual method
2313 208 : EnumItemStruct *clone_item_impl () const override
2314 : {
2315 208 : return new EnumItemStruct (*this);
2316 : }
2317 : };
2318 :
2319 : // A discriminant (numbered enum) item used in an "enum" tagged union
2320 : class EnumItemDiscriminant : public EnumItem
2321 : {
2322 : std::unique_ptr<Expr> expression;
2323 :
2324 : public:
2325 296 : EnumItemDiscriminant (Identifier variant_name, Visibility vis,
2326 : std::unique_ptr<Expr> expr,
2327 : std::vector<Attribute> outer_attrs, location_t locus)
2328 : : EnumItem (std::move (variant_name), std::move (vis),
2329 : std::move (outer_attrs), locus),
2330 296 : expression (std::move (expr))
2331 296 : {}
2332 :
2333 : // Copy constructor with clone
2334 965 : EnumItemDiscriminant (EnumItemDiscriminant const &other)
2335 965 : : EnumItem (other), expression (other.expression->clone_expr ())
2336 965 : {}
2337 :
2338 : // Overloaded assignment operator to clone
2339 : EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other)
2340 : {
2341 : EnumItem::operator= (other);
2342 : expression = other.expression->clone_expr ();
2343 : // variant_name = other.variant_name;
2344 : // outer_attrs = other.outer_attrs;
2345 :
2346 : return *this;
2347 : }
2348 :
2349 : // move constructors
2350 : EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
2351 : EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
2352 :
2353 18 : EnumItem::Kind get_enum_item_kind () const override
2354 : {
2355 18 : return EnumItem::Kind::Discriminant;
2356 : }
2357 :
2358 : std::string as_string () const override;
2359 :
2360 : void accept_vis (ASTVisitor &vis) override;
2361 :
2362 : bool has_expr () { return expression != nullptr; }
2363 :
2364 : // TODO: is this better? Or is a "vis_block" better?
2365 8747 : Expr &get_expr ()
2366 : {
2367 8747 : rust_assert (expression != nullptr);
2368 8747 : return *expression;
2369 : }
2370 :
2371 1934 : std::unique_ptr<Expr> &get_expr_ptr ()
2372 : {
2373 1934 : rust_assert (expression != nullptr);
2374 1934 : return expression;
2375 : }
2376 :
2377 : protected:
2378 : // Clone function implementation as (not pure) virtual method
2379 965 : EnumItemDiscriminant *clone_item_impl () const override
2380 : {
2381 965 : return new EnumItemDiscriminant (*this);
2382 : }
2383 : };
2384 :
2385 : // AST node for Rust "enum" - tagged union
2386 : class Enum : public VisItem, public GlobContainer
2387 : {
2388 : Identifier enum_name;
2389 :
2390 : // bool has_generics;
2391 : // Generics generic_params;
2392 : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2393 :
2394 : // bool has_where_clause;
2395 : WhereClause where_clause;
2396 :
2397 : std::vector<std::unique_ptr<EnumItem>> items;
2398 :
2399 : location_t locus;
2400 :
2401 : public:
2402 : std::string as_string () const override;
2403 :
2404 : // Returns whether "enum" has generic parameters.
2405 1170 : bool has_generics () const { return !generic_params.empty (); }
2406 :
2407 : // Returns whether "enum" has a where clause.
2408 22233 : bool has_where_clause () const { return !where_clause.is_empty (); }
2409 :
2410 : /* Returns whether enum is a "zero-variant" (no possible variant) enum,
2411 : * which cannot be instantiated. */
2412 : bool is_zero_variant () const { return items.empty (); }
2413 :
2414 : // Mega-constructor
2415 668 : Enum (Identifier enum_name, Visibility vis,
2416 : std::vector<std::unique_ptr<GenericParam>> generic_params,
2417 : WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
2418 : std::vector<Attribute> outer_attrs, location_t locus)
2419 : : VisItem (std::move (vis), std::move (outer_attrs)),
2420 668 : enum_name (std::move (enum_name)),
2421 668 : generic_params (std::move (generic_params)),
2422 668 : where_clause (std::move (where_clause)), items (std::move (items)),
2423 668 : locus (locus)
2424 668 : {}
2425 :
2426 : // TODO: constructor with less arguments
2427 :
2428 : // Copy constructor with vector clone
2429 1756 : Enum (Enum const &other)
2430 1756 : : VisItem (other), enum_name (other.enum_name),
2431 1756 : where_clause (other.where_clause), locus (other.locus)
2432 : {
2433 1756 : generic_params.reserve (other.generic_params.size ());
2434 2775 : for (const auto &e : other.generic_params)
2435 1019 : generic_params.push_back (e->clone_generic_param ());
2436 :
2437 1756 : items.reserve (other.items.size ());
2438 5834 : for (const auto &e : other.items)
2439 4078 : items.push_back (e->clone_enum_item ());
2440 1756 : }
2441 :
2442 : // Overloaded assignment operator with vector clone
2443 : Enum &operator= (Enum const &other)
2444 : {
2445 : VisItem::operator= (other);
2446 : enum_name = other.enum_name;
2447 : where_clause = other.where_clause;
2448 : locus = other.locus;
2449 :
2450 : generic_params.reserve (other.generic_params.size ());
2451 : for (const auto &e : other.generic_params)
2452 : generic_params.push_back (e->clone_generic_param ());
2453 :
2454 : items.reserve (other.items.size ());
2455 : for (const auto &e : other.items)
2456 : items.push_back (e->clone_enum_item ());
2457 :
2458 : return *this;
2459 : }
2460 :
2461 : // Move constructors
2462 : Enum (Enum &&other) = default;
2463 : Enum &operator= (Enum &&other) = default;
2464 :
2465 5198 : location_t get_locus () const override final { return locus; }
2466 :
2467 : void accept_vis (ASTVisitor &vis) override;
2468 :
2469 17993 : Identifier get_identifier () const { return enum_name; }
2470 :
2471 : // Invalid if name is empty, so base stripping on that.
2472 0 : void mark_for_strip () override { enum_name = {""}; }
2473 2639 : bool is_marked_for_strip () const override { return enum_name.empty (); }
2474 :
2475 : // TODO: this mutable getter seems really dodgy. Think up better way.
2476 25725 : std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
2477 : const std::vector<std::unique_ptr<EnumItem>> &get_variants () const
2478 : {
2479 : return items;
2480 : }
2481 :
2482 755 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2483 : {
2484 22460 : return generic_params;
2485 : }
2486 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2487 : {
2488 : return generic_params;
2489 : }
2490 :
2491 : // TODO: is this better? Or is a "vis_block" better?
2492 32 : WhereClause &get_where_clause () { return where_clause; }
2493 :
2494 1092 : Item::Kind get_item_kind () const override { return Item::Kind::Enum; }
2495 :
2496 1395 : GlobContainer::Kind get_glob_container_kind () const override
2497 : {
2498 1395 : return GlobContainer::Kind::Enum;
2499 : }
2500 :
2501 : protected:
2502 : /* Use covariance to implement clone function as returning this object
2503 : * rather than base */
2504 1091 : Enum *clone_item_impl () const override { return new Enum (*this); }
2505 : };
2506 :
2507 : // Rust untagged union used for C compat AST node
2508 : class Union : public VisItem
2509 : {
2510 : Identifier union_name;
2511 :
2512 : // bool has_generics;
2513 : // Generics generic_params;
2514 : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2515 :
2516 : // bool has_where_clause;
2517 : WhereClause where_clause;
2518 :
2519 : std::vector<StructField> variants;
2520 :
2521 : location_t locus;
2522 :
2523 : public:
2524 : std::string as_string () const override;
2525 :
2526 : // Returns whether union has generic params.
2527 212 : bool has_generics () const { return !generic_params.empty (); }
2528 :
2529 : // Returns whether union has where clause.
2530 2978 : bool has_where_clause () const { return !where_clause.is_empty (); }
2531 :
2532 116 : Union (Identifier union_name, Visibility vis,
2533 : std::vector<std::unique_ptr<GenericParam>> generic_params,
2534 : WhereClause where_clause, std::vector<StructField> variants,
2535 : std::vector<Attribute> outer_attrs, location_t locus)
2536 : : VisItem (std::move (vis), std::move (outer_attrs)),
2537 232 : union_name (std::move (union_name)),
2538 116 : generic_params (std::move (generic_params)),
2539 116 : where_clause (std::move (where_clause)), variants (std::move (variants)),
2540 116 : locus (locus)
2541 116 : {}
2542 :
2543 : // copy constructor with vector clone
2544 242 : Union (Union const &other)
2545 242 : : VisItem (other), union_name (other.union_name),
2546 242 : where_clause (other.where_clause), variants (other.variants),
2547 242 : locus (other.locus)
2548 : {
2549 242 : generic_params.reserve (other.generic_params.size ());
2550 415 : for (const auto &e : other.generic_params)
2551 173 : generic_params.push_back (e->clone_generic_param ());
2552 242 : }
2553 :
2554 : // overloaded assignment operator with vector clone
2555 : Union &operator= (Union const &other)
2556 : {
2557 : VisItem::operator= (other);
2558 : union_name = other.union_name;
2559 : where_clause = other.where_clause;
2560 : variants = other.variants;
2561 : locus = other.locus;
2562 :
2563 : generic_params.reserve (other.generic_params.size ());
2564 : for (const auto &e : other.generic_params)
2565 : generic_params.push_back (e->clone_generic_param ());
2566 :
2567 : return *this;
2568 : }
2569 :
2570 : // move constructors
2571 : Union (Union &&other) = default;
2572 : Union &operator= (Union &&other) = default;
2573 :
2574 659 : location_t get_locus () const override final { return locus; }
2575 :
2576 : void accept_vis (ASTVisitor &vis) override;
2577 :
2578 : // Invalid if name is empty, so base stripping on that.
2579 0 : void mark_for_strip () override { union_name = {""}; }
2580 308 : bool is_marked_for_strip () const override { return union_name.empty (); }
2581 :
2582 : // TODO: this mutable getter seems really dodgy. Think up better way.
2583 3515 : std::vector<StructField> &get_variants () { return variants; }
2584 : const std::vector<StructField> &get_variants () const { return variants; }
2585 :
2586 157 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2587 : {
2588 3034 : return generic_params;
2589 : }
2590 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2591 : {
2592 : return generic_params;
2593 : }
2594 :
2595 : // TODO: is this better? Or is a "vis_block" better?
2596 0 : WhereClause &get_where_clause () { return where_clause; }
2597 :
2598 2327 : Identifier get_identifier () const { return union_name; }
2599 :
2600 500 : Item::Kind get_item_kind () const override { return Item::Kind::Union; }
2601 :
2602 : protected:
2603 : /* Use covariance to implement clone function as returning this object
2604 : * rather than base */
2605 126 : Union *clone_item_impl () const override { return new Union (*this); }
2606 : };
2607 :
2608 : /* "Constant item" AST node - used for constant, compile-time expressions
2609 : * within module scope (like constexpr) */
2610 : class ConstantItem : public VisItem, public AssociatedItem
2611 : {
2612 : // either has an identifier or "_" - maybe handle in identifier?
2613 : // bool identifier_is_underscore;
2614 : // if no identifier declared, identifier will be "_"
2615 : Identifier identifier;
2616 :
2617 : std::unique_ptr<Type> type;
2618 : std::unique_ptr<Expr> const_expr;
2619 :
2620 : location_t locus;
2621 :
2622 : public:
2623 : std::string as_string () const override;
2624 :
2625 1367 : ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
2626 : std::unique_ptr<Expr> const_expr,
2627 : std::vector<Attribute> outer_attrs, location_t locus)
2628 : : VisItem (std::move (vis), std::move (outer_attrs)),
2629 1367 : identifier (std::move (ident)), type (std::move (type)),
2630 1367 : const_expr (std::move (const_expr)), locus (locus)
2631 1367 : {}
2632 :
2633 4 : ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
2634 : std::vector<Attribute> outer_attrs, location_t locus)
2635 : : VisItem (std::move (vis), std::move (outer_attrs)),
2636 4 : identifier (std::move (ident)), type (std::move (type)),
2637 4 : const_expr (nullptr), locus (locus)
2638 4 : {}
2639 :
2640 4535 : ConstantItem (ConstantItem const &other)
2641 4535 : : VisItem (other), identifier (other.identifier), locus (other.locus)
2642 : {
2643 : // guard to prevent null dereference (only required if error state)
2644 4535 : if (other.type != nullptr)
2645 4535 : type = other.type->clone_type ();
2646 4535 : if (other.const_expr != nullptr)
2647 4341 : const_expr = other.const_expr->clone_expr ();
2648 4535 : }
2649 :
2650 : // Overload assignment operator to clone
2651 : ConstantItem &operator= (ConstantItem const &other)
2652 : {
2653 : VisItem::operator= (other);
2654 : identifier = other.identifier;
2655 : locus = other.locus;
2656 :
2657 : // guard to prevent null dereference (only required if error state)
2658 : if (other.type != nullptr)
2659 : type = other.type->clone_type ();
2660 : else
2661 : type = nullptr;
2662 : if (other.const_expr != nullptr)
2663 : const_expr = other.const_expr->clone_expr ();
2664 : else
2665 : const_expr = nullptr;
2666 :
2667 : return *this;
2668 : }
2669 :
2670 : // move constructors
2671 : ConstantItem (ConstantItem &&other) = default;
2672 : ConstantItem &operator= (ConstantItem &&other) = default;
2673 :
2674 : /* Returns whether constant item is an "unnamed" (wildcard underscore used
2675 : * as identifier) constant. */
2676 552 : bool is_unnamed () const { return identifier.as_string () == "_"; }
2677 :
2678 29091 : location_t get_locus () const override final { return locus; }
2679 :
2680 : // needed to override AssociatedItem::get_node_id
2681 110538 : NodeId get_node_id () const override final { return VisItem::get_node_id (); }
2682 :
2683 : void accept_vis (ASTVisitor &vis) override;
2684 :
2685 : // Invalid if type and expression are null, so base stripping on that.
2686 1 : void mark_for_strip () override
2687 : {
2688 1 : type = nullptr;
2689 1 : const_expr = nullptr;
2690 1 : }
2691 26573 : bool is_marked_for_strip () const override
2692 : {
2693 26573 : return type == nullptr && const_expr == nullptr;
2694 : }
2695 :
2696 210875 : bool has_expr () const { return const_expr != nullptr; }
2697 :
2698 : // TODO: is this better? Or is a "vis_block" better?
2699 151222 : Expr &get_expr ()
2700 : {
2701 151222 : rust_assert (const_expr != nullptr);
2702 151222 : return *const_expr;
2703 : }
2704 :
2705 51338 : std::unique_ptr<Expr> &get_expr_ptr ()
2706 : {
2707 51338 : rust_assert (const_expr != nullptr);
2708 51338 : return const_expr;
2709 : }
2710 :
2711 : // TODO: is this better? Or is a "vis_block" better?
2712 156867 : Type &get_type ()
2713 : {
2714 156867 : rust_assert (type != nullptr);
2715 156867 : return *type;
2716 : }
2717 :
2718 52866 : std::unique_ptr<Type> &get_type_ptr ()
2719 : {
2720 52866 : rust_assert (type != nullptr);
2721 52866 : return type;
2722 : }
2723 :
2724 83202 : const Identifier &get_identifier () const { return identifier; }
2725 :
2726 2231 : Item::Kind get_item_kind () const override
2727 : {
2728 2231 : return Item::Kind::ConstantItem;
2729 : }
2730 :
2731 : protected:
2732 : /* Use covariance to implement clone function as returning this object
2733 : * rather than base */
2734 2094 : ConstantItem *clone_item_impl () const override
2735 : {
2736 2094 : return new ConstantItem (*this);
2737 : }
2738 :
2739 : /* Use covariance to implement clone function as returning this object
2740 : * rather than base */
2741 1084 : ConstantItem *clone_associated_item_impl () const override
2742 : {
2743 1084 : return new ConstantItem (*this);
2744 : }
2745 : };
2746 :
2747 : /* Static item AST node - items within module scope with fixed storage
2748 : * duration? */
2749 : class StaticItem : public VisItem
2750 : {
2751 : bool has_mut;
2752 : Identifier name;
2753 : std::unique_ptr<Type> type;
2754 : std::unique_ptr<Expr> expr;
2755 : location_t locus;
2756 :
2757 : public:
2758 : std::string as_string () const override;
2759 :
2760 133 : StaticItem (Identifier name, bool is_mut, std::unique_ptr<Type> type,
2761 : std::unique_ptr<Expr> expr, Visibility vis,
2762 : std::vector<Attribute> outer_attrs, location_t locus)
2763 133 : : VisItem (std::move (vis), std::move (outer_attrs)), has_mut (is_mut),
2764 266 : name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
2765 133 : locus (locus)
2766 133 : {}
2767 :
2768 : // Copy constructor with clone
2769 204 : StaticItem (StaticItem const &other)
2770 204 : : VisItem (other), has_mut (other.has_mut), name (other.name),
2771 204 : locus (other.locus)
2772 : {
2773 : // guard to prevent null dereference (only required if error state)
2774 204 : if (other.type != nullptr)
2775 204 : type = other.type->clone_type ();
2776 204 : if (other.expr != nullptr)
2777 204 : expr = other.expr->clone_expr ();
2778 204 : }
2779 :
2780 : // Overloaded assignment operator to clone
2781 : StaticItem &operator= (StaticItem const &other)
2782 : {
2783 : VisItem::operator= (other);
2784 : name = other.name;
2785 : has_mut = other.has_mut;
2786 : locus = other.locus;
2787 :
2788 : // guard to prevent null dereference (only required if error state)
2789 : if (other.type != nullptr)
2790 : type = other.type->clone_type ();
2791 : else
2792 : type = nullptr;
2793 : if (other.expr != nullptr)
2794 : expr = other.expr->clone_expr ();
2795 : else
2796 : expr = nullptr;
2797 :
2798 : return *this;
2799 : }
2800 :
2801 : // move constructors
2802 : StaticItem (StaticItem &&other) = default;
2803 : StaticItem &operator= (StaticItem &&other) = default;
2804 :
2805 1753 : location_t get_locus () const override final { return locus; }
2806 :
2807 : void accept_vis (ASTVisitor &vis) override;
2808 :
2809 : // Invalid if type or expression are null, so base stripping on that.
2810 0 : void mark_for_strip () override
2811 : {
2812 0 : type = nullptr;
2813 0 : expr = nullptr;
2814 0 : }
2815 1415 : bool is_marked_for_strip () const override
2816 : {
2817 1415 : return type == nullptr && expr == nullptr;
2818 : }
2819 :
2820 70 : bool has_expr () { return expr != nullptr; }
2821 :
2822 : // TODO: is this better? Or is a "vis_block" better?
2823 8270 : Expr &get_expr ()
2824 : {
2825 8270 : rust_assert (expr != nullptr);
2826 8270 : return *expr;
2827 : }
2828 :
2829 2954 : std::unique_ptr<Expr> &get_expr_ptr ()
2830 : {
2831 2954 : rust_assert (expr != nullptr);
2832 2954 : return expr;
2833 : }
2834 :
2835 : // TODO: is this better? Or is a "vis_block" better?
2836 8270 : Type &get_type ()
2837 : {
2838 8270 : rust_assert (type != nullptr);
2839 8270 : return *type;
2840 : }
2841 :
2842 2954 : std::unique_ptr<Type> &get_type_ptr ()
2843 : {
2844 2954 : rust_assert (type != nullptr);
2845 2954 : return type;
2846 : }
2847 :
2848 181 : bool is_mutable () const { return has_mut; }
2849 :
2850 4812 : Identifier get_identifier () const { return name; }
2851 :
2852 49 : Item::Kind get_item_kind () const override { return Item::Kind::StaticItem; }
2853 :
2854 : protected:
2855 : /* Use covariance to implement clone function as returning this object
2856 : * rather than base */
2857 204 : StaticItem *clone_item_impl () const override
2858 : {
2859 204 : return new StaticItem (*this);
2860 : }
2861 : };
2862 :
2863 : // Type items within traits
2864 : class TraitItemType : public TraitItem
2865 : {
2866 : std::vector<Attribute> outer_attrs;
2867 :
2868 : Identifier name;
2869 :
2870 : // Generic parameters for GATs (Generic Associated Types)
2871 : std::vector<std::unique_ptr<GenericParam>> generic_params;
2872 :
2873 : // bool has_type_param_bounds;
2874 : // TypeParamBounds type_param_bounds;
2875 : std::vector<std::unique_ptr<TypeParamBound>>
2876 : type_param_bounds; // inlined form
2877 :
2878 : public:
2879 0 : bool has_generics () const { return !generic_params.empty (); }
2880 :
2881 : // Returns whether trait item type has type param bounds.
2882 0 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2883 :
2884 911 : TraitItemType (Identifier name,
2885 : std::vector<std::unique_ptr<GenericParam>> generic_params,
2886 : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
2887 : std::vector<Attribute> outer_attrs, Visibility vis,
2888 : location_t locus)
2889 911 : : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
2890 911 : name (std::move (name)), generic_params (std::move (generic_params)),
2891 911 : type_param_bounds (std::move (type_param_bounds))
2892 911 : {}
2893 :
2894 : // Copy constructor with vector clone
2895 2050 : TraitItemType (TraitItemType const &other)
2896 4100 : : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2897 2050 : name (other.name)
2898 : {
2899 2050 : node_id = other.node_id;
2900 2050 : generic_params.reserve (other.generic_params.size ());
2901 2086 : for (const auto &e : other.generic_params)
2902 36 : generic_params.push_back (e->clone_generic_param ());
2903 2050 : type_param_bounds.reserve (other.type_param_bounds.size ());
2904 2237 : for (const auto &e : other.type_param_bounds)
2905 187 : type_param_bounds.push_back (e->clone_type_param_bound ());
2906 2050 : }
2907 :
2908 : // Overloaded assignment operator with vector clone
2909 : TraitItemType &operator= (TraitItemType const &other)
2910 : {
2911 : TraitItem::operator= (other);
2912 : outer_attrs = other.outer_attrs;
2913 : name = other.name;
2914 : locus = other.locus;
2915 : node_id = other.node_id;
2916 :
2917 : generic_params.reserve (other.generic_params.size ());
2918 : for (const auto &e : other.generic_params)
2919 : generic_params.push_back (e->clone_generic_param ());
2920 : type_param_bounds.reserve (other.type_param_bounds.size ());
2921 : for (const auto &e : other.type_param_bounds)
2922 : type_param_bounds.push_back (e->clone_type_param_bound ());
2923 :
2924 : return *this;
2925 : }
2926 :
2927 : // default move constructors
2928 : TraitItemType (TraitItemType &&other) = default;
2929 : TraitItemType &operator= (TraitItemType &&other) = default;
2930 :
2931 : std::string as_string () const override;
2932 :
2933 : void accept_vis (ASTVisitor &vis) override;
2934 :
2935 : // Invalid if name is empty, so base stripping on that.
2936 0 : void mark_for_strip () override { name = {""}; }
2937 4449 : bool is_marked_for_strip () const override { return name.empty (); }
2938 :
2939 : // TODO: this mutable getter seems really dodgy. Think up better way.
2940 42569 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2941 909 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2942 :
2943 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2944 : {
2945 33775 : return generic_params;
2946 : }
2947 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2948 : {
2949 : return generic_params;
2950 : }
2951 :
2952 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
2953 : {
2954 33775 : return type_param_bounds;
2955 : }
2956 : const std::vector<std::unique_ptr<TypeParamBound>> &
2957 : get_type_param_bounds () const
2958 : {
2959 : return type_param_bounds;
2960 : }
2961 :
2962 6147 : Identifier get_identifier () const { return name; }
2963 :
2964 : protected:
2965 : // Clone function implementation as (not pure) virtual method
2966 2050 : TraitItemType *clone_associated_item_impl () const override
2967 : {
2968 2050 : return new TraitItemType (*this);
2969 : }
2970 : };
2971 :
2972 : // Rust trait item declaration AST node
2973 : class Trait : public VisItem
2974 : {
2975 : bool has_unsafe;
2976 : bool has_auto;
2977 : Identifier name;
2978 : std::vector<std::unique_ptr<GenericParam>> generic_params;
2979 : TypeParam self_param;
2980 : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
2981 : WhereClause where_clause;
2982 : std::vector<Attribute> inner_attrs;
2983 : std::vector<std::unique_ptr<AssociatedItem>> trait_items;
2984 : location_t locus;
2985 :
2986 : public:
2987 : std::string as_string () const override;
2988 :
2989 : // Returns whether trait has generic parameters.
2990 8513 : bool has_generics () const { return !generic_params.empty (); }
2991 :
2992 : // Returns whether trait has type parameter bounds.
2993 4523 : bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2994 :
2995 : // Returns whether trait has where clause.
2996 135279 : bool has_where_clause () const { return !where_clause.is_empty (); }
2997 :
2998 : // Returns whether trait has trait items.
2999 30 : bool has_trait_items () const { return !trait_items.empty (); }
3000 :
3001 : // Returns whether trait has inner attributes.
3002 : bool has_inner_attrs () const { return !inner_attrs.empty (); }
3003 :
3004 106486 : Identifier get_identifier () const { return name; }
3005 :
3006 4493 : bool is_unsafe () const { return has_unsafe; }
3007 13585 : bool is_auto () const { return has_auto; }
3008 :
3009 : // Mega-constructor
3010 4582 : Trait (Identifier name, bool is_unsafe, bool is_auto,
3011 : std::vector<std::unique_ptr<GenericParam>> generic_params,
3012 : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
3013 : WhereClause where_clause,
3014 : std::vector<std::unique_ptr<AssociatedItem>> trait_items,
3015 : Visibility vis, std::vector<Attribute> outer_attrs,
3016 : std::vector<Attribute> inner_attrs, location_t locus)
3017 : : VisItem (std::move (vis), std::move (outer_attrs)),
3018 9164 : has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)),
3019 9164 : generic_params (std::move (generic_params)), self_param ({"Self"}, locus),
3020 4582 : type_param_bounds (std::move (type_param_bounds)),
3021 4582 : where_clause (std::move (where_clause)),
3022 4582 : inner_attrs (std::move (inner_attrs)),
3023 4582 : trait_items (std::move (trait_items)), locus (locus)
3024 4582 : {}
3025 :
3026 : // Copy constructor with vector clone
3027 10429 : Trait (Trait const &other)
3028 10429 : : VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto),
3029 10429 : name (other.name), self_param (other.self_param),
3030 10429 : where_clause (other.where_clause), inner_attrs (other.inner_attrs),
3031 20858 : locus (other.locus)
3032 : {
3033 10429 : generic_params.reserve (other.generic_params.size ());
3034 12551 : for (const auto &e : other.generic_params)
3035 2122 : generic_params.push_back (e->clone_generic_param ());
3036 :
3037 10429 : type_param_bounds.reserve (other.type_param_bounds.size ());
3038 12552 : for (const auto &e : other.type_param_bounds)
3039 2123 : type_param_bounds.push_back (e->clone_type_param_bound ());
3040 :
3041 10429 : trait_items.reserve (other.trait_items.size ());
3042 21172 : for (const auto &e : other.trait_items)
3043 10743 : trait_items.push_back (e->clone_associated_item ());
3044 10429 : }
3045 :
3046 : // Overloaded assignment operator with vector clone
3047 : Trait &operator= (Trait const &other)
3048 : {
3049 : VisItem::operator= (other);
3050 : name = other.name;
3051 : self_param = other.self_param;
3052 : has_unsafe = other.has_unsafe;
3053 : has_auto = other.has_auto;
3054 : where_clause = other.where_clause;
3055 : inner_attrs = other.inner_attrs;
3056 : locus = other.locus;
3057 :
3058 : generic_params.reserve (other.generic_params.size ());
3059 : for (const auto &e : other.generic_params)
3060 : generic_params.push_back (e->clone_generic_param ());
3061 :
3062 : type_param_bounds.reserve (other.type_param_bounds.size ());
3063 : for (const auto &e : other.type_param_bounds)
3064 : type_param_bounds.push_back (e->clone_type_param_bound ());
3065 :
3066 : trait_items.reserve (other.trait_items.size ());
3067 : for (const auto &e : other.trait_items)
3068 : trait_items.push_back (e->clone_associated_item ());
3069 :
3070 : return *this;
3071 : }
3072 :
3073 : // default move constructors
3074 : Trait (Trait &&other) = default;
3075 : Trait &operator= (Trait &&other) = default;
3076 :
3077 31745 : location_t get_locus () const override final { return locus; }
3078 :
3079 : void accept_vis (ASTVisitor &vis) override;
3080 :
3081 : // Invalid if trait name is empty, so base stripping on that.
3082 2 : void mark_for_strip () override { name = {""}; }
3083 15040 : bool is_marked_for_strip () const override { return name.empty (); }
3084 :
3085 : // TODO: think of better way to do this
3086 : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3087 135310 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3088 :
3089 : const std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items () const
3090 : {
3091 : return trait_items;
3092 : }
3093 34077 : std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items ()
3094 : {
3095 158822 : return trait_items;
3096 : }
3097 :
3098 1509 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3099 : {
3100 136788 : return generic_params;
3101 : }
3102 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3103 : {
3104 : return generic_params;
3105 : }
3106 :
3107 3990 : std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
3108 : {
3109 141234 : return type_param_bounds;
3110 : }
3111 : const std::vector<std::unique_ptr<TypeParamBound>> &
3112 : get_type_param_bounds () const
3113 : {
3114 : return type_param_bounds;
3115 : }
3116 :
3117 196 : WhereClause &get_where_clause () { return where_clause; }
3118 :
3119 120251 : AST::TypeParam &get_implicit_self () { return self_param; }
3120 :
3121 17967 : Item::Kind get_item_kind () const override { return Item::Kind::Trait; }
3122 :
3123 : protected:
3124 : /* Use covariance to implement clone function as returning this object
3125 : * rather than base */
3126 5883 : Trait *clone_item_impl () const override { return new Trait (*this); }
3127 : };
3128 :
3129 : // Implementation item declaration AST node - abstract base class
3130 : class Impl : public VisItem
3131 : {
3132 : // must be protected to allow subclasses to access them properly
3133 : protected:
3134 : // bool has_generics;
3135 : // Generics generic_params;
3136 : std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3137 :
3138 : std::unique_ptr<Type> trait_type;
3139 :
3140 : // bool has_where_clause;
3141 : WhereClause where_clause;
3142 :
3143 : // bool has_inner_attrs;
3144 : std::vector<Attribute> inner_attrs;
3145 :
3146 : private:
3147 : // doesn't really need to be protected as write access probably not needed
3148 : location_t locus;
3149 :
3150 : public:
3151 : // Returns whether impl has generic parameters.
3152 14611 : bool has_generics () const { return !generic_params.empty (); }
3153 :
3154 : // Returns whether impl has where clause.
3155 1644736 : bool has_where_clause () const { return !where_clause.is_empty (); }
3156 :
3157 : // Returns whether impl has inner attributes.
3158 : bool has_inner_attrs () const { return !inner_attrs.empty (); }
3159 :
3160 20775 : location_t get_locus () const override final { return locus; }
3161 :
3162 : // Invalid if trait type is null, so base stripping on that.
3163 20 : void mark_for_strip () override { trait_type = nullptr; }
3164 252267 : bool is_marked_for_strip () const override { return trait_type == nullptr; }
3165 :
3166 : // TODO: think of better way to do this
3167 : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3168 1905873 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3169 :
3170 10544 : std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3171 : {
3172 1649221 : return generic_params;
3173 : }
3174 : const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3175 : {
3176 : return generic_params;
3177 : }
3178 :
3179 : // TODO: is this better? Or is a "vis_block" better?
3180 81638 : WhereClause &get_where_clause () { return where_clause; }
3181 :
3182 : // TODO: is this better? Or is a "vis_block" better?
3183 1677638 : Type &get_type ()
3184 : {
3185 1677638 : rust_assert (trait_type != nullptr);
3186 1677638 : return *trait_type;
3187 : }
3188 :
3189 520632 : std::unique_ptr<Type> &get_type_ptr ()
3190 : {
3191 520632 : rust_assert (trait_type != nullptr);
3192 520632 : return trait_type;
3193 : }
3194 :
3195 14464 : Item::Kind get_item_kind () const override { return Item::Kind::Impl; }
3196 :
3197 : protected:
3198 : // Mega-constructor
3199 14762 : Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
3200 : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3201 : Visibility vis, std::vector<Attribute> inner_attrs,
3202 : std::vector<Attribute> outer_attrs, location_t locus)
3203 : : VisItem (std::move (vis), std::move (outer_attrs)),
3204 14762 : generic_params (std::move (generic_params)),
3205 14762 : trait_type (std::move (trait_type)),
3206 14762 : where_clause (std::move (where_clause)),
3207 14762 : inner_attrs (std::move (inner_attrs)), locus (locus)
3208 14762 : {}
3209 :
3210 : // Copy constructor
3211 67836 : Impl (Impl const &other)
3212 67836 : : VisItem (other), where_clause (other.where_clause),
3213 67836 : inner_attrs (other.inner_attrs), locus (other.locus)
3214 : {
3215 : // guard to prevent null dereference (only required if error state)
3216 67836 : if (other.trait_type != nullptr)
3217 67836 : trait_type = other.trait_type->clone_type ();
3218 :
3219 67836 : generic_params.reserve (other.generic_params.size ());
3220 112624 : for (const auto &e : other.generic_params)
3221 44788 : generic_params.push_back (e->clone_generic_param ());
3222 67836 : }
3223 :
3224 : // Assignment operator overload with cloning
3225 : Impl &operator= (Impl const &other)
3226 : {
3227 : VisItem::operator= (other);
3228 : where_clause = other.where_clause;
3229 : inner_attrs = other.inner_attrs;
3230 : locus = other.locus;
3231 :
3232 : // guard to prevent null dereference (only required if error state)
3233 : if (other.trait_type != nullptr)
3234 : trait_type = other.trait_type->clone_type ();
3235 : else
3236 : trait_type = nullptr;
3237 :
3238 : generic_params.reserve (other.generic_params.size ());
3239 : for (const auto &e : other.generic_params)
3240 : generic_params.push_back (e->clone_generic_param ());
3241 :
3242 : return *this;
3243 : }
3244 :
3245 : // move constructors
3246 : Impl (Impl &&other) = default;
3247 : Impl &operator= (Impl &&other) = default;
3248 : };
3249 :
3250 : // Regular "impl foo" impl block declaration AST node
3251 : class InherentImpl : public Impl
3252 : {
3253 : // bool has_impl_items;
3254 : std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3255 :
3256 : public:
3257 : std::string as_string () const override;
3258 :
3259 : // Returns whether inherent impl block has inherent impl items.
3260 0 : bool has_impl_items () const { return !impl_items.empty (); }
3261 :
3262 : // Mega-constructor
3263 1557 : InherentImpl (std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3264 : std::vector<std::unique_ptr<GenericParam>> generic_params,
3265 : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3266 : Visibility vis, std::vector<Attribute> inner_attrs,
3267 : std::vector<Attribute> outer_attrs, location_t locus)
3268 : : Impl (std::move (generic_params), std::move (trait_type),
3269 : std::move (where_clause), std::move (vis), std::move (inner_attrs),
3270 : std::move (outer_attrs), locus),
3271 1557 : impl_items (std::move (impl_items))
3272 1557 : {}
3273 :
3274 : // Copy constructor with vector clone
3275 4800 : InherentImpl (InherentImpl const &other) : Impl (other)
3276 : {
3277 4800 : impl_items.reserve (other.impl_items.size ());
3278 26516 : for (const auto &e : other.impl_items)
3279 21716 : impl_items.push_back (e->clone_associated_item ());
3280 4800 : }
3281 :
3282 : // Overloaded assignment operator with vector clone
3283 : InherentImpl &operator= (InherentImpl const &other)
3284 : {
3285 : Impl::operator= (other);
3286 :
3287 : impl_items.reserve (other.impl_items.size ());
3288 : for (const auto &e : other.impl_items)
3289 : impl_items.push_back (e->clone_associated_item ());
3290 :
3291 : return *this;
3292 : }
3293 :
3294 : // default move constructors
3295 : InherentImpl (InherentImpl &&other) = default;
3296 : InherentImpl &operator= (InherentImpl &&other) = default;
3297 :
3298 : void accept_vis (ASTVisitor &vis) override;
3299 :
3300 : // TODO: think of better way to do this
3301 : const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3302 : {
3303 : return impl_items;
3304 : }
3305 27524 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3306 : {
3307 109309 : return impl_items;
3308 : }
3309 :
3310 : protected:
3311 : /* Use covariance to implement clone function as returning this object
3312 : * rather than base */
3313 3256 : InherentImpl *clone_item_impl () const override
3314 : {
3315 3256 : return new InherentImpl (*this);
3316 : }
3317 : };
3318 :
3319 : // The "impl footrait for foo" impl block declaration AST node
3320 : class TraitImpl : public Impl
3321 : {
3322 : bool has_unsafe;
3323 : bool has_exclam;
3324 : TypePath trait_path;
3325 :
3326 : // bool has_impl_items;
3327 : std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3328 :
3329 : public:
3330 : std::string as_string () const override;
3331 :
3332 : // Returns whether trait impl has impl items.
3333 0 : bool has_impl_items () const { return !impl_items.empty (); }
3334 :
3335 : // Mega-constructor
3336 13205 : TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
3337 : std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3338 : std::vector<std::unique_ptr<GenericParam>> generic_params,
3339 : std::unique_ptr<Type> trait_type, WhereClause where_clause,
3340 : Visibility vis, std::vector<Attribute> inner_attrs,
3341 : std::vector<Attribute> outer_attrs, location_t locus)
3342 : : Impl (std::move (generic_params), std::move (trait_type),
3343 : std::move (where_clause), std::move (vis), std::move (inner_attrs),
3344 : std::move (outer_attrs), locus),
3345 13205 : has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path),
3346 13205 : impl_items (std::move (impl_items))
3347 13205 : {}
3348 :
3349 : // Copy constructor with vector clone
3350 63036 : TraitImpl (TraitImpl const &other)
3351 63036 : : Impl (other), has_unsafe (other.has_unsafe),
3352 63036 : has_exclam (other.has_exclam), trait_path (other.trait_path)
3353 : {
3354 63036 : impl_items.reserve (other.impl_items.size ());
3355 146348 : for (const auto &e : other.impl_items)
3356 83312 : impl_items.push_back (e->clone_associated_item ());
3357 63036 : }
3358 :
3359 : // Overloaded assignment operator with vector clone
3360 : TraitImpl &operator= (TraitImpl const &other)
3361 : {
3362 : Impl::operator= (other);
3363 : trait_path = other.trait_path;
3364 : has_unsafe = other.has_unsafe;
3365 : has_exclam = other.has_exclam;
3366 :
3367 : impl_items.reserve (other.impl_items.size ());
3368 : for (const auto &e : other.impl_items)
3369 : impl_items.push_back (e->clone_associated_item ());
3370 :
3371 : return *this;
3372 : }
3373 :
3374 : // move constructors
3375 : TraitImpl (TraitImpl &&other) = default;
3376 : TraitImpl &operator= (TraitImpl &&other) = default;
3377 :
3378 : void accept_vis (ASTVisitor &vis) override;
3379 :
3380 13097 : bool is_unsafe () const { return has_unsafe; };
3381 31327 : bool is_exclam () const { return has_exclam; }
3382 :
3383 : // TODO: think of better way to do this
3384 : const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3385 : {
3386 : return impl_items;
3387 : }
3388 484918 : std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3389 : {
3390 1802623 : return impl_items;
3391 : }
3392 :
3393 : // TODO: is this better? Or is a "vis_block" better?
3394 1815805 : TypePath &get_trait_path () { return trait_path; }
3395 :
3396 : protected:
3397 : /* Use covariance to implement clone function as returning this object
3398 : * rather than base */
3399 49854 : TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
3400 : };
3401 :
3402 : #if 0
3403 : // Abstract base class for an item used inside an extern block
3404 : class ExternalItem
3405 : {
3406 : // bool has_outer_attrs;
3407 : std::vector<Attribute> outer_attrs;
3408 :
3409 : // bool has_visibility;
3410 : Visibility visibility;
3411 :
3412 : Identifier item_name;
3413 : location_t locus;
3414 :
3415 : public:
3416 : virtual ~ExternalItem () {}
3417 :
3418 : /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
3419 : * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
3420 : * support would require a lot of refactoring. */
3421 :
3422 : // Returns whether item has outer attributes.
3423 : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3424 :
3425 : // Returns whether item has non-default visibility.
3426 : bool has_visibility () const { return !visibility.is_error (); }
3427 :
3428 : // Unique pointer custom clone function
3429 : std::unique_ptr<ExternalItem> clone_external_item () const
3430 : {
3431 : return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
3432 : }
3433 :
3434 : virtual std::string as_string () const;
3435 :
3436 : location_t get_locus () const override final { return locus; }
3437 :
3438 : virtual void accept_vis (ASTVisitor &vis) = 0;
3439 :
3440 : // TODO: make virtual? Would be more flexible.
3441 : // Based on idea that name should never be empty.
3442 : void mark_for_strip () { item_name = ""; };
3443 : bool is_marked_for_strip () const { return item_name.empty (); };
3444 :
3445 : protected:
3446 : ExternalItem (Identifier item_name, Visibility vis,
3447 : std::vector<Attribute> outer_attrs, location_t locus)
3448 : : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
3449 : item_name (std::move (item_name)), locus (locus)
3450 : {}
3451 :
3452 : // Copy constructor
3453 : ExternalItem (ExternalItem const &other)
3454 : : outer_attrs (other.outer_attrs), visibility (other.visibility),
3455 : item_name (other.item_name), locus (other.locus)
3456 : {}
3457 :
3458 : // Overloaded assignment operator to clone
3459 : ExternalItem &operator= (ExternalItem const &other)
3460 : {
3461 : item_name = other.item_name;
3462 : visibility = other.visibility;
3463 : outer_attrs = other.outer_attrs;
3464 : locus = other.locus;
3465 :
3466 : return *this;
3467 : }
3468 :
3469 : // move constructors
3470 : ExternalItem (ExternalItem &&other) = default;
3471 : ExternalItem &operator= (ExternalItem &&other) = default;
3472 :
3473 : // Clone function implementation as pure virtual method
3474 : virtual ExternalItem *clone_external_item_impl () const = 0;
3475 :
3476 : // possibly make this public if required
3477 : std::string get_item_name () const { return item_name; }
3478 : };
3479 : #endif
3480 :
3481 : // A foreign type defined outside the current crate.
3482 : // https://rust-lang.github.io/rfcs/1861-extern-types.html
3483 : class ExternalTypeItem : public ExternalItem
3484 : {
3485 : std::vector<Attribute> outer_attrs;
3486 :
3487 : Visibility visibility;
3488 : Identifier item_name;
3489 : location_t locus;
3490 :
3491 : bool marked_for_strip;
3492 :
3493 : public:
3494 7 : ExternalTypeItem (Identifier item_name, Visibility vis,
3495 : std::vector<Attribute> outer_attrs, location_t locus)
3496 7 : : ExternalItem (), outer_attrs (std::move (outer_attrs)), visibility (vis),
3497 7 : item_name (std::move (item_name)), locus (locus), marked_for_strip (false)
3498 7 : {}
3499 :
3500 : // copy constructor
3501 10 : ExternalTypeItem (ExternalTypeItem const &other)
3502 10 : : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3503 10 : visibility (other.visibility), item_name (other.item_name),
3504 10 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3505 : {
3506 10 : node_id = other.node_id;
3507 10 : }
3508 :
3509 : ExternalTypeItem &operator= (ExternalTypeItem const &other)
3510 : {
3511 : node_id = other.node_id;
3512 : outer_attrs = other.outer_attrs;
3513 : visibility = other.visibility;
3514 : item_name = other.item_name;
3515 : locus = other.locus;
3516 : marked_for_strip = other.marked_for_strip;
3517 :
3518 : return *this;
3519 : }
3520 :
3521 : // move constructors
3522 : ExternalTypeItem (ExternalTypeItem &&other) = default;
3523 : ExternalTypeItem &operator= (ExternalTypeItem &&other) = default;
3524 :
3525 : std::string as_string () const override;
3526 :
3527 : void accept_vis (ASTVisitor &vis) override;
3528 :
3529 : // Returns whether item has outer attributes.
3530 : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3531 :
3532 : // Returns whether item has non-default visibility.
3533 : bool has_visibility () const { return true; }
3534 :
3535 57 : location_t get_locus () const { return locus; }
3536 :
3537 0 : void mark_for_strip () override { marked_for_strip = true; };
3538 47 : bool is_marked_for_strip () const override { return marked_for_strip; };
3539 :
3540 : // TODO: this mutable getter seems really dodgy. Think up better way.
3541 259 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3542 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3543 :
3544 54 : Identifier get_identifier () const { return item_name; }
3545 :
3546 222 : Visibility &get_visibility () { return visibility; }
3547 : const Visibility &get_visibility () const { return visibility; }
3548 :
3549 : protected:
3550 : /* Use covariance to implement clone function as returning this object
3551 : * rather than base */
3552 10 : ExternalTypeItem *clone_external_item_impl () const override
3553 : {
3554 10 : return new ExternalTypeItem (*this);
3555 : }
3556 : };
3557 :
3558 : // A static item used in an extern block
3559 : class ExternalStaticItem : public ExternalItem
3560 : {
3561 : // bool has_outer_attrs;
3562 : std::vector<Attribute> outer_attrs;
3563 :
3564 : // bool has_visibility;
3565 : Visibility visibility;
3566 :
3567 : Identifier item_name;
3568 : location_t locus;
3569 :
3570 : bool has_mut;
3571 : std::unique_ptr<Type> item_type;
3572 :
3573 : public:
3574 1 : ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
3575 : bool is_mut, Visibility vis,
3576 : std::vector<Attribute> outer_attrs, location_t locus)
3577 1 : : ExternalItem (), outer_attrs (std::move (outer_attrs)),
3578 1 : visibility (std::move (vis)), item_name (std::move (item_name)),
3579 1 : locus (locus), has_mut (is_mut), item_type (std::move (item_type))
3580 1 : {}
3581 :
3582 : // Copy constructor
3583 2 : ExternalStaticItem (ExternalStaticItem const &other)
3584 2 : : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3585 2 : visibility (other.visibility), item_name (other.item_name),
3586 4 : locus (other.locus), has_mut (other.has_mut)
3587 : {
3588 2 : node_id = other.node_id;
3589 : // guard to prevent null dereference (only required if error state)
3590 2 : if (other.item_type != nullptr)
3591 2 : item_type = other.item_type->clone_type ();
3592 2 : }
3593 :
3594 : // Overloaded assignment operator to clone
3595 : ExternalStaticItem &operator= (ExternalStaticItem const &other)
3596 : {
3597 : node_id = other.node_id;
3598 : outer_attrs = other.outer_attrs;
3599 : visibility = other.visibility;
3600 : item_name = other.item_name;
3601 : locus = other.locus;
3602 : has_mut = other.has_mut;
3603 :
3604 : // guard to prevent null dereference (only required if error state)
3605 : if (other.item_type != nullptr)
3606 : item_type = other.item_type->clone_type ();
3607 : else
3608 : item_type = nullptr;
3609 :
3610 : return *this;
3611 : }
3612 :
3613 : // move constructors
3614 : ExternalStaticItem (ExternalStaticItem &&other) = default;
3615 : ExternalStaticItem &operator= (ExternalStaticItem &&other) = default;
3616 :
3617 : std::string as_string () const override;
3618 :
3619 : void accept_vis (ASTVisitor &vis) override;
3620 :
3621 : // Returns whether item has outer attributes.
3622 : bool has_outer_attrs () const { return !outer_attrs.empty (); }
3623 :
3624 : // Returns whether item has non-default visibility.
3625 : bool has_visibility () const { return true; }
3626 :
3627 4 : location_t get_locus () const { return locus; }
3628 :
3629 : // Based on idea that type should never be null.
3630 0 : void mark_for_strip () override { item_type = nullptr; };
3631 3 : bool is_marked_for_strip () const override { return item_type == nullptr; };
3632 :
3633 : // TODO: this mutable getter seems really dodgy. Think up better way.
3634 24 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3635 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3636 :
3637 : // TODO: is this better? Or is a "vis_block" better?
3638 19 : Type &get_type ()
3639 : {
3640 19 : rust_assert (item_type != nullptr);
3641 19 : return *item_type;
3642 : }
3643 :
3644 5 : std::unique_ptr<Type> &get_type_ptr ()
3645 : {
3646 5 : rust_assert (item_type != nullptr);
3647 5 : return item_type;
3648 : }
3649 :
3650 4 : Identifier get_identifier () const { return item_name; }
3651 :
3652 22 : Visibility &get_visibility () { return visibility; }
3653 :
3654 : const Visibility &get_visibility () const { return visibility; }
3655 :
3656 1 : bool is_mut () const { return has_mut; }
3657 :
3658 : protected:
3659 : /* Use covariance to implement clone function as returning this object
3660 : * rather than base */
3661 2 : ExternalStaticItem *clone_external_item_impl () const override
3662 : {
3663 2 : return new ExternalStaticItem (*this);
3664 : }
3665 : };
3666 :
3667 : // An extern block AST node
3668 : class ExternBlock : public VisItem
3669 : {
3670 : // bool has_abi;
3671 : std::string abi;
3672 :
3673 : // bool has_inner_attrs;
3674 : std::vector<Attribute> inner_attrs;
3675 :
3676 : // bool has_extern_items;
3677 : std::vector<std::unique_ptr<ExternalItem>> extern_items;
3678 :
3679 : location_t locus;
3680 :
3681 : // TODO: find another way to store this to save memory?
3682 : bool marked_for_strip = false;
3683 :
3684 : public:
3685 : std::string as_string () const override;
3686 :
3687 : // Returns whether extern block has inner attributes.
3688 : bool has_inner_attrs () const { return !inner_attrs.empty (); }
3689 :
3690 : // Returns whether extern block has extern items.
3691 0 : bool has_extern_items () const { return !extern_items.empty (); }
3692 :
3693 : // Returns whether extern block has ABI name.
3694 7000 : bool has_abi () const { return !abi.empty (); }
3695 :
3696 10454 : std::string get_abi () const { return abi; }
3697 :
3698 1786 : ExternBlock (std::string abi,
3699 : std::vector<std::unique_ptr<ExternalItem>> extern_items,
3700 : Visibility vis, std::vector<Attribute> inner_attrs,
3701 : std::vector<Attribute> outer_attrs, location_t locus)
3702 1786 : : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
3703 1786 : inner_attrs (std::move (inner_attrs)),
3704 1786 : extern_items (std::move (extern_items)), locus (locus)
3705 1786 : {}
3706 :
3707 : // Copy constructor with vector clone
3708 3973 : ExternBlock (ExternBlock const &other)
3709 3973 : : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
3710 7946 : locus (other.locus), marked_for_strip (other.marked_for_strip)
3711 : {
3712 3973 : extern_items.reserve (other.extern_items.size ());
3713 12983 : for (const auto &e : other.extern_items)
3714 9010 : extern_items.push_back (e->clone_external_item ());
3715 3973 : }
3716 :
3717 : // Overloaded assignment operator with vector clone
3718 : ExternBlock &operator= (ExternBlock const &other)
3719 : {
3720 : VisItem::operator= (other);
3721 : abi = other.abi;
3722 : inner_attrs = other.inner_attrs;
3723 : locus = other.locus;
3724 : marked_for_strip = other.marked_for_strip;
3725 :
3726 : extern_items.reserve (other.extern_items.size ());
3727 : for (const auto &e : other.extern_items)
3728 : extern_items.push_back (e->clone_external_item ());
3729 :
3730 : return *this;
3731 : }
3732 :
3733 : // move constructors
3734 : ExternBlock (ExternBlock &&other) = default;
3735 : ExternBlock &operator= (ExternBlock &&other) = default;
3736 :
3737 4767 : location_t get_locus () const override final { return locus; }
3738 :
3739 : void accept_vis (ASTVisitor &vis) override;
3740 :
3741 : // Can't think of any invalid invariants, so store boolean.
3742 0 : void mark_for_strip () override { marked_for_strip = true; }
3743 5427 : bool is_marked_for_strip () const override { return marked_for_strip; }
3744 :
3745 : // TODO: think of better way to do this
3746 : const std::vector<std::unique_ptr<ExternalItem>> &get_extern_items () const
3747 : {
3748 : return extern_items;
3749 : }
3750 12703 : std::vector<std::unique_ptr<ExternalItem>> &get_extern_items ()
3751 : {
3752 52115 : return extern_items;
3753 : }
3754 :
3755 : // TODO: think of better way to do this
3756 : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3757 50439 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3758 :
3759 68 : Item::Kind get_item_kind () const override { return Item::Kind::ExternBlock; }
3760 :
3761 : protected:
3762 : /* Use covariance to implement clone function as returning this object
3763 : * rather than base */
3764 2189 : ExternBlock *clone_item_impl () const override
3765 : {
3766 2189 : return new ExternBlock (*this);
3767 : }
3768 : };
3769 :
3770 : class MacroRulesDefinition;
3771 : } // namespace AST
3772 : } // namespace Rust
3773 :
3774 : #endif
|