libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / ast / rust-item.h
blobc03de9b1a9297ca2d56052945183b8cdd012ac74
1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
19 #ifndef RUST_AST_ITEM_H
20 #define RUST_AST_ITEM_H
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"
29 namespace Rust {
30 namespace AST {
31 // forward decls
32 class TypePath;
34 // TODO: inline?
35 /*struct AbiName {
36 std::string abi_name;
37 // Technically is meant to be STRING_LITERAL
39 public:
40 // Returns whether abi name is empty, i.e. doesn't exist.
41 bool is_empty() const {
42 return abi_name.empty();
45 AbiName(std::string name) : abi_name(std::move(name)) {}
47 // Empty AbiName constructor
48 AbiName() {}
49 };*/
51 // A type generic parameter (as opposed to a lifetime generic parameter)
52 class TypeParam : public GenericParam
54 // bool has_outer_attribute;
55 // std::unique_ptr<Attribute> outer_attr;
56 Attribute outer_attr;
58 Identifier type_representation;
60 // bool has_type_param_bounds;
61 // TypeParamBounds type_param_bounds;
62 std::vector<std::unique_ptr<TypeParamBound>>
63 type_param_bounds; // inlined form
65 // bool has_type;
66 std::unique_ptr<Type> type;
68 location_t locus;
70 public:
71 Identifier get_type_representation () const { return type_representation; }
73 // Returns whether the type of the type param has been specified.
74 bool has_type () const { return type != nullptr; }
76 // Returns whether the type param has type param bounds.
77 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
79 // Returns whether the type param has an outer attribute.
80 bool has_outer_attribute () const { return !outer_attr.is_empty (); }
82 Attribute &get_outer_attribute () { return outer_attr; }
84 TypeParam (Identifier type_representation, location_t locus = UNDEF_LOCATION,
85 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
86 = std::vector<std::unique_ptr<TypeParamBound>> (),
87 std::unique_ptr<Type> type = nullptr,
88 Attribute outer_attr = Attribute::create_empty ())
89 : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()),
90 outer_attr (std::move (outer_attr)),
91 type_representation (std::move (type_representation)),
92 type_param_bounds (std::move (type_param_bounds)),
93 type (std::move (type)), locus (locus)
96 // Copy constructor uses clone
97 TypeParam (TypeParam const &other)
98 : GenericParam (other.node_id), outer_attr (other.outer_attr),
99 type_representation (other.type_representation), locus (other.locus)
101 // guard to prevent null pointer dereference
102 if (other.type != nullptr)
103 type = other.type->clone_type ();
105 type_param_bounds.reserve (other.type_param_bounds.size ());
106 for (const auto &e : other.type_param_bounds)
107 type_param_bounds.push_back (e->clone_type_param_bound ());
110 // Overloaded assignment operator to clone
111 TypeParam &operator= (TypeParam const &other)
113 type_representation = other.type_representation;
114 outer_attr = other.outer_attr;
115 locus = other.locus;
116 node_id = other.node_id;
118 // guard to prevent null pointer dereference
119 if (other.type != nullptr)
120 type = other.type->clone_type ();
121 else
122 type = nullptr;
124 type_param_bounds.reserve (other.type_param_bounds.size ());
125 for (const auto &e : other.type_param_bounds)
126 type_param_bounds.push_back (e->clone_type_param_bound ());
128 return *this;
131 // move constructors
132 TypeParam (TypeParam &&other) = default;
133 TypeParam &operator= (TypeParam &&other) = default;
135 std::string as_string () const override;
137 location_t get_locus () const override final { return locus; }
139 Kind get_kind () const override final { return Kind::Type; }
141 void accept_vis (ASTVisitor &vis) override;
143 // TODO: is this better? Or is a "vis_block" better?
144 Type &get_type ()
146 rust_assert (type != nullptr);
147 return *type;
150 std::unique_ptr<Type> &get_type_ptr ()
152 rust_assert (type != nullptr);
153 return type;
156 // TODO: mutable getter seems kinda dodgy
157 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
159 return type_param_bounds;
161 const std::vector<std::unique_ptr<TypeParamBound>> &
162 get_type_param_bounds () const
164 return type_param_bounds;
167 protected:
168 // Clone function implementation as virtual method
169 TypeParam *clone_generic_param_impl () const override
171 return new TypeParam (*this);
175 /* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
176 * TypeBoundWhereClauseItem */
177 class WhereClauseItem
179 public:
180 virtual ~WhereClauseItem () {}
182 // Unique pointer custom clone function
183 std::unique_ptr<WhereClauseItem> clone_where_clause_item () const
185 return std::unique_ptr<WhereClauseItem> (clone_where_clause_item_impl ());
188 virtual std::string as_string () const = 0;
190 virtual void accept_vis (ASTVisitor &vis) = 0;
192 virtual NodeId get_node_id () const = 0;
194 protected:
195 // Clone function implementation as pure virtual method
196 virtual WhereClauseItem *clone_where_clause_item_impl () const = 0;
199 // A lifetime where clause item
200 class LifetimeWhereClauseItem : public WhereClauseItem
202 Lifetime lifetime;
203 std::vector<Lifetime> lifetime_bounds;
204 location_t locus;
205 NodeId node_id;
207 public:
208 LifetimeWhereClauseItem (Lifetime lifetime,
209 std::vector<Lifetime> lifetime_bounds,
210 location_t locus)
211 : lifetime (std::move (lifetime)),
212 lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
213 node_id (Analysis::Mappings::get ()->get_next_node_id ())
216 std::string as_string () const override;
218 void accept_vis (ASTVisitor &vis) override;
220 NodeId get_node_id () const override final { return node_id; }
222 Lifetime &get_lifetime () { return lifetime; }
224 std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
226 location_t get_locus () const { return locus; }
228 protected:
229 // Clone function implementation as (not pure) virtual method
230 LifetimeWhereClauseItem *clone_where_clause_item_impl () const override
232 return new LifetimeWhereClauseItem (*this);
236 // A type bound where clause item
237 class TypeBoundWhereClauseItem : public WhereClauseItem
239 std::vector<LifetimeParam> for_lifetimes;
240 std::unique_ptr<Type> bound_type;
241 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
242 NodeId node_id;
243 location_t locus;
245 public:
246 // Returns whether the item has ForLifetimes
247 bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
249 std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
251 // Returns whether the item has type param bounds
252 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
254 TypeBoundWhereClauseItem (
255 std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type,
256 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
257 location_t locus)
258 : for_lifetimes (std::move (for_lifetimes)),
259 bound_type (std::move (bound_type)),
260 type_param_bounds (std::move (type_param_bounds)),
261 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
264 // Copy constructor requires clone
265 TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
266 : for_lifetimes (other.for_lifetimes),
267 bound_type (other.bound_type->clone_type ())
269 node_id = other.node_id;
270 type_param_bounds.reserve (other.type_param_bounds.size ());
271 for (const auto &e : other.type_param_bounds)
272 type_param_bounds.push_back (e->clone_type_param_bound ());
275 // Overload assignment operator to clone
276 TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other)
278 node_id = other.node_id;
279 for_lifetimes = other.for_lifetimes;
280 bound_type = other.bound_type->clone_type ();
281 type_param_bounds.reserve (other.type_param_bounds.size ());
282 for (const auto &e : other.type_param_bounds)
283 type_param_bounds.push_back (e->clone_type_param_bound ());
285 return *this;
288 // move constructors
289 TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default;
290 TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other)
291 = default;
293 std::string as_string () const override;
295 void accept_vis (ASTVisitor &vis) override;
297 Type &get_type ()
299 rust_assert (bound_type != nullptr);
300 return *bound_type;
303 std::unique_ptr<Type> &get_type_ptr ()
305 rust_assert (bound_type != nullptr);
306 return bound_type;
309 // TODO: this mutable getter seems really dodgy. Think up better way.
310 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
312 return type_param_bounds;
315 const std::vector<std::unique_ptr<TypeParamBound>> &
316 get_type_param_bounds () const
318 return type_param_bounds;
321 NodeId get_node_id () const override final { return node_id; }
323 location_t get_locus () const { return locus; }
325 protected:
326 // Clone function implementation as (not pure) virtual method
327 TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
329 return new TypeBoundWhereClauseItem (*this);
333 // A where clause
334 class WhereClause
336 std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
337 NodeId node_id;
339 public:
340 WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
341 : where_clause_items (std::move (where_clause_items)),
342 node_id (Analysis::Mappings::get ()->get_next_node_id ())
345 // copy constructor with vector clone
346 WhereClause (WhereClause const &other)
348 node_id = other.node_id;
349 where_clause_items.reserve (other.where_clause_items.size ());
350 for (const auto &e : other.where_clause_items)
351 where_clause_items.push_back (e->clone_where_clause_item ());
354 // overloaded assignment operator with vector clone
355 WhereClause &operator= (WhereClause const &other)
357 node_id = other.node_id;
358 where_clause_items.reserve (other.where_clause_items.size ());
359 for (const auto &e : other.where_clause_items)
360 where_clause_items.push_back (e->clone_where_clause_item ());
362 return *this;
365 // move constructors
366 WhereClause (WhereClause &&other) = default;
367 WhereClause &operator= (WhereClause &&other) = default;
369 // Creates a WhereClause with no items.
370 static WhereClause create_empty ()
372 return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
375 // Returns whether the WhereClause has no items.
376 bool is_empty () const { return where_clause_items.empty (); }
378 std::string as_string () const;
380 NodeId get_node_id () const { return node_id; }
382 // TODO: this mutable getter seems kinda dodgy
383 std::vector<std::unique_ptr<WhereClauseItem>> &get_items ()
385 return where_clause_items;
387 const std::vector<std::unique_ptr<WhereClauseItem>> &get_items () const
389 return where_clause_items;
393 // Abstract class Param
394 class Param : public Visitable
396 public:
397 Param (std::vector<Attribute> outer_attrs, location_t locus)
398 : outer_attrs (std::move (outer_attrs)), locus (locus),
399 node_id (Analysis::Mappings::get ()->get_next_node_id ())
402 virtual ~Param () = default;
404 std::unique_ptr<Param> clone_param () const
406 return std::unique_ptr<Param> (clone_param_impl ());
409 virtual bool is_variadic () const { return false; }
411 virtual bool is_self () const { return false; }
413 NodeId get_node_id () const { return node_id; }
415 location_t get_locus () const { return locus; }
417 std::vector<Attribute> get_outer_attrs () const { return outer_attrs; }
419 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
421 virtual Param *clone_param_impl () const = 0;
423 virtual std::string as_string () const = 0;
425 protected:
426 std::vector<Attribute> outer_attrs;
427 location_t locus;
428 NodeId node_id;
431 // A self parameter in a method
432 class SelfParam : public Param
434 bool has_ref;
435 bool is_mut;
436 // bool has_lifetime; // only possible if also ref
437 Lifetime lifetime;
439 // bool has_type; // only possible if not ref
440 std::unique_ptr<Type> type;
442 // Unrestricted constructor used for error state
443 SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
444 : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
445 lifetime (std::move (lifetime)), type (type)
447 // this is ok as no outside classes can ever call this
449 // TODO: self param can have outer attributes
451 public:
452 // Returns whether the self-param has a type field.
453 bool has_type () const { return type != nullptr; }
455 // Returns whether the self-param has a valid lifetime.
456 bool has_lifetime () const { return !lifetime.is_error (); }
458 // Returns whether the self-param is in an error state.
459 bool is_error () const
461 return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
462 // not having either is not an error
465 // Creates an error state self-param.
466 static SelfParam create_error ()
468 // cannot have no ref but have a lifetime at the same time
469 return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
472 // Type-based self parameter (not ref, no lifetime)
473 SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
474 : Param ({}, locus), has_ref (false), is_mut (is_mut),
475 lifetime (Lifetime::error ()), type (std::move (type))
478 // Lifetime-based self parameter (is ref, no type)
479 SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
480 : Param ({}, locus), has_ref (true), is_mut (is_mut),
481 lifetime (std::move (lifetime))
484 // Copy constructor requires clone
485 SelfParam (SelfParam const &other)
486 : Param (other.get_outer_attrs (), other.get_locus ()),
487 has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime)
489 node_id = other.node_id;
490 if (other.type != nullptr)
491 type = other.type->clone_type ();
494 // Overload assignment operator to use clone
495 SelfParam &operator= (SelfParam const &other)
497 is_mut = other.is_mut;
498 has_ref = other.has_ref;
499 lifetime = other.lifetime;
500 locus = other.locus;
501 node_id = other.node_id;
502 outer_attrs = other.outer_attrs;
504 if (other.type != nullptr)
505 type = other.type->clone_type ();
506 else
507 type = nullptr;
509 return *this;
512 // move constructors
513 SelfParam (SelfParam &&other) = default;
514 SelfParam &operator= (SelfParam &&other) = default;
516 std::string as_string () const override;
518 location_t get_locus () const { return locus; }
520 bool is_self () const override { return true; }
522 bool get_has_ref () const { return has_ref; };
523 bool get_is_mut () const { return is_mut; }
525 Lifetime get_lifetime () const { return lifetime; }
526 Lifetime &get_lifetime () { return lifetime; }
528 NodeId get_node_id () const { return node_id; }
530 // TODO: is this better? Or is a "vis_block" better?
531 Type &get_type ()
533 rust_assert (has_type ());
534 return *type;
537 std::unique_ptr<Type> &get_type_ptr ()
539 rust_assert (has_type ());
540 return type;
543 void accept_vis (ASTVisitor &vis) override;
545 SelfParam *clone_param_impl () const override
547 return new SelfParam (*this);
551 // Qualifiers for function, i.e. const, unsafe, extern etc.
552 class FunctionQualifiers
554 Async async_status;
555 Const const_status;
556 Unsafety unsafe_status;
557 bool has_extern;
558 std::string extern_abi;
559 location_t locus;
561 public:
562 FunctionQualifiers (location_t locus, Async async_status, Const const_status,
563 Unsafety unsafe_status, bool has_extern = false,
564 std::string extern_abi = std::string ())
565 : async_status (async_status), const_status (const_status),
566 unsafe_status (unsafe_status), has_extern (has_extern),
567 extern_abi (std::move (extern_abi)), locus (locus)
569 if (!this->extern_abi.empty ())
571 // having extern is required; not having it is an implementation error
572 rust_assert (has_extern);
576 std::string as_string () const;
578 bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; }
579 bool is_extern () const { return has_extern; }
580 bool is_const () const { return const_status == Const::Yes; }
581 bool is_async () const { return async_status == Async::Yes; }
582 std::string get_extern_abi () const { return extern_abi; }
583 bool has_abi () const { return !extern_abi.empty (); }
584 Const get_const_status () const { return const_status; }
585 Async get_async_status () const { return async_status; }
587 location_t get_locus () const { return locus; }
590 class VariadicParam : public Param
592 std::unique_ptr<Pattern> param_name;
594 public:
595 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 param_name (std::move (param_name))
601 VariadicParam (std::vector<Attribute> outer_attrs, location_t locus)
602 : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr)
605 VariadicParam (VariadicParam const &other)
606 : Param (other.get_outer_attrs (), other.locus)
608 if (other.param_name != nullptr)
609 param_name = other.param_name->clone_pattern ();
612 VariadicParam &operator= (VariadicParam const &other)
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;
622 return *this;
625 bool is_variadic () const override { return true; }
627 VariadicParam *clone_param_impl () const override
629 return new VariadicParam (*this);
632 Pattern &get_pattern ()
634 rust_assert (param_name != nullptr);
635 return *param_name;
638 const Pattern &get_pattern () const
640 rust_assert (param_name != nullptr);
641 return *param_name;
644 bool has_pattern () const { return param_name != nullptr; }
646 void accept_vis (ASTVisitor &vis) override;
648 std::string as_string () const override;
651 // A function parameter
652 class FunctionParam : public Param
654 std::unique_ptr<Pattern> param_name;
655 std::unique_ptr<Type> type;
657 public:
658 FunctionParam (std::unique_ptr<Pattern> param_name,
659 std::unique_ptr<Type> param_type,
660 std::vector<Attribute> outer_attrs, location_t locus)
661 : Param (std::move (outer_attrs), locus),
662 param_name (std::move (param_name)), type (std::move (param_type))
665 // Copy constructor uses clone
666 FunctionParam (FunctionParam const &other)
667 : Param (other.get_outer_attrs (), other.locus)
669 // guard to prevent nullptr dereference
670 if (other.param_name != nullptr)
671 param_name = other.param_name->clone_pattern ();
672 if (other.type != nullptr)
673 type = other.type->clone_type ();
676 // Overload assignment operator to use clone
677 FunctionParam &operator= (FunctionParam const &other)
679 locus = other.locus;
680 node_id = other.node_id;
682 // guard to prevent nullptr dereference
683 if (other.param_name != nullptr)
684 param_name = other.param_name->clone_pattern ();
685 else
686 param_name = nullptr;
687 if (other.type != nullptr)
688 type = other.type->clone_type ();
689 else
690 type = nullptr;
692 return *this;
695 // move constructors
696 FunctionParam (FunctionParam &&other) = default;
697 FunctionParam &operator= (FunctionParam &&other) = default;
699 // Returns whether FunctionParam is in an invalid state.
700 bool is_error () const { return param_name == nullptr || type == nullptr; }
702 // Creates an error FunctionParam.
703 static FunctionParam create_error ()
705 return FunctionParam (nullptr, nullptr, {}, UNDEF_LOCATION);
708 std::string as_string () const override;
710 // TODO: seems kinda dodgy. Think of better way.
711 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
712 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
714 // TODO: is this better? Or is a "vis_block" better?
715 Pattern &get_pattern ()
717 rust_assert (param_name != nullptr);
718 return *param_name;
721 bool has_name () const { return param_name != nullptr; }
723 // TODO: is this better? Or is a "vis_block" better?
724 Type &get_type ()
726 rust_assert (type != nullptr);
727 return *type;
730 std::unique_ptr<Type> &get_type_ptr ()
732 rust_assert (type != nullptr);
733 return type;
736 FunctionParam *clone_param_impl () const override
738 return new FunctionParam (*this);
741 void accept_vis (ASTVisitor &vis) override;
744 // Rust module item - abstract base class
745 class Module : public VisItem
747 public:
748 // Type of the current module. A module can be either loaded or unloaded,
749 // meaning that the items of the module can already be present or not. For
750 // example, the following module would be loaded: `mod foo { fn bar() {} }`.
751 // However, the module would be unloaded if it refers to an external file (i.e
752 // `mod foo;`) and then become loaded upon expansion.
753 enum ModuleKind
755 LOADED,
756 UNLOADED,
759 Identifier get_name () const { return module_name; }
761 AST::Kind get_ast_kind () const override { return AST::Kind::MODULE; }
763 private:
764 Identifier module_name;
765 location_t locus;
766 ModuleKind kind;
767 Unsafety safety;
769 // Name of the file including the module
770 std::string outer_filename;
771 // bool has_inner_attrs;
772 std::vector<Attribute> inner_attrs;
773 // bool has_items;
774 std::vector<std::unique_ptr<Item>> items;
775 // Names of including inline modules (immediate parent is last in the list)
776 std::vector<std::string> module_scope;
778 // Filename the module refers to. Empty string on LOADED modules or if an
779 // error occured when dealing with UNLOADED modules
780 std::string module_file;
782 void clone_items (const std::vector<std::unique_ptr<Item>> &other_items)
784 items.reserve (other_items.size ());
785 for (const auto &e : other_items)
786 items.push_back (e->clone_item ());
789 public:
790 // Returns whether the module has items in its body.
791 bool has_items () const { return !items.empty (); }
793 // Returns whether the module has any inner attributes.
794 bool has_inner_attrs () const { return !inner_attrs.empty (); }
796 // Unloaded module constructor
797 Module (Identifier module_name, Visibility visibility,
798 std::vector<Attribute> outer_attrs, location_t locus, Unsafety safety,
799 std::string outer_filename, std::vector<std::string> module_scope)
800 : VisItem (std::move (visibility), std::move (outer_attrs)),
801 module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
802 safety (safety), outer_filename (outer_filename),
803 inner_attrs (std::vector<Attribute> ()),
804 items (std::vector<std::unique_ptr<Item>> ()),
805 module_scope (std::move (module_scope))
808 // Loaded module constructor, with items
809 Module (Identifier name, location_t locus,
810 std::vector<std::unique_ptr<Item>> items,
811 Visibility visibility = Visibility::create_error (),
812 Unsafety safety = Unsafety::Normal,
813 std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
814 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
815 : VisItem (std::move (visibility), std::move (outer_attrs)),
816 module_name (name), locus (locus), kind (ModuleKind::LOADED),
817 safety (safety), outer_filename (std::string ()),
818 inner_attrs (std::move (inner_attrs)), items (std::move (items))
821 // Copy constructor with vector clone
822 Module (Module const &other)
823 : VisItem (other), module_name (other.module_name), locus (other.locus),
824 kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs),
825 module_scope (other.module_scope)
827 // We need to check whether we are copying a loaded module or an unloaded
828 // one. In the second case, clear the `items` vector.
829 if (other.kind == LOADED)
830 clone_items (other.items);
831 else
832 items.clear ();
835 // Overloaded assignment operator with vector clone
836 Module &operator= (Module const &other)
838 VisItem::operator= (other);
840 module_name = other.module_name;
841 locus = other.locus;
842 kind = other.kind;
843 inner_attrs = other.inner_attrs;
844 module_scope = other.module_scope;
846 // Likewise, we need to clear the `items` vector in case the other module is
847 // unloaded
848 if (kind == LOADED)
849 clone_items (other.items);
850 else
851 items.clear ();
853 return *this;
856 // Search for the filename associated with an external module, storing it in
857 // module_file
858 void process_file_path ();
859 // Load the items contained in an external module
860 void load_items ();
862 void accept_vis (ASTVisitor &vis) override;
864 /* Override that runs the function recursively on all items contained within
865 * the module. */
866 void add_crate_name (std::vector<std::string> &names) const override;
868 // Returns the kind of the module
869 enum ModuleKind get_kind () const { return kind; }
871 Unsafety get_unsafety () const { return safety; }
873 // TODO: think of better way to do this - mutable getter seems dodgy
874 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
875 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
877 const std::vector<std::unique_ptr<Item>> &get_items () const { return items; }
878 std::vector<std::unique_ptr<Item>> &get_items () { return items; }
880 std::vector<std::unique_ptr<AST::Item>> take_items ()
882 return std::move (items);
885 void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
887 items = std::move (new_items);
890 // move constructors
891 Module (Module &&other) = default;
892 Module &operator= (Module &&other) = default;
894 std::string as_string () const override;
896 location_t get_locus () const override final { return locus; }
898 // Invalid if name is empty, so base stripping on that.
899 void mark_for_strip () override { module_name = {""}; }
900 bool is_marked_for_strip () const override { return module_name.empty (); }
902 protected:
903 /* Use covariance to implement clone function as returning this object
904 * rather than base */
905 Module *clone_item_impl () const override { return new Module (*this); }
908 // Rust extern crate declaration AST node
909 class ExternCrate : public VisItem
911 // this is either an identifier or "self", with self parsed to string
912 std::string referenced_crate;
913 // bool has_as_clause;
914 // AsClause as_clause;
915 // this is either an identifier or "_", with _ parsed to string
916 std::string as_clause_name;
918 location_t locus;
920 /* e.g.
921 "extern crate foo as _"
922 "extern crate foo"
923 "extern crate std as cool_std" */
924 public:
925 std::string as_string () const override;
927 // Returns whether extern crate declaration has an as clause.
928 bool has_as_clause () const { return !as_clause_name.empty (); }
930 /* Returns whether extern crate declaration references the current crate
931 * (i.e. self). */
932 bool references_self () const { return referenced_crate == "self"; }
934 // Constructor
935 ExternCrate (std::string referenced_crate, Visibility visibility,
936 std::vector<Attribute> outer_attrs, location_t locus,
937 std::string as_clause_name = std::string ())
938 : VisItem (std::move (visibility), std::move (outer_attrs)),
939 referenced_crate (std::move (referenced_crate)),
940 as_clause_name (std::move (as_clause_name)), locus (locus)
943 location_t get_locus () const override final { return locus; }
945 void accept_vis (ASTVisitor &vis) override;
947 const std::string &get_referenced_crate () const { return referenced_crate; }
948 const std::string &get_as_clause () const { return as_clause_name; }
950 // Override that adds extern crate name in decl to passed list of names.
951 void add_crate_name (std::vector<std::string> &names) const override
953 names.push_back (referenced_crate);
956 // Invalid if crate name is empty, so base stripping on that.
957 void mark_for_strip () override { referenced_crate = ""; }
958 bool is_marked_for_strip () const override
960 return referenced_crate.empty ();
963 protected:
964 /* Use covariance to implement clone function as returning this object
965 * rather than base */
966 ExternCrate *clone_item_impl () const override
968 return new ExternCrate (*this);
972 // The path-ish thing referred to in a use declaration - abstract base class
973 class UseTree
975 location_t locus;
976 NodeId node_id;
978 public:
979 enum Kind
981 Glob,
982 Rebind,
983 List,
986 virtual ~UseTree () {}
988 // Overload assignment operator to clone
989 UseTree &operator= (UseTree const &other)
991 locus = other.locus;
993 return *this;
996 UseTree (const UseTree &other) = default;
998 // move constructors
999 UseTree (UseTree &&other) = default;
1000 UseTree &operator= (UseTree &&other) = default;
1002 // Unique pointer custom clone function
1003 std::unique_ptr<UseTree> clone_use_tree () const
1005 return std::unique_ptr<UseTree> (clone_use_tree_impl ());
1008 virtual std::string as_string () const = 0;
1009 virtual Kind get_kind () const = 0;
1011 location_t get_locus () const { return locus; }
1012 NodeId get_node_id () const { return node_id; }
1014 virtual void accept_vis (ASTVisitor &vis) = 0;
1016 protected:
1017 // Clone function implementation as pure virtual method
1018 virtual UseTree *clone_use_tree_impl () const = 0;
1020 UseTree (location_t locus)
1021 : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
1025 // Use tree with a glob (wildcard) operator
1026 class UseTreeGlob : public UseTree
1028 public:
1029 enum PathType
1031 NO_PATH,
1032 GLOBAL,
1033 PATH_PREFIXED
1036 private:
1037 PathType glob_type;
1038 SimplePath path;
1040 public:
1041 UseTreeGlob (PathType glob_type, SimplePath path, location_t locus)
1042 : UseTree (locus), glob_type (glob_type), path (std::move (path))
1044 if (this->glob_type != PATH_PREFIXED)
1046 // compiler implementation error if there is a path with a
1047 // non-path-prefixed use tree glob
1048 rust_assert (!has_path ());
1050 // TODO: do path-prefixed paths also have to have a path? If so, have an
1051 // assert for that too.
1054 /* Returns whether has path. Should be made redundant by PathType
1055 * PATH_PREFIXED. */
1056 bool has_path () const { return !path.is_empty (); }
1058 std::string as_string () const override;
1060 void accept_vis (ASTVisitor &vis) override;
1062 PathType get_glob_type () { return glob_type; }
1064 Kind get_kind () const override { return Glob; }
1066 SimplePath get_path () const
1068 rust_assert (has_path ());
1069 return path;
1072 SimplePath &get_path () { return path; }
1074 /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory
1075 * methods? */
1076 protected:
1077 /* Use covariance to implement clone function as returning this object
1078 * rather than base */
1079 UseTreeGlob *clone_use_tree_impl () const override
1081 return new UseTreeGlob (*this);
1085 // Use tree with a list of paths with a common prefix
1086 class UseTreeList : public UseTree
1088 public:
1089 enum PathType
1091 NO_PATH,
1092 GLOBAL,
1093 PATH_PREFIXED
1096 private:
1097 PathType path_type;
1098 SimplePath path;
1100 std::vector<std::unique_ptr<UseTree>> trees;
1102 public:
1103 UseTreeList (PathType path_type, SimplePath path,
1104 std::vector<std::unique_ptr<UseTree>> trees, location_t locus)
1105 : UseTree (locus), path_type (path_type), path (std::move (path)),
1106 trees (std::move (trees))
1108 if (this->path_type != PATH_PREFIXED)
1110 // compiler implementation error if there is a path with a
1111 // non-path-prefixed use tree glob
1112 rust_assert (!has_path ());
1114 // TODO: do path-prefixed paths also have to have a path? If so, have an
1115 // assert for that too.
1118 // copy constructor with vector clone
1119 UseTreeList (UseTreeList const &other)
1120 : UseTree (other), path_type (other.path_type), path (other.path)
1122 trees.reserve (other.trees.size ());
1123 for (const auto &e : other.trees)
1124 trees.push_back (e->clone_use_tree ());
1127 // overloaded assignment operator with vector clone
1128 UseTreeList &operator= (UseTreeList const &other)
1130 UseTree::operator= (other);
1131 path_type = other.path_type;
1132 path = other.path;
1134 trees.reserve (other.trees.size ());
1135 for (const auto &e : other.trees)
1136 trees.push_back (e->clone_use_tree ());
1138 return *this;
1141 // move constructors
1142 UseTreeList (UseTreeList &&other) = default;
1143 UseTreeList &operator= (UseTreeList &&other) = default;
1145 // Returns whether has path. Should be made redundant by path_type.
1146 bool has_path () const { return !path.is_empty (); }
1148 // Returns whether has inner tree elements.
1149 bool has_trees () const { return !trees.empty (); }
1151 std::string as_string () const override;
1153 PathType get_path_type () { return path_type; }
1155 void accept_vis (ASTVisitor &vis) override;
1157 Kind get_kind () const override { return List; }
1158 SimplePath get_path () const
1160 rust_assert (has_path ());
1161 return path;
1164 SimplePath &get_path () { return path; }
1166 std::vector<std::unique_ptr<UseTree>> &get_trees () { return trees; }
1168 const std::vector<std::unique_ptr<UseTree>> &get_trees () const
1170 return trees;
1173 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1174 // methods?
1175 protected:
1176 /* Use covariance to implement clone function as returning this object
1177 * rather than base */
1178 UseTreeList *clone_use_tree_impl () const override
1180 return new UseTreeList (*this);
1184 // Use tree where it rebinds the module name as something else
1185 class UseTreeRebind : public UseTree
1187 public:
1188 enum NewBindType
1190 NONE,
1191 IDENTIFIER,
1192 WILDCARD
1195 private:
1196 SimplePath path;
1198 NewBindType bind_type;
1199 Identifier identifier; // only if NewBindType is IDENTIFIER
1201 public:
1202 UseTreeRebind (NewBindType bind_type, SimplePath path, location_t locus,
1203 Identifier identifier = std::string ())
1204 : UseTree (locus), path (std::move (path)), bind_type (bind_type),
1205 identifier (std::move (identifier))
1208 // Returns whether has path (this should always be true).
1209 bool has_path () const { return !path.is_empty (); }
1211 // Returns whether has identifier (or, rather, is allowed to).
1212 bool has_identifier () const { return bind_type == IDENTIFIER; }
1214 std::string as_string () const override;
1216 NewBindType get_new_bind_type () { return bind_type; }
1218 void accept_vis (ASTVisitor &vis) override;
1220 Kind get_kind () const override { return Rebind; }
1222 const SimplePath &get_path () const
1224 rust_assert (has_path ());
1225 return path;
1228 SimplePath &get_path () { return path; }
1230 const Identifier &get_identifier () const
1232 rust_assert (has_identifier ());
1233 return identifier;
1236 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1237 // methods?
1238 protected:
1239 /* Use covariance to implement clone function as returning this object
1240 * rather than base */
1241 virtual UseTreeRebind *clone_use_tree_impl () const override
1243 return new UseTreeRebind (*this);
1247 // Rust use declaration (i.e. for modules) AST node
1248 class UseDeclaration : public VisItem
1250 std::unique_ptr<UseTree> use_tree;
1251 location_t locus;
1253 public:
1254 std::string as_string () const override;
1256 UseDeclaration (std::unique_ptr<UseTree> use_tree, Visibility visibility,
1257 std::vector<Attribute> outer_attrs, location_t locus)
1258 : VisItem (std::move (visibility), std::move (outer_attrs)),
1259 use_tree (std::move (use_tree)), locus (locus)
1262 // Copy constructor with clone
1263 UseDeclaration (UseDeclaration const &other)
1264 : VisItem (other), locus (other.locus)
1266 // guard to prevent null dereference (only required if error state)
1267 if (other.use_tree != nullptr)
1268 use_tree = other.use_tree->clone_use_tree ();
1271 // Overloaded assignment operator to clone
1272 UseDeclaration &operator= (UseDeclaration const &other)
1274 VisItem::operator= (other);
1275 // visibility = other.visibility->clone_visibility();
1276 // outer_attrs = other.outer_attrs;
1277 locus = other.locus;
1279 // guard to prevent null dereference (only required if error state)
1280 if (other.use_tree != nullptr)
1281 use_tree = other.use_tree->clone_use_tree ();
1282 else
1283 use_tree = nullptr;
1285 return *this;
1288 // move constructors
1289 UseDeclaration (UseDeclaration &&other) = default;
1290 UseDeclaration &operator= (UseDeclaration &&other) = default;
1292 location_t get_locus () const override final { return locus; }
1294 std::unique_ptr<UseTree> &get_tree () { return use_tree; }
1296 const std::unique_ptr<UseTree> &get_tree () const { return use_tree; }
1298 void accept_vis (ASTVisitor &vis) override;
1300 // Invalid if use tree is null, so base stripping on that.
1301 void mark_for_strip () override { use_tree = nullptr; }
1302 bool is_marked_for_strip () const override { return use_tree == nullptr; }
1304 protected:
1305 /* Use covariance to implement clone function as returning this object
1306 * rather than base */
1307 UseDeclaration *clone_item_impl () const override
1309 return new UseDeclaration (*this);
1313 class LetStmt;
1315 // Rust function declaration AST node
1316 class Function : public VisItem, public AssociatedItem, public ExternalItem
1318 FunctionQualifiers qualifiers;
1319 Identifier function_name;
1320 std::vector<std::unique_ptr<GenericParam>> generic_params;
1321 std::vector<std::unique_ptr<Param>> function_params;
1322 std::unique_ptr<Type> return_type;
1323 WhereClause where_clause;
1324 tl::optional<std::unique_ptr<BlockExpr>> function_body;
1325 location_t locus;
1326 bool is_default;
1327 bool is_external_function;
1329 public:
1330 std::string as_string () const override;
1332 // Returns whether function has generic parameters.
1333 bool has_generics () const { return !generic_params.empty (); }
1335 // Returns whether function has regular parameters.
1336 bool has_function_params () const { return !function_params.empty (); }
1338 // Returns whether function has return type - if not, it is void.
1339 bool has_return_type () const { return return_type != nullptr; }
1341 // Returns whether function has a where clause.
1342 bool has_where_clause () const { return !where_clause.is_empty (); }
1344 bool has_self_param () const
1346 return function_params.size () > 0 && function_params[0]->is_self ();
1349 bool has_body () const { return function_body.has_value (); }
1351 // Mega-constructor with all possible fields
1352 Function (Identifier function_name, FunctionQualifiers qualifiers,
1353 std::vector<std::unique_ptr<GenericParam>> generic_params,
1354 std::vector<std::unique_ptr<Param>> function_params,
1355 std::unique_ptr<Type> return_type, WhereClause where_clause,
1356 tl::optional<std::unique_ptr<BlockExpr>> function_body,
1357 Visibility vis, std::vector<Attribute> outer_attrs,
1358 location_t locus, bool is_default = false,
1359 bool is_external_function = false)
1360 : VisItem (std::move (vis), std::move (outer_attrs)),
1361 ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
1362 function_name (std::move (function_name)),
1363 generic_params (std::move (generic_params)),
1364 function_params (std::move (function_params)),
1365 return_type (std::move (return_type)),
1366 where_clause (std::move (where_clause)),
1367 function_body (std::move (function_body)), locus (locus),
1368 is_default (is_default), is_external_function (is_external_function)
1371 // TODO: add constructor with less fields
1373 // Copy constructor with clone
1374 Function (Function const &other);
1376 // Overloaded assignment operator to clone
1377 Function &operator= (Function const &other);
1379 // move constructors
1380 Function (Function &&other) = default;
1381 Function &operator= (Function &&other) = default;
1383 location_t get_locus () const override final { return locus; }
1385 void accept_vis (ASTVisitor &vis) override;
1387 bool is_variadic () const
1389 return function_params.size () != 0
1390 && function_params.back ()->is_variadic ();
1393 bool is_external () const { return is_external_function; }
1395 // Invalid if block is null, so base stripping on that.
1396 void mark_for_strip () override { function_body = nullptr; }
1397 bool is_marked_for_strip () const override
1399 return function_body == nullptr;
1402 std::vector<std::unique_ptr<Param>> &get_function_params ()
1404 return function_params;
1406 const std::vector<std::unique_ptr<Param>> &get_function_params () const
1408 return function_params;
1411 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1413 return generic_params;
1415 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1417 return generic_params;
1420 // TODO: is this better? Or is a "vis_block" better?
1421 tl::optional<std::unique_ptr<BlockExpr>> &get_definition ()
1423 return function_body;
1426 const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
1428 FunctionQualifiers &get_qualifiers () { return qualifiers; }
1430 Identifier get_function_name () const { return function_name; }
1432 // TODO: is this better? Or is a "vis_block" better?
1433 WhereClause &get_where_clause () { return where_clause; }
1435 // TODO: is this better? Or is a "vis_block" better?
1436 Type &get_return_type ()
1438 rust_assert (has_return_type ());
1439 return *return_type;
1442 std::unique_ptr<Type> &get_return_type_ptr ()
1444 rust_assert (has_return_type ());
1445 return return_type;
1448 Param &get_self_param ()
1450 rust_assert (has_self_param ());
1451 return *function_params[0];
1453 const Param &get_self_param () const
1455 rust_assert (has_self_param ());
1456 return *function_params[0];
1459 // ExternalItem::node_id is same as Stmt::node_id
1460 NodeId get_node_id () const override { return Stmt::node_id; }
1462 protected:
1463 /* Use covariance to implement clone function as returning this object
1464 * rather than base */
1465 Function *clone_item_impl () const override { return new Function (*this); }
1467 /* Use covariance to implement clone function as returning this object
1468 * rather than base */
1469 Function *clone_associated_item_impl () const override
1471 return new Function (*this);
1474 /* Use covariance to implement clone function as returning this object
1475 * rather than base */
1476 Function *clone_external_item_impl () const override
1478 return new Function (*this);
1482 // Rust type alias (i.e. typedef) AST node
1483 class TypeAlias : public VisItem, public AssociatedItem
1485 Identifier new_type_name;
1487 // bool has_generics;
1488 // Generics generic_params;
1489 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1491 // bool has_where_clause;
1492 WhereClause where_clause;
1494 std::unique_ptr<Type> existing_type;
1496 location_t locus;
1498 public:
1499 std::string as_string () const override;
1501 // Returns whether type alias has generic parameters.
1502 bool has_generics () const { return !generic_params.empty (); }
1504 // Returns whether type alias has a where clause.
1505 bool has_where_clause () const { return !where_clause.is_empty (); }
1507 // Mega-constructor with all possible fields
1508 TypeAlias (Identifier new_type_name,
1509 std::vector<std::unique_ptr<GenericParam>> generic_params,
1510 WhereClause where_clause, std::unique_ptr<Type> existing_type,
1511 Visibility vis, std::vector<Attribute> outer_attrs,
1512 location_t locus)
1513 : VisItem (std::move (vis), std::move (outer_attrs)),
1514 new_type_name (std::move (new_type_name)),
1515 generic_params (std::move (generic_params)),
1516 where_clause (std::move (where_clause)),
1517 existing_type (std::move (existing_type)), locus (locus)
1520 // Copy constructor
1521 TypeAlias (TypeAlias const &other)
1522 : VisItem (other), new_type_name (other.new_type_name),
1523 where_clause (other.where_clause), locus (other.locus)
1525 // guard to prevent null dereference (only required if error state)
1526 if (other.existing_type != nullptr)
1527 existing_type = other.existing_type->clone_type ();
1529 generic_params.reserve (other.generic_params.size ());
1530 for (const auto &e : other.generic_params)
1531 generic_params.push_back (e->clone_generic_param ());
1534 // Overloaded assignment operator to clone
1535 TypeAlias &operator= (TypeAlias const &other)
1537 VisItem::operator= (other);
1538 new_type_name = other.new_type_name;
1539 where_clause = other.where_clause;
1540 // visibility = other.visibility->clone_visibility();
1541 // outer_attrs = other.outer_attrs;
1542 locus = other.locus;
1544 // guard to prevent null dereference (only required if error state)
1545 if (other.existing_type != nullptr)
1546 existing_type = other.existing_type->clone_type ();
1547 else
1548 existing_type = nullptr;
1550 generic_params.reserve (other.generic_params.size ());
1551 for (const auto &e : other.generic_params)
1552 generic_params.push_back (e->clone_generic_param ());
1554 return *this;
1557 // move constructors
1558 TypeAlias (TypeAlias &&other) = default;
1559 TypeAlias &operator= (TypeAlias &&other) = default;
1561 location_t get_locus () const override final { return locus; }
1563 void accept_vis (ASTVisitor &vis) override;
1565 // Invalid if existing type is null, so base stripping on that.
1566 void mark_for_strip () override { existing_type = nullptr; }
1567 bool is_marked_for_strip () const override
1569 return existing_type == nullptr;
1572 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1574 return generic_params;
1576 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1578 return generic_params;
1581 // TODO: is this better? Or is a "vis_block" better?
1582 WhereClause &get_where_clause () { return where_clause; }
1584 // TODO: is this better? Or is a "vis_block" better?
1585 Type &get_type_aliased ()
1587 rust_assert (existing_type != nullptr);
1588 return *existing_type;
1591 Identifier get_new_type_name () const { return new_type_name; }
1593 protected:
1594 /* Use covariance to implement clone function as returning this object
1595 * rather than base */
1596 TypeAlias *clone_item_impl () const override { return new TypeAlias (*this); }
1598 /* Use covariance to implement clone function as returning this object
1599 * rather than base */
1600 TypeAlias *clone_associated_item_impl () const override
1602 return new TypeAlias (*this);
1606 // Rust base struct declaration AST node - abstract base class
1607 class Struct : public VisItem
1609 protected:
1610 // protected to enable access by derived classes - allows better as_string
1611 Identifier struct_name;
1613 // bool has_generics;
1614 // Generics generic_params;
1615 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1617 // bool has_where_clause;
1618 WhereClause where_clause;
1620 private:
1621 location_t locus;
1623 public:
1624 // Returns whether struct has generic parameters.
1625 bool has_generics () const { return !generic_params.empty (); }
1627 // Returns whether struct has a where clause.
1628 bool has_where_clause () const { return !where_clause.is_empty (); }
1630 location_t get_locus () const override final { return locus; }
1632 // Invalid if name is empty, so base stripping on that.
1633 void mark_for_strip () override { struct_name = {""}; }
1634 bool is_marked_for_strip () const override { return struct_name.empty (); }
1636 Identifier get_struct_name () const { return struct_name; }
1638 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1640 return generic_params;
1642 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1644 return generic_params;
1647 // TODO: is this better? Or is a "vis_block" better?
1648 WhereClause &get_where_clause () { return where_clause; }
1650 Identifier get_identifier () const { return struct_name; }
1652 protected:
1653 Struct (Identifier struct_name,
1654 std::vector<std::unique_ptr<GenericParam>> generic_params,
1655 WhereClause where_clause, Visibility vis, location_t locus,
1656 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1657 : VisItem (std::move (vis), std::move (outer_attrs)),
1658 struct_name (std::move (struct_name)),
1659 generic_params (std::move (generic_params)),
1660 where_clause (std::move (where_clause)), locus (locus)
1663 // Copy constructor with vector clone
1664 Struct (Struct const &other)
1665 : VisItem (other), struct_name (other.struct_name),
1666 where_clause (other.where_clause), locus (other.locus)
1668 generic_params.reserve (other.generic_params.size ());
1669 for (const auto &e : other.generic_params)
1670 generic_params.push_back (e->clone_generic_param ());
1673 // Overloaded assignment operator with vector clone
1674 Struct &operator= (Struct const &other)
1676 VisItem::operator= (other);
1677 struct_name = other.struct_name;
1678 where_clause = other.where_clause;
1679 locus = other.locus;
1681 generic_params.reserve (other.generic_params.size ());
1682 for (const auto &e : other.generic_params)
1683 generic_params.push_back (e->clone_generic_param ());
1685 return *this;
1688 // move constructors
1689 Struct (Struct &&other) = default;
1690 Struct &operator= (Struct &&other) = default;
1693 // A single field in a struct
1694 class StructField
1696 // bool has_outer_attributes;
1697 std::vector<Attribute> outer_attrs;
1699 // bool has_visibility;
1700 Visibility visibility;
1702 Identifier field_name;
1703 std::unique_ptr<Type> field_type;
1705 NodeId node_id;
1707 location_t locus;
1709 public:
1710 // Returns whether struct field has any outer attributes.
1711 bool has_outer_attributes () const { return !outer_attrs.empty (); }
1713 // Returns whether struct field has a non-private (non-default) visibility.
1714 bool has_visibility () const { return !visibility.is_error (); }
1716 StructField (Identifier field_name, std::unique_ptr<Type> field_type,
1717 Visibility vis, location_t locus,
1718 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1719 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1720 field_name (std::move (field_name)), field_type (std::move (field_type)),
1721 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
1724 // Copy constructor
1725 StructField (StructField const &other)
1726 : outer_attrs (other.outer_attrs), visibility (other.visibility),
1727 field_name (other.field_name), node_id (other.node_id),
1728 locus (other.locus)
1730 // guard to prevent null dereference
1731 if (other.field_type != nullptr)
1732 field_type = other.field_type->clone_type ();
1735 ~StructField () = default;
1737 // Overloaded assignment operator to clone
1738 StructField &operator= (StructField const &other)
1740 field_name = other.field_name;
1741 visibility = other.visibility;
1742 outer_attrs = other.outer_attrs;
1743 node_id = other.node_id;
1745 // guard to prevent null dereference
1746 if (other.field_type != nullptr)
1747 field_type = other.field_type->clone_type ();
1748 else
1749 field_type = nullptr;
1751 return *this;
1754 // move constructors
1755 StructField (StructField &&other) = default;
1756 StructField &operator= (StructField &&other) = default;
1758 // Returns whether struct field is in an error state.
1759 bool is_error () const
1761 return field_name.empty () && field_type == nullptr;
1762 // this should really be an or since neither are allowed
1765 // Creates an error state struct field.
1766 static StructField create_error ()
1768 return StructField (std::string (""), nullptr, Visibility::create_error (),
1769 UNDEF_LOCATION);
1772 std::string as_string () const;
1774 // TODO: this mutable getter seems really dodgy. Think up better way.
1775 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1776 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1778 Identifier get_field_name () const { return field_name; }
1780 location_t get_locus () const { return locus; }
1782 // TODO: is this better? Or is a "vis_block" better?
1783 Type &get_field_type ()
1785 rust_assert (field_type != nullptr);
1786 return *field_type;
1789 std::unique_ptr<Type> &get_field_type_ptr ()
1791 rust_assert (field_type != nullptr);
1792 return field_type;
1795 Visibility &get_visibility () { return visibility; }
1796 const Visibility &get_visibility () const { return visibility; }
1798 NodeId get_node_id () const { return node_id; }
1801 // Rust struct declaration with true struct type AST node
1802 class StructStruct : public Struct
1804 std::vector<StructField> fields;
1805 bool is_unit;
1807 public:
1808 std::string as_string () const override;
1810 // Mega-constructor with all possible fields
1811 StructStruct (std::vector<StructField> fields, Identifier struct_name,
1812 std::vector<std::unique_ptr<GenericParam>> generic_params,
1813 WhereClause where_clause, bool is_unit, Visibility vis,
1814 std::vector<Attribute> outer_attrs, location_t locus)
1815 : Struct (std::move (struct_name), std::move (generic_params),
1816 std::move (where_clause), std::move (vis), locus,
1817 std::move (outer_attrs)),
1818 fields (std::move (fields)), is_unit (is_unit)
1821 // Unit struct constructor
1822 StructStruct (Identifier struct_name,
1823 std::vector<std::unique_ptr<GenericParam>> generic_params,
1824 WhereClause where_clause, Visibility vis,
1825 std::vector<Attribute> outer_attrs, location_t locus)
1826 : Struct (std::move (struct_name), std::move (generic_params),
1827 std::move (where_clause), std::move (vis), locus,
1828 std::move (outer_attrs)),
1829 is_unit (true)
1832 /* Returns whether the struct is a unit struct - struct defined without
1833 * fields. This is important because it also means an implicit constant of its
1834 * type is defined. */
1835 bool is_unit_struct () const { return is_unit; }
1837 void accept_vis (ASTVisitor &vis) override;
1839 // TODO: this mutable getter seems really dodgy. Think up better way.
1840 std::vector<StructField> &get_fields () { return fields; }
1841 const std::vector<StructField> &get_fields () const { return fields; }
1843 protected:
1844 /* Use covariance to implement clone function as returning this object
1845 * rather than base */
1846 StructStruct *clone_item_impl () const override
1848 return new StructStruct (*this);
1852 // A single field in a tuple
1853 class TupleField
1855 // bool has_outer_attributes;
1856 std::vector<Attribute> outer_attrs;
1858 // bool has_visibility;
1859 Visibility visibility;
1861 std::unique_ptr<Type> field_type;
1863 NodeId node_id;
1865 location_t locus;
1867 public:
1868 // Returns whether tuple field has outer attributes.
1869 bool has_outer_attributes () const { return !outer_attrs.empty (); }
1871 /* Returns whether tuple field has a non-default visibility (i.e. a public
1872 * one) */
1873 bool has_visibility () const { return !visibility.is_error (); }
1875 // Complete constructor
1876 TupleField (std::unique_ptr<Type> field_type, Visibility vis,
1877 location_t locus,
1878 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1879 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1880 field_type (std::move (field_type)),
1881 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
1884 // Copy constructor with clone
1885 TupleField (TupleField const &other)
1886 : outer_attrs (other.outer_attrs), visibility (other.visibility),
1887 node_id (other.node_id), locus (other.locus)
1889 // guard to prevent null dereference (only required if error)
1890 if (other.field_type != nullptr)
1891 field_type = other.field_type->clone_type ();
1894 ~TupleField () = default;
1896 // Overloaded assignment operator to clone
1897 TupleField &operator= (TupleField const &other)
1899 visibility = other.visibility;
1900 outer_attrs = other.outer_attrs;
1901 node_id = other.node_id;
1902 locus = other.locus;
1904 // guard to prevent null dereference (only required if error)
1905 if (other.field_type != nullptr)
1906 field_type = other.field_type->clone_type ();
1907 else
1908 field_type = nullptr;
1910 return *this;
1913 // move constructors
1914 TupleField (TupleField &&other) = default;
1915 TupleField &operator= (TupleField &&other) = default;
1917 // Returns whether tuple field is in an error state.
1918 bool is_error () const { return field_type == nullptr; }
1920 // Creates an error state tuple field.
1921 static TupleField create_error ()
1923 return TupleField (nullptr, Visibility::create_error (), UNDEF_LOCATION);
1926 std::string as_string () const;
1928 NodeId get_node_id () const { return node_id; }
1930 Visibility &get_visibility () { return visibility; }
1931 const Visibility &get_visibility () const { return visibility; }
1933 location_t get_locus () const { return locus; }
1935 // TODO: this mutable getter seems really dodgy. Think up better way.
1936 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1937 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1939 // TODO: is this better? Or is a "vis_block" better?
1940 Type &get_field_type ()
1942 rust_assert (field_type != nullptr);
1943 return *field_type;
1946 std::unique_ptr<Type> &get_field_type_ptr ()
1948 rust_assert (field_type != nullptr);
1949 return field_type;
1953 // Rust tuple declared using struct keyword AST node
1954 class TupleStruct : public Struct
1956 std::vector<TupleField> fields;
1958 public:
1959 std::string as_string () const override;
1961 // Mega-constructor with all possible fields
1962 TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
1963 std::vector<std::unique_ptr<GenericParam>> generic_params,
1964 WhereClause where_clause, Visibility vis,
1965 std::vector<Attribute> outer_attrs, location_t locus)
1966 : Struct (std::move (struct_name), std::move (generic_params),
1967 std::move (where_clause), std::move (vis), locus,
1968 std::move (outer_attrs)),
1969 fields (std::move (fields))
1972 void accept_vis (ASTVisitor &vis) override;
1974 // TODO: this mutable getter seems really dodgy. Think up better way.
1975 std::vector<TupleField> &get_fields () { return fields; }
1976 const std::vector<TupleField> &get_fields () const { return fields; }
1978 protected:
1979 /* Use covariance to implement clone function as returning this object
1980 * rather than base */
1981 TupleStruct *clone_item_impl () const override
1983 return new TupleStruct (*this);
1987 /* An item used in an "enum" tagged union - not abstract: base represents a
1988 * name-only enum. EnumItems (variants) syntactically allow a Visibility
1989 * annotation. */
1990 class EnumItem : public VisItem
1992 Identifier variant_name;
1994 location_t locus;
1996 public:
1997 virtual ~EnumItem () {}
1999 EnumItem (Identifier variant_name, Visibility vis,
2000 std::vector<Attribute> outer_attrs, location_t locus)
2001 : VisItem (std::move (vis), std::move (outer_attrs)),
2002 variant_name (std::move (variant_name)), locus (locus)
2005 // Unique pointer custom clone function
2006 std::unique_ptr<EnumItem> clone_enum_item () const
2008 return std::unique_ptr<EnumItem> (clone_item_impl ());
2011 virtual std::string as_string () const override;
2013 // not pure virtual as not abstract
2014 virtual void accept_vis (ASTVisitor &vis) override;
2016 location_t get_locus () const override { return locus; }
2018 Identifier get_identifier () const { return variant_name; }
2020 // Based on idea that name is never empty.
2021 void mark_for_strip () override { variant_name = {""}; }
2022 bool is_marked_for_strip () const override { return variant_name.empty (); }
2024 protected:
2025 EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
2028 // A tuple item used in an "enum" tagged union
2029 class EnumItemTuple : public EnumItem
2031 // bool has_tuple_fields;
2032 std::vector<TupleField> tuple_fields;
2034 public:
2035 // Returns whether tuple enum item has tuple fields.
2036 bool has_tuple_fields () const { return !tuple_fields.empty (); }
2038 EnumItemTuple (Identifier variant_name, Visibility vis,
2039 std::vector<TupleField> tuple_fields,
2040 std::vector<Attribute> outer_attrs, location_t locus)
2041 : EnumItem (std::move (variant_name), std::move (vis),
2042 std::move (outer_attrs), locus),
2043 tuple_fields (std::move (tuple_fields))
2046 std::string as_string () const override;
2048 void accept_vis (ASTVisitor &vis) override;
2050 // TODO: this mutable getter seems really dodgy. Think up better way.
2051 std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
2052 const std::vector<TupleField> &get_tuple_fields () const
2054 return tuple_fields;
2057 protected:
2058 // Clone function implementation as (not pure) virtual method
2059 EnumItemTuple *clone_item_impl () const override
2061 return new EnumItemTuple (*this);
2065 // A struct item used in an "enum" tagged union
2066 class EnumItemStruct : public EnumItem
2068 // bool has_struct_fields;
2069 std::vector<StructField> struct_fields;
2071 public:
2072 // Returns whether struct enum item has struct fields.
2073 bool has_struct_fields () const { return !struct_fields.empty (); }
2075 EnumItemStruct (Identifier variant_name, Visibility vis,
2076 std::vector<StructField> struct_fields,
2077 std::vector<Attribute> outer_attrs, location_t locus)
2078 : EnumItem (std::move (variant_name), std::move (vis),
2079 std::move (outer_attrs), locus),
2080 struct_fields (std::move (struct_fields))
2083 std::string as_string () const override;
2085 void accept_vis (ASTVisitor &vis) override;
2087 // TODO: this mutable getter seems really dodgy. Think up better way.
2088 std::vector<StructField> &get_struct_fields () { return struct_fields; }
2089 const std::vector<StructField> &get_struct_fields () const
2091 return struct_fields;
2094 protected:
2095 // Clone function implementation as (not pure) virtual method
2096 EnumItemStruct *clone_item_impl () const override
2098 return new EnumItemStruct (*this);
2102 // A discriminant (numbered enum) item used in an "enum" tagged union
2103 class EnumItemDiscriminant : public EnumItem
2105 std::unique_ptr<Expr> expression;
2107 public:
2108 EnumItemDiscriminant (Identifier variant_name, Visibility vis,
2109 std::unique_ptr<Expr> expr,
2110 std::vector<Attribute> outer_attrs, location_t locus)
2111 : EnumItem (std::move (variant_name), std::move (vis),
2112 std::move (outer_attrs), locus),
2113 expression (std::move (expr))
2116 // Copy constructor with clone
2117 EnumItemDiscriminant (EnumItemDiscriminant const &other)
2118 : EnumItem (other), expression (other.expression->clone_expr ())
2121 // Overloaded assignment operator to clone
2122 EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other)
2124 EnumItem::operator= (other);
2125 expression = other.expression->clone_expr ();
2126 // variant_name = other.variant_name;
2127 // outer_attrs = other.outer_attrs;
2129 return *this;
2132 // move constructors
2133 EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
2134 EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
2136 std::string as_string () const override;
2138 void accept_vis (ASTVisitor &vis) override;
2140 bool has_expr () { return expression != nullptr; }
2142 // TODO: is this better? Or is a "vis_block" better?
2143 Expr &get_expr ()
2145 rust_assert (expression != nullptr);
2146 return *expression;
2149 std::unique_ptr<Expr> &get_expr_ptr ()
2151 rust_assert (expression != nullptr);
2152 return expression;
2155 protected:
2156 // Clone function implementation as (not pure) virtual method
2157 EnumItemDiscriminant *clone_item_impl () const override
2159 return new EnumItemDiscriminant (*this);
2163 // AST node for Rust "enum" - tagged union
2164 class Enum : public VisItem
2166 Identifier enum_name;
2168 // bool has_generics;
2169 // Generics generic_params;
2170 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2172 // bool has_where_clause;
2173 WhereClause where_clause;
2175 std::vector<std::unique_ptr<EnumItem>> items;
2177 location_t locus;
2179 public:
2180 std::string as_string () const override;
2182 // Returns whether "enum" has generic parameters.
2183 bool has_generics () const { return !generic_params.empty (); }
2185 // Returns whether "enum" has a where clause.
2186 bool has_where_clause () const { return !where_clause.is_empty (); }
2188 /* Returns whether enum is a "zero-variant" (no possible variant) enum,
2189 * which cannot be instantiated. */
2190 bool is_zero_variant () const { return items.empty (); }
2192 // Mega-constructor
2193 Enum (Identifier enum_name, Visibility vis,
2194 std::vector<std::unique_ptr<GenericParam>> generic_params,
2195 WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
2196 std::vector<Attribute> outer_attrs, location_t locus)
2197 : VisItem (std::move (vis), std::move (outer_attrs)),
2198 enum_name (std::move (enum_name)),
2199 generic_params (std::move (generic_params)),
2200 where_clause (std::move (where_clause)), items (std::move (items)),
2201 locus (locus)
2204 // TODO: constructor with less arguments
2206 // Copy constructor with vector clone
2207 Enum (Enum const &other)
2208 : VisItem (other), enum_name (other.enum_name),
2209 where_clause (other.where_clause), locus (other.locus)
2211 generic_params.reserve (other.generic_params.size ());
2212 for (const auto &e : other.generic_params)
2213 generic_params.push_back (e->clone_generic_param ());
2215 items.reserve (other.items.size ());
2216 for (const auto &e : other.items)
2217 items.push_back (e->clone_enum_item ());
2220 // Overloaded assignment operator with vector clone
2221 Enum &operator= (Enum const &other)
2223 VisItem::operator= (other);
2224 enum_name = other.enum_name;
2225 where_clause = other.where_clause;
2226 locus = other.locus;
2228 generic_params.reserve (other.generic_params.size ());
2229 for (const auto &e : other.generic_params)
2230 generic_params.push_back (e->clone_generic_param ());
2232 items.reserve (other.items.size ());
2233 for (const auto &e : other.items)
2234 items.push_back (e->clone_enum_item ());
2236 return *this;
2239 // Move constructors
2240 Enum (Enum &&other) = default;
2241 Enum &operator= (Enum &&other) = default;
2243 location_t get_locus () const override final { return locus; }
2245 void accept_vis (ASTVisitor &vis) override;
2247 Identifier get_identifier () const { return enum_name; }
2249 // Invalid if name is empty, so base stripping on that.
2250 void mark_for_strip () override { enum_name = {""}; }
2251 bool is_marked_for_strip () const override { return enum_name.empty (); }
2253 // TODO: this mutable getter seems really dodgy. Think up better way.
2254 std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
2255 const std::vector<std::unique_ptr<EnumItem>> &get_variants () const
2257 return items;
2260 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2262 return generic_params;
2264 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2266 return generic_params;
2269 // TODO: is this better? Or is a "vis_block" better?
2270 WhereClause &get_where_clause () { return where_clause; }
2272 protected:
2273 /* Use covariance to implement clone function as returning this object
2274 * rather than base */
2275 Enum *clone_item_impl () const override { return new Enum (*this); }
2278 // Rust untagged union used for C compat AST node
2279 class Union : public VisItem
2281 Identifier union_name;
2283 // bool has_generics;
2284 // Generics generic_params;
2285 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2287 // bool has_where_clause;
2288 WhereClause where_clause;
2290 std::vector<StructField> variants;
2292 location_t locus;
2294 public:
2295 std::string as_string () const override;
2297 // Returns whether union has generic params.
2298 bool has_generics () const { return !generic_params.empty (); }
2300 // Returns whether union has where clause.
2301 bool has_where_clause () const { return !where_clause.is_empty (); }
2303 Union (Identifier union_name, Visibility vis,
2304 std::vector<std::unique_ptr<GenericParam>> generic_params,
2305 WhereClause where_clause, std::vector<StructField> variants,
2306 std::vector<Attribute> outer_attrs, location_t locus)
2307 : VisItem (std::move (vis), std::move (outer_attrs)),
2308 union_name (std::move (union_name)),
2309 generic_params (std::move (generic_params)),
2310 where_clause (std::move (where_clause)), variants (std::move (variants)),
2311 locus (locus)
2314 // copy constructor with vector clone
2315 Union (Union const &other)
2316 : VisItem (other), union_name (other.union_name),
2317 where_clause (other.where_clause), variants (other.variants),
2318 locus (other.locus)
2320 generic_params.reserve (other.generic_params.size ());
2321 for (const auto &e : other.generic_params)
2322 generic_params.push_back (e->clone_generic_param ());
2325 // overloaded assignment operator with vector clone
2326 Union &operator= (Union const &other)
2328 VisItem::operator= (other);
2329 union_name = other.union_name;
2330 where_clause = other.where_clause;
2331 variants = other.variants;
2332 locus = other.locus;
2334 generic_params.reserve (other.generic_params.size ());
2335 for (const auto &e : other.generic_params)
2336 generic_params.push_back (e->clone_generic_param ());
2338 return *this;
2341 // move constructors
2342 Union (Union &&other) = default;
2343 Union &operator= (Union &&other) = default;
2345 location_t get_locus () const override final { return locus; }
2347 void accept_vis (ASTVisitor &vis) override;
2349 // Invalid if name is empty, so base stripping on that.
2350 void mark_for_strip () override { union_name = {""}; }
2351 bool is_marked_for_strip () const override { return union_name.empty (); }
2353 // TODO: this mutable getter seems really dodgy. Think up better way.
2354 std::vector<StructField> &get_variants () { return variants; }
2355 const std::vector<StructField> &get_variants () const { return variants; }
2357 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2359 return generic_params;
2361 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2363 return generic_params;
2366 // TODO: is this better? Or is a "vis_block" better?
2367 WhereClause &get_where_clause () { return where_clause; }
2369 Identifier get_identifier () const { return union_name; }
2371 protected:
2372 /* Use covariance to implement clone function as returning this object
2373 * rather than base */
2374 Union *clone_item_impl () const override { return new Union (*this); }
2377 /* "Constant item" AST node - used for constant, compile-time expressions
2378 * within module scope (like constexpr) */
2379 class ConstantItem : public VisItem, public AssociatedItem
2381 // either has an identifier or "_" - maybe handle in identifier?
2382 // bool identifier_is_underscore;
2383 // if no identifier declared, identifier will be "_"
2384 std::string identifier;
2386 std::unique_ptr<Type> type;
2387 std::unique_ptr<Expr> const_expr;
2389 location_t locus;
2391 public:
2392 std::string as_string () const override;
2394 ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
2395 std::unique_ptr<Expr> const_expr,
2396 std::vector<Attribute> outer_attrs, location_t locus)
2397 : VisItem (std::move (vis), std::move (outer_attrs)),
2398 identifier (std::move (ident)), type (std::move (type)),
2399 const_expr (std::move (const_expr)), locus (locus)
2402 ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
2403 std::vector<Attribute> outer_attrs, location_t locus)
2404 : VisItem (std::move (vis), std::move (outer_attrs)),
2405 identifier (std::move (ident)), type (std::move (type)),
2406 const_expr (nullptr), locus (locus)
2409 ConstantItem (ConstantItem const &other)
2410 : VisItem (other), identifier (other.identifier), locus (other.locus)
2412 // guard to prevent null dereference (only required if error state)
2413 if (other.type != nullptr)
2414 type = other.type->clone_type ();
2415 if (other.const_expr != nullptr)
2416 const_expr = other.const_expr->clone_expr ();
2419 // Overload assignment operator to clone
2420 ConstantItem &operator= (ConstantItem const &other)
2422 VisItem::operator= (other);
2423 identifier = other.identifier;
2424 locus = other.locus;
2426 // guard to prevent null dereference (only required if error state)
2427 if (other.type != nullptr)
2428 type = other.type->clone_type ();
2429 else
2430 type = nullptr;
2431 if (other.const_expr != nullptr)
2432 const_expr = other.const_expr->clone_expr ();
2433 else
2434 const_expr = nullptr;
2436 return *this;
2439 // move constructors
2440 ConstantItem (ConstantItem &&other) = default;
2441 ConstantItem &operator= (ConstantItem &&other) = default;
2443 /* Returns whether constant item is an "unnamed" (wildcard underscore used
2444 * as identifier) constant. */
2445 bool is_unnamed () const { return identifier == "_"; }
2447 location_t get_locus () const override final { return locus; }
2449 void accept_vis (ASTVisitor &vis) override;
2451 // Invalid if type or expression are null, so base stripping on that.
2452 void mark_for_strip () override
2454 type = nullptr;
2455 const_expr = nullptr;
2457 bool is_marked_for_strip () const override
2459 return type == nullptr && const_expr == nullptr;
2462 bool has_expr () { return const_expr != nullptr; }
2464 // TODO: is this better? Or is a "vis_block" better?
2465 Expr &get_expr ()
2467 rust_assert (const_expr != nullptr);
2468 return *const_expr;
2471 std::unique_ptr<Expr> &get_expr_ptr ()
2473 rust_assert (const_expr != nullptr);
2474 return const_expr;
2477 // TODO: is this better? Or is a "vis_block" better?
2478 Type &get_type ()
2480 rust_assert (type != nullptr);
2481 return *type;
2484 std::unique_ptr<Type> &get_type_ptr ()
2486 rust_assert (type != nullptr);
2487 return type;
2490 std::string get_identifier () const { return identifier; }
2492 protected:
2493 /* Use covariance to implement clone function as returning this object
2494 * rather than base */
2495 ConstantItem *clone_item_impl () const override
2497 return new ConstantItem (*this);
2500 /* Use covariance to implement clone function as returning this object
2501 * rather than base */
2502 ConstantItem *clone_associated_item_impl () const override
2504 return new ConstantItem (*this);
2508 /* Static item AST node - items within module scope with fixed storage
2509 * duration? */
2510 class StaticItem : public VisItem
2512 bool has_mut;
2513 Identifier name;
2514 std::unique_ptr<Type> type;
2515 std::unique_ptr<Expr> expr;
2516 location_t locus;
2518 public:
2519 std::string as_string () const override;
2521 StaticItem (Identifier name, bool is_mut, std::unique_ptr<Type> type,
2522 std::unique_ptr<Expr> expr, Visibility vis,
2523 std::vector<Attribute> outer_attrs, location_t locus)
2524 : VisItem (std::move (vis), std::move (outer_attrs)), has_mut (is_mut),
2525 name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
2526 locus (locus)
2529 // Copy constructor with clone
2530 StaticItem (StaticItem const &other)
2531 : VisItem (other), has_mut (other.has_mut), name (other.name),
2532 locus (other.locus)
2534 // guard to prevent null dereference (only required if error state)
2535 if (other.type != nullptr)
2536 type = other.type->clone_type ();
2537 if (other.expr != nullptr)
2538 expr = other.expr->clone_expr ();
2541 // Overloaded assignment operator to clone
2542 StaticItem &operator= (StaticItem const &other)
2544 VisItem::operator= (other);
2545 name = other.name;
2546 has_mut = other.has_mut;
2547 locus = other.locus;
2549 // guard to prevent null dereference (only required if error state)
2550 if (other.type != nullptr)
2551 type = other.type->clone_type ();
2552 else
2553 type = nullptr;
2554 if (other.expr != nullptr)
2555 expr = other.expr->clone_expr ();
2556 else
2557 expr = nullptr;
2559 return *this;
2562 // move constructors
2563 StaticItem (StaticItem &&other) = default;
2564 StaticItem &operator= (StaticItem &&other) = default;
2566 location_t get_locus () const override final { return locus; }
2568 void accept_vis (ASTVisitor &vis) override;
2570 // Invalid if type or expression are null, so base stripping on that.
2571 void mark_for_strip () override
2573 type = nullptr;
2574 expr = nullptr;
2576 bool is_marked_for_strip () const override
2578 return type == nullptr && expr == nullptr;
2581 bool has_expr () { return expr != nullptr; }
2583 // TODO: is this better? Or is a "vis_block" better?
2584 Expr &get_expr ()
2586 rust_assert (expr != nullptr);
2587 return *expr;
2590 std::unique_ptr<Expr> &get_expr_ptr ()
2592 rust_assert (expr != nullptr);
2593 return expr;
2596 // TODO: is this better? Or is a "vis_block" better?
2597 Type &get_type ()
2599 rust_assert (type != nullptr);
2600 return *type;
2603 std::unique_ptr<Type> &get_type_ptr ()
2605 rust_assert (type != nullptr);
2606 return type;
2609 bool is_mutable () const { return has_mut; }
2611 Identifier get_identifier () const { return name; }
2613 protected:
2614 /* Use covariance to implement clone function as returning this object
2615 * rather than base */
2616 StaticItem *clone_item_impl () const override
2618 return new StaticItem (*this);
2622 // Constant item within traits
2623 class TraitItemConst : public TraitItem
2625 std::vector<Attribute> outer_attrs;
2626 Identifier name;
2627 std::unique_ptr<Type> type;
2629 // bool has_expression;
2630 std::unique_ptr<Expr> expr;
2632 public:
2633 // Whether the constant item has an associated expression.
2634 bool has_expression () const { return expr != nullptr; }
2636 TraitItemConst (Identifier name, std::unique_ptr<Type> type,
2637 std::unique_ptr<Expr> expr,
2638 std::vector<Attribute> outer_attrs, location_t locus)
2639 : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
2640 name (std::move (name)), type (std::move (type)), expr (std::move (expr))
2643 // Copy constructor with clones
2644 TraitItemConst (TraitItemConst const &other)
2645 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2646 name (other.name)
2648 node_id = other.node_id;
2650 // guard to prevent null dereference
2651 if (other.expr != nullptr)
2652 expr = other.expr->clone_expr ();
2654 // guard to prevent null dereference (only for error state)
2655 if (other.type != nullptr)
2656 type = other.type->clone_type ();
2659 // Overloaded assignment operator to clone
2660 TraitItemConst &operator= (TraitItemConst const &other)
2662 TraitItem::operator= (other);
2663 outer_attrs = other.outer_attrs;
2664 name = other.name;
2665 locus = other.locus;
2666 node_id = other.node_id;
2668 // guard to prevent null dereference
2669 if (other.expr != nullptr)
2670 expr = other.expr->clone_expr ();
2671 else
2672 expr = nullptr;
2674 // guard to prevent null dereference (only for error state)
2675 if (other.type != nullptr)
2676 type = other.type->clone_type ();
2677 else
2678 type = nullptr;
2680 return *this;
2683 // move constructors
2684 TraitItemConst (TraitItemConst &&other) = default;
2685 TraitItemConst &operator= (TraitItemConst &&other) = default;
2687 std::string as_string () const override;
2689 location_t get_locus () const override { return locus; }
2691 void accept_vis (ASTVisitor &vis) override;
2693 // Invalid if type is null, so base stripping on that.
2694 void mark_for_strip () override { type = nullptr; }
2695 bool is_marked_for_strip () const override { return type == nullptr; }
2697 // TODO: this mutable getter seems really dodgy. Think up better way.
2698 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2699 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2701 bool has_expr () const { return expr != nullptr; }
2703 // TODO: is this better? Or is a "vis_block" better?
2704 Expr &get_expr ()
2706 rust_assert (has_expr ());
2707 return *expr;
2710 std::unique_ptr<Expr> &get_expr_ptr ()
2712 rust_assert (has_expr ());
2713 return expr;
2716 // TODO: is this better? Or is a "vis_block" better?
2717 Type &get_type ()
2719 rust_assert (type != nullptr);
2720 return *type;
2723 std::unique_ptr<Type> &get_type_ptr ()
2725 rust_assert (type != nullptr);
2726 return type;
2729 Identifier get_identifier () const { return name; }
2731 protected:
2732 // Clone function implementation as (not pure) virtual method
2733 TraitItemConst *clone_associated_item_impl () const override
2735 return new TraitItemConst (*this);
2739 // Type items within traits
2740 class TraitItemType : public TraitItem
2742 std::vector<Attribute> outer_attrs;
2744 Identifier name;
2746 // bool has_type_param_bounds;
2747 // TypeParamBounds type_param_bounds;
2748 std::vector<std::unique_ptr<TypeParamBound>>
2749 type_param_bounds; // inlined form
2751 public:
2752 // Returns whether trait item type has type param bounds.
2753 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2755 TraitItemType (Identifier name,
2756 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
2757 std::vector<Attribute> outer_attrs, Visibility vis,
2758 location_t locus)
2759 : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
2760 name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
2763 // Copy constructor with vector clone
2764 TraitItemType (TraitItemType const &other)
2765 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2766 name (other.name)
2768 node_id = other.node_id;
2769 type_param_bounds.reserve (other.type_param_bounds.size ());
2770 for (const auto &e : other.type_param_bounds)
2771 type_param_bounds.push_back (e->clone_type_param_bound ());
2774 // Overloaded assignment operator with vector clone
2775 TraitItemType &operator= (TraitItemType const &other)
2777 TraitItem::operator= (other);
2778 outer_attrs = other.outer_attrs;
2779 name = other.name;
2780 locus = other.locus;
2781 node_id = other.node_id;
2783 type_param_bounds.reserve (other.type_param_bounds.size ());
2784 for (const auto &e : other.type_param_bounds)
2785 type_param_bounds.push_back (e->clone_type_param_bound ());
2787 return *this;
2790 // default move constructors
2791 TraitItemType (TraitItemType &&other) = default;
2792 TraitItemType &operator= (TraitItemType &&other) = default;
2794 std::string as_string () const override;
2796 void accept_vis (ASTVisitor &vis) override;
2798 // Invalid if name is empty, so base stripping on that.
2799 void mark_for_strip () override { name = {""}; }
2800 bool is_marked_for_strip () const override { return name.empty (); }
2802 // TODO: this mutable getter seems really dodgy. Think up better way.
2803 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2804 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2806 // TODO: mutable getter seems kinda dodgy
2807 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
2809 return type_param_bounds;
2811 const std::vector<std::unique_ptr<TypeParamBound>> &
2812 get_type_param_bounds () const
2814 return type_param_bounds;
2817 Identifier get_identifier () const { return name; }
2819 protected:
2820 // Clone function implementation as (not pure) virtual method
2821 TraitItemType *clone_associated_item_impl () const override
2823 return new TraitItemType (*this);
2827 // Rust trait item declaration AST node
2828 class Trait : public VisItem
2830 bool has_unsafe;
2831 bool has_auto;
2832 Identifier name;
2833 std::vector<std::unique_ptr<GenericParam>> generic_params;
2834 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
2835 WhereClause where_clause;
2836 std::vector<Attribute> inner_attrs;
2837 std::vector<std::unique_ptr<AssociatedItem>> trait_items;
2838 location_t locus;
2840 public:
2841 std::string as_string () const override;
2843 // Returns whether trait has generic parameters.
2844 bool has_generics () const { return !generic_params.empty (); }
2846 // Returns whether trait has type parameter bounds.
2847 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
2849 // Returns whether trait has where clause.
2850 bool has_where_clause () const { return !where_clause.is_empty (); }
2852 // Returns whether trait has trait items.
2853 bool has_trait_items () const { return !trait_items.empty (); }
2855 // Returns whether trait has inner attributes.
2856 bool has_inner_attrs () const { return !inner_attrs.empty (); }
2858 Identifier get_identifier () const { return name; }
2860 bool is_unsafe () const { return has_unsafe; }
2861 bool is_auto () const { return has_auto; }
2863 // Mega-constructor
2864 Trait (Identifier name, bool is_unsafe, bool is_auto,
2865 std::vector<std::unique_ptr<GenericParam>> generic_params,
2866 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
2867 WhereClause where_clause,
2868 std::vector<std::unique_ptr<AssociatedItem>> trait_items,
2869 Visibility vis, std::vector<Attribute> outer_attrs,
2870 std::vector<Attribute> inner_attrs, location_t locus)
2871 : VisItem (std::move (vis), std::move (outer_attrs)),
2872 has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)),
2873 generic_params (std::move (generic_params)),
2874 type_param_bounds (std::move (type_param_bounds)),
2875 where_clause (std::move (where_clause)),
2876 inner_attrs (std::move (inner_attrs)),
2877 trait_items (std::move (trait_items)), locus (locus)
2880 // Copy constructor with vector clone
2881 Trait (Trait const &other)
2882 : VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto),
2883 name (other.name), where_clause (other.where_clause),
2884 inner_attrs (other.inner_attrs), locus (other.locus)
2886 generic_params.reserve (other.generic_params.size ());
2887 for (const auto &e : other.generic_params)
2888 generic_params.push_back (e->clone_generic_param ());
2890 type_param_bounds.reserve (other.type_param_bounds.size ());
2891 for (const auto &e : other.type_param_bounds)
2892 type_param_bounds.push_back (e->clone_type_param_bound ());
2894 trait_items.reserve (other.trait_items.size ());
2895 for (const auto &e : other.trait_items)
2896 trait_items.push_back (e->clone_associated_item ());
2899 // Overloaded assignment operator with vector clone
2900 Trait &operator= (Trait const &other)
2902 VisItem::operator= (other);
2903 name = other.name;
2904 has_unsafe = other.has_unsafe;
2905 has_auto = other.has_auto;
2906 where_clause = other.where_clause;
2907 inner_attrs = other.inner_attrs;
2908 locus = other.locus;
2910 generic_params.reserve (other.generic_params.size ());
2911 for (const auto &e : other.generic_params)
2912 generic_params.push_back (e->clone_generic_param ());
2914 type_param_bounds.reserve (other.type_param_bounds.size ());
2915 for (const auto &e : other.type_param_bounds)
2916 type_param_bounds.push_back (e->clone_type_param_bound ());
2918 trait_items.reserve (other.trait_items.size ());
2919 for (const auto &e : other.trait_items)
2920 trait_items.push_back (e->clone_associated_item ());
2922 return *this;
2925 // default move constructors
2926 Trait (Trait &&other) = default;
2927 Trait &operator= (Trait &&other) = default;
2929 location_t get_locus () const override final { return locus; }
2931 void accept_vis (ASTVisitor &vis) override;
2933 // Invalid if trait name is empty, so base stripping on that.
2934 void mark_for_strip () override { name = {""}; }
2935 bool is_marked_for_strip () const override { return name.empty (); }
2937 // TODO: think of better way to do this
2938 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
2939 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
2941 const std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items () const
2943 return trait_items;
2945 std::vector<std::unique_ptr<AssociatedItem>> &get_trait_items ()
2947 return trait_items;
2950 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2952 return generic_params;
2954 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2956 return generic_params;
2959 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
2961 return type_param_bounds;
2963 const std::vector<std::unique_ptr<TypeParamBound>> &
2964 get_type_param_bounds () const
2966 return type_param_bounds;
2969 WhereClause &get_where_clause () { return where_clause; }
2971 void insert_implict_self (std::unique_ptr<AST::GenericParam> &&param)
2973 std::vector<std::unique_ptr<GenericParam>> new_list;
2974 new_list.reserve (generic_params.size () + 1);
2976 new_list.push_back (std::move (param));
2977 for (auto &p : generic_params)
2979 new_list.push_back (std::move (p));
2982 generic_params = std::move (new_list);
2985 protected:
2986 /* Use covariance to implement clone function as returning this object
2987 * rather than base */
2988 Trait *clone_item_impl () const override { return new Trait (*this); }
2991 // Implementation item declaration AST node - abstract base class
2992 class Impl : public VisItem
2994 // must be protected to allow subclasses to access them properly
2995 protected:
2996 // bool has_generics;
2997 // Generics generic_params;
2998 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3000 std::unique_ptr<Type> trait_type;
3002 // bool has_where_clause;
3003 WhereClause where_clause;
3005 // bool has_inner_attrs;
3006 std::vector<Attribute> inner_attrs;
3008 private:
3009 // doesn't really need to be protected as write access probably not needed
3010 location_t locus;
3012 public:
3013 // Returns whether impl has generic parameters.
3014 bool has_generics () const { return !generic_params.empty (); }
3016 // Returns whether impl has where clause.
3017 bool has_where_clause () const { return !where_clause.is_empty (); }
3019 // Returns whether impl has inner attributes.
3020 bool has_inner_attrs () const { return !inner_attrs.empty (); }
3022 location_t get_locus () const override final { return locus; }
3024 // Invalid if trait type is null, so base stripping on that.
3025 void mark_for_strip () override { trait_type = nullptr; }
3026 bool is_marked_for_strip () const override { return trait_type == nullptr; }
3028 // TODO: think of better way to do this
3029 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3030 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3032 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3034 return generic_params;
3036 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3038 return generic_params;
3041 // TODO: is this better? Or is a "vis_block" better?
3042 WhereClause &get_where_clause () { return where_clause; }
3044 // TODO: is this better? Or is a "vis_block" better?
3045 Type &get_type ()
3047 rust_assert (trait_type != nullptr);
3048 return *trait_type;
3051 std::unique_ptr<Type> &get_type_ptr ()
3053 rust_assert (trait_type != nullptr);
3054 return trait_type;
3057 protected:
3058 // Mega-constructor
3059 Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
3060 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3061 Visibility vis, std::vector<Attribute> inner_attrs,
3062 std::vector<Attribute> outer_attrs, location_t locus)
3063 : VisItem (std::move (vis), std::move (outer_attrs)),
3064 generic_params (std::move (generic_params)),
3065 trait_type (std::move (trait_type)),
3066 where_clause (std::move (where_clause)),
3067 inner_attrs (std::move (inner_attrs)), locus (locus)
3070 // Copy constructor
3071 Impl (Impl const &other)
3072 : VisItem (other), where_clause (other.where_clause),
3073 inner_attrs (other.inner_attrs), locus (other.locus)
3075 // guard to prevent null dereference (only required if error state)
3076 if (other.trait_type != nullptr)
3077 trait_type = other.trait_type->clone_type ();
3079 generic_params.reserve (other.generic_params.size ());
3080 for (const auto &e : other.generic_params)
3081 generic_params.push_back (e->clone_generic_param ());
3084 // Assignment operator overload with cloning
3085 Impl &operator= (Impl const &other)
3087 VisItem::operator= (other);
3088 where_clause = other.where_clause;
3089 inner_attrs = other.inner_attrs;
3090 locus = other.locus;
3092 // guard to prevent null dereference (only required if error state)
3093 if (other.trait_type != nullptr)
3094 trait_type = other.trait_type->clone_type ();
3095 else
3096 trait_type = nullptr;
3098 generic_params.reserve (other.generic_params.size ());
3099 for (const auto &e : other.generic_params)
3100 generic_params.push_back (e->clone_generic_param ());
3102 return *this;
3105 // move constructors
3106 Impl (Impl &&other) = default;
3107 Impl &operator= (Impl &&other) = default;
3110 // Regular "impl foo" impl block declaration AST node
3111 class InherentImpl : public Impl
3113 // bool has_impl_items;
3114 std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3116 public:
3117 std::string as_string () const override;
3119 // Returns whether inherent impl block has inherent impl items.
3120 bool has_impl_items () const { return !impl_items.empty (); }
3122 // Mega-constructor
3123 InherentImpl (std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3124 std::vector<std::unique_ptr<GenericParam>> generic_params,
3125 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3126 Visibility vis, std::vector<Attribute> inner_attrs,
3127 std::vector<Attribute> outer_attrs, location_t locus)
3128 : Impl (std::move (generic_params), std::move (trait_type),
3129 std::move (where_clause), std::move (vis), std::move (inner_attrs),
3130 std::move (outer_attrs), locus),
3131 impl_items (std::move (impl_items))
3134 // Copy constructor with vector clone
3135 InherentImpl (InherentImpl const &other) : Impl (other)
3137 impl_items.reserve (other.impl_items.size ());
3138 for (const auto &e : other.impl_items)
3139 impl_items.push_back (e->clone_associated_item ());
3142 // Overloaded assignment operator with vector clone
3143 InherentImpl &operator= (InherentImpl const &other)
3145 Impl::operator= (other);
3147 impl_items.reserve (other.impl_items.size ());
3148 for (const auto &e : other.impl_items)
3149 impl_items.push_back (e->clone_associated_item ());
3151 return *this;
3154 // default move constructors
3155 InherentImpl (InherentImpl &&other) = default;
3156 InherentImpl &operator= (InherentImpl &&other) = default;
3158 void accept_vis (ASTVisitor &vis) override;
3160 // TODO: think of better way to do this
3161 const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3163 return impl_items;
3165 std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3167 return impl_items;
3170 protected:
3171 /* Use covariance to implement clone function as returning this object
3172 * rather than base */
3173 InherentImpl *clone_item_impl () const override
3175 return new InherentImpl (*this);
3179 // The "impl footrait for foo" impl block declaration AST node
3180 class TraitImpl : public Impl
3182 bool has_unsafe;
3183 bool has_exclam;
3184 TypePath trait_path;
3186 // bool has_impl_items;
3187 std::vector<std::unique_ptr<AssociatedItem>> impl_items;
3189 public:
3190 std::string as_string () const override;
3192 // Returns whether trait impl has impl items.
3193 bool has_impl_items () const { return !impl_items.empty (); }
3195 // Mega-constructor
3196 TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
3197 std::vector<std::unique_ptr<AssociatedItem>> impl_items,
3198 std::vector<std::unique_ptr<GenericParam>> generic_params,
3199 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3200 Visibility vis, std::vector<Attribute> inner_attrs,
3201 std::vector<Attribute> outer_attrs, location_t locus)
3202 : Impl (std::move (generic_params), std::move (trait_type),
3203 std::move (where_clause), std::move (vis), std::move (inner_attrs),
3204 std::move (outer_attrs), locus),
3205 has_unsafe (is_unsafe), has_exclam (has_exclam),
3206 trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
3209 // Copy constructor with vector clone
3210 TraitImpl (TraitImpl const &other)
3211 : Impl (other), has_unsafe (other.has_unsafe),
3212 has_exclam (other.has_exclam), trait_path (other.trait_path)
3214 impl_items.reserve (other.impl_items.size ());
3215 for (const auto &e : other.impl_items)
3216 impl_items.push_back (e->clone_associated_item ());
3219 // Overloaded assignment operator with vector clone
3220 TraitImpl &operator= (TraitImpl const &other)
3222 Impl::operator= (other);
3223 trait_path = other.trait_path;
3224 has_unsafe = other.has_unsafe;
3225 has_exclam = other.has_exclam;
3227 impl_items.reserve (other.impl_items.size ());
3228 for (const auto &e : other.impl_items)
3229 impl_items.push_back (e->clone_associated_item ());
3231 return *this;
3234 // move constructors
3235 TraitImpl (TraitImpl &&other) = default;
3236 TraitImpl &operator= (TraitImpl &&other) = default;
3238 void accept_vis (ASTVisitor &vis) override;
3240 bool is_unsafe () const { return has_unsafe; };
3241 bool is_exclam () const { return has_exclam; }
3243 // TODO: think of better way to do this
3244 const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
3246 return impl_items;
3248 std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
3250 return impl_items;
3253 // TODO: is this better? Or is a "vis_block" better?
3254 TypePath &get_trait_path ()
3256 // TODO: assert that trait path is not empty?
3257 return trait_path;
3260 protected:
3261 /* Use covariance to implement clone function as returning this object
3262 * rather than base */
3263 TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
3266 #if 0
3267 // Abstract base class for an item used inside an extern block
3268 class ExternalItem
3270 // bool has_outer_attrs;
3271 std::vector<Attribute> outer_attrs;
3273 // bool has_visibility;
3274 Visibility visibility;
3276 Identifier item_name;
3277 location_t locus;
3279 public:
3280 virtual ~ExternalItem () {}
3282 /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
3283 * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
3284 * support would require a lot of refactoring. */
3286 // Returns whether item has outer attributes.
3287 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3289 // Returns whether item has non-default visibility.
3290 bool has_visibility () const { return !visibility.is_error (); }
3292 // Unique pointer custom clone function
3293 std::unique_ptr<ExternalItem> clone_external_item () const
3295 return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
3298 virtual std::string as_string () const;
3300 location_t get_locus () const override final { return locus; }
3302 virtual void accept_vis (ASTVisitor &vis) = 0;
3304 // TODO: make virtual? Would be more flexible.
3305 // Based on idea that name should never be empty.
3306 void mark_for_strip () { item_name = ""; };
3307 bool is_marked_for_strip () const { return item_name.empty (); };
3309 protected:
3310 ExternalItem (Identifier item_name, Visibility vis,
3311 std::vector<Attribute> outer_attrs, location_t locus)
3312 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
3313 item_name (std::move (item_name)), locus (locus)
3316 // Copy constructor
3317 ExternalItem (ExternalItem const &other)
3318 : outer_attrs (other.outer_attrs), visibility (other.visibility),
3319 item_name (other.item_name), locus (other.locus)
3322 // Overloaded assignment operator to clone
3323 ExternalItem &operator= (ExternalItem const &other)
3325 item_name = other.item_name;
3326 visibility = other.visibility;
3327 outer_attrs = other.outer_attrs;
3328 locus = other.locus;
3330 return *this;
3333 // move constructors
3334 ExternalItem (ExternalItem &&other) = default;
3335 ExternalItem &operator= (ExternalItem &&other) = default;
3337 // Clone function implementation as pure virtual method
3338 virtual ExternalItem *clone_external_item_impl () const = 0;
3340 // possibly make this public if required
3341 std::string get_item_name () const { return item_name; }
3343 #endif
3345 // A foreign type defined outside the current crate.
3346 // https://rust-lang.github.io/rfcs/1861-extern-types.html
3347 class ExternalTypeItem : public ExternalItem
3349 std::vector<Attribute> outer_attrs;
3351 Visibility visibility;
3352 Identifier item_name;
3353 location_t locus;
3355 bool marked_for_strip;
3357 public:
3358 ExternalTypeItem (Identifier item_name, Visibility vis,
3359 std::vector<Attribute> outer_attrs, location_t locus)
3360 : ExternalItem (), outer_attrs (std::move (outer_attrs)), visibility (vis),
3361 item_name (std::move (item_name)), locus (locus), marked_for_strip (false)
3364 // copy constructor
3365 ExternalTypeItem (ExternalTypeItem const &other)
3366 : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3367 visibility (other.visibility), item_name (other.item_name),
3368 locus (other.locus), marked_for_strip (other.marked_for_strip)
3370 node_id = other.node_id;
3373 ExternalTypeItem &operator= (ExternalTypeItem const &other)
3375 node_id = other.node_id;
3376 outer_attrs = other.outer_attrs;
3377 visibility = other.visibility;
3378 item_name = other.item_name;
3379 locus = other.locus;
3380 marked_for_strip = other.marked_for_strip;
3382 return *this;
3385 // move constructors
3386 ExternalTypeItem (ExternalTypeItem &&other) = default;
3387 ExternalTypeItem &operator= (ExternalTypeItem &&other) = default;
3389 std::string as_string () const override;
3391 void accept_vis (ASTVisitor &vis) override;
3393 // Returns whether item has outer attributes.
3394 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3396 // Returns whether item has non-default visibility.
3397 bool has_visibility () const { return !visibility.is_error (); }
3399 location_t get_locus () const { return locus; }
3401 void mark_for_strip () override { marked_for_strip = true; };
3402 bool is_marked_for_strip () const override { return marked_for_strip; };
3404 // TODO: this mutable getter seems really dodgy. Think up better way.
3405 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3406 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3408 Identifier get_identifier () const { return item_name; }
3410 Visibility &get_visibility () { return visibility; }
3411 const Visibility &get_visibility () const { return visibility; }
3413 protected:
3414 /* Use covariance to implement clone function as returning this object
3415 * rather than base */
3416 ExternalTypeItem *clone_external_item_impl () const override
3418 return new ExternalTypeItem (*this);
3422 // A static item used in an extern block
3423 class ExternalStaticItem : public ExternalItem
3425 // bool has_outer_attrs;
3426 std::vector<Attribute> outer_attrs;
3428 // bool has_visibility;
3429 Visibility visibility;
3431 Identifier item_name;
3432 location_t locus;
3434 bool has_mut;
3435 std::unique_ptr<Type> item_type;
3437 public:
3438 ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
3439 bool is_mut, Visibility vis,
3440 std::vector<Attribute> outer_attrs, location_t locus)
3441 : ExternalItem (), outer_attrs (std::move (outer_attrs)),
3442 visibility (std::move (vis)), item_name (std::move (item_name)),
3443 locus (locus), has_mut (is_mut), item_type (std::move (item_type))
3446 // Copy constructor
3447 ExternalStaticItem (ExternalStaticItem const &other)
3448 : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3449 visibility (other.visibility), item_name (other.item_name),
3450 locus (other.locus), has_mut (other.has_mut)
3452 node_id = other.node_id;
3453 // guard to prevent null dereference (only required if error state)
3454 if (other.item_type != nullptr)
3455 item_type = other.item_type->clone_type ();
3458 // Overloaded assignment operator to clone
3459 ExternalStaticItem &operator= (ExternalStaticItem const &other)
3461 node_id = other.node_id;
3462 outer_attrs = other.outer_attrs;
3463 visibility = other.visibility;
3464 item_name = other.item_name;
3465 locus = other.locus;
3466 has_mut = other.has_mut;
3468 // guard to prevent null dereference (only required if error state)
3469 if (other.item_type != nullptr)
3470 item_type = other.item_type->clone_type ();
3471 else
3472 item_type = nullptr;
3474 return *this;
3477 // move constructors
3478 ExternalStaticItem (ExternalStaticItem &&other) = default;
3479 ExternalStaticItem &operator= (ExternalStaticItem &&other) = default;
3481 std::string as_string () const override;
3483 void accept_vis (ASTVisitor &vis) override;
3485 // Returns whether item has outer attributes.
3486 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3488 // Returns whether item has non-default visibility.
3489 bool has_visibility () const { return !visibility.is_error (); }
3491 location_t get_locus () const { return locus; }
3493 // Based on idea that type should never be null.
3494 void mark_for_strip () override { item_type = nullptr; };
3495 bool is_marked_for_strip () const override { return item_type == nullptr; };
3497 // TODO: this mutable getter seems really dodgy. Think up better way.
3498 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3499 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3501 // TODO: is this better? Or is a "vis_block" better?
3502 Type &get_type ()
3504 rust_assert (item_type != nullptr);
3505 return *item_type;
3508 std::unique_ptr<Type> &get_type_ptr ()
3510 rust_assert (item_type != nullptr);
3511 return item_type;
3514 Identifier get_identifier () const { return item_name; }
3516 Visibility &get_visibility () { return visibility; }
3518 const Visibility &get_visibility () const { return visibility; }
3520 bool is_mut () const { return has_mut; }
3522 protected:
3523 /* Use covariance to implement clone function as returning this object
3524 * rather than base */
3525 ExternalStaticItem *clone_external_item_impl () const override
3527 return new ExternalStaticItem (*this);
3531 // A named function parameter used in external functions
3532 class NamedFunctionParam
3534 // bool has_name; // otherwise is _
3535 std::string name;
3537 std::unique_ptr<Type> param_type;
3539 // seemingly new since writing this node
3540 std::vector<Attribute> outer_attrs;
3542 NodeId node_id;
3543 location_t locus;
3544 bool variadic;
3546 public:
3547 /* Returns whether the named function parameter has a name (i.e. name is not
3548 * '_'). */
3549 bool has_name () const { return name != "_" && name != ""; }
3551 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3553 // Returns whether the named function parameter is in an error state.
3554 bool is_error () const
3556 // also if identifier is "" but that is probably more costly to compute
3557 return param_type == nullptr && !variadic;
3560 bool is_variadic () const { return variadic; }
3562 std::string get_name () const { return name; }
3564 location_t get_locus () { return locus; }
3566 // Creates an error state named function parameter.
3567 static NamedFunctionParam create_error ()
3569 return NamedFunctionParam ("", nullptr, {}, UNDEF_LOCATION);
3572 NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
3573 std::vector<Attribute> outer_attrs, location_t locus)
3574 : name (std::move (name)), param_type (std::move (param_type)),
3575 outer_attrs (std::move (outer_attrs)),
3576 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
3577 variadic (false)
3580 NamedFunctionParam (std::string name, std::vector<Attribute> outer_attrs,
3581 location_t locus)
3582 : name (std::move (name)), param_type (nullptr),
3583 outer_attrs (std::move (outer_attrs)),
3584 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
3585 variadic (true)
3588 NamedFunctionParam (std::vector<Attribute> outer_attrs, location_t locus)
3589 : name (""), param_type (nullptr), outer_attrs (std::move (outer_attrs)),
3590 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
3591 variadic (true)
3594 // Copy constructor
3595 NamedFunctionParam (NamedFunctionParam const &other)
3596 : name (other.name), outer_attrs (other.outer_attrs),
3597 variadic (other.variadic)
3599 node_id = other.node_id;
3600 // guard to prevent null dereference (only required if error state)
3601 if (other.param_type != nullptr)
3602 param_type = other.param_type->clone_type ();
3603 else
3604 param_type = nullptr;
3607 ~NamedFunctionParam () = default;
3609 // Overloaded assignment operator to clone
3610 NamedFunctionParam &operator= (NamedFunctionParam const &other)
3612 node_id = other.node_id;
3613 name = other.name;
3614 // has_name = other.has_name;
3615 outer_attrs = other.outer_attrs;
3617 // guard to prevent null dereference (only required if error state)
3618 if (other.param_type != nullptr)
3619 param_type = other.param_type->clone_type ();
3620 else
3621 param_type = nullptr;
3623 return *this;
3626 // move constructors
3627 NamedFunctionParam (NamedFunctionParam &&other) = default;
3628 NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
3630 std::string as_string () const;
3632 // Based on idea that nane should never be empty.
3633 void mark_for_strip () { param_type = nullptr; };
3634 bool is_marked_for_strip () const { return is_error (); };
3636 // TODO: this mutable getter seems really dodgy. Think up better way.
3637 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3638 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3640 // TODO: is this better? Or is a "vis_block" better?
3641 Type &get_type ()
3643 rust_assert (param_type != nullptr);
3644 return *param_type;
3647 std::unique_ptr<Type> &get_type_ptr ()
3649 rust_assert (param_type != nullptr);
3650 return param_type;
3653 NodeId get_node_id () const { return node_id; }
3656 // A function item used in an extern block
3657 class ExternalFunctionItem : public ExternalItem
3659 // bool has_outer_attrs;
3660 std::vector<Attribute> outer_attrs;
3662 // bool has_visibility;
3663 Visibility visibility;
3665 Identifier item_name;
3666 location_t locus;
3668 // bool has_generics;
3669 // Generics generic_params;
3670 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3672 // bool has_return_type;
3673 // FunctionReturnType return_type;
3674 std::unique_ptr<Type> return_type; // inlined
3676 // bool has_where_clause;
3677 WhereClause where_clause;
3679 std::vector<NamedFunctionParam> function_params;
3681 public:
3682 // Returns whether item has generic parameters.
3683 bool has_generics () const { return !generic_params.empty (); }
3685 // Returns whether item has a return type (otherwise void).
3686 bool has_return_type () const { return return_type != nullptr; }
3688 // Returns whether item has a where clause.
3689 bool has_where_clause () const { return !where_clause.is_empty (); }
3691 // Returns whether item has outer attributes.
3692 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3694 // Returns whether item has non-default visibility.
3695 bool has_visibility () const { return !visibility.is_error (); }
3697 // Returns whether item has variadic parameters.
3698 bool is_variadic () const
3700 return function_params.size () != 0
3701 && function_params.back ().is_variadic ();
3704 location_t get_locus () const { return locus; }
3706 Visibility &get_visibility () { return visibility; }
3707 const Visibility &get_visibility () const { return visibility; }
3709 ExternalFunctionItem (
3710 Identifier item_name,
3711 std::vector<std::unique_ptr<GenericParam>> generic_params,
3712 std::unique_ptr<Type> return_type, WhereClause where_clause,
3713 std::vector<NamedFunctionParam> function_params, Visibility vis,
3714 std::vector<Attribute> outer_attrs, location_t locus)
3715 : ExternalItem (), outer_attrs (std::move (outer_attrs)),
3716 visibility (std::move (vis)), item_name (std::move (item_name)),
3717 locus (locus), generic_params (std::move (generic_params)),
3718 return_type (std::move (return_type)),
3719 where_clause (std::move (where_clause)),
3720 function_params (std::move (function_params))
3722 // TODO: assert that if has variadic outer attrs, then has_variadics is
3723 // true?
3726 // Copy constructor with clone
3727 ExternalFunctionItem (ExternalFunctionItem const &other)
3728 : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
3729 visibility (other.visibility), item_name (other.item_name),
3730 locus (other.locus), where_clause (other.where_clause),
3731 function_params (other.function_params)
3733 node_id = other.node_id;
3734 // guard to prevent null pointer dereference
3735 if (other.return_type != nullptr)
3736 return_type = other.return_type->clone_type ();
3738 generic_params.reserve (other.generic_params.size ());
3739 for (const auto &e : other.generic_params)
3740 generic_params.push_back (e->clone_generic_param ());
3743 // Overloaded assignment operator with clone
3744 ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
3746 outer_attrs = other.outer_attrs;
3747 visibility = other.visibility;
3748 item_name = other.item_name;
3749 locus = other.locus;
3750 where_clause = other.where_clause;
3751 function_params = other.function_params;
3752 node_id = other.node_id;
3754 // guard to prevent null pointer dereference
3755 if (other.return_type != nullptr)
3756 return_type = other.return_type->clone_type ();
3757 else
3758 return_type = nullptr;
3760 generic_params.reserve (other.generic_params.size ());
3761 for (const auto &e : other.generic_params)
3762 generic_params.push_back (e->clone_generic_param ());
3764 return *this;
3767 // move constructors
3768 ExternalFunctionItem (ExternalFunctionItem &&other) = default;
3769 ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default;
3771 std::string as_string () const override;
3773 void accept_vis (ASTVisitor &vis) override;
3775 // Based on idea that nane should never be empty.
3776 void mark_for_strip () override { item_name = {""}; };
3777 bool is_marked_for_strip () const override { return item_name.empty (); };
3779 // TODO: this mutable getter seems really dodgy. Think up better way.
3780 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3781 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3783 std::vector<NamedFunctionParam> &get_function_params ()
3785 return function_params;
3787 const std::vector<NamedFunctionParam> &get_function_params () const
3789 return function_params;
3792 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3794 return generic_params;
3796 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3798 return generic_params;
3801 // TODO: is this better? Or is a "vis_block" better?
3802 WhereClause &get_where_clause () { return where_clause; }
3804 // TODO: is this better? Or is a "vis_block" better?
3805 Type &get_return_type ()
3807 rust_assert (has_return_type ());
3808 return *return_type;
3811 std::unique_ptr<Type> &get_return_type_ptr ()
3813 rust_assert (has_return_type ());
3814 return return_type;
3817 Identifier get_identifier () const { return item_name; };
3819 protected:
3820 /* Use covariance to implement clone function as returning this object
3821 * rather than base */
3822 ExternalFunctionItem *clone_external_item_impl () const override
3824 return new ExternalFunctionItem (*this);
3828 // An extern block AST node
3829 class ExternBlock : public VisItem
3831 // bool has_abi;
3832 std::string abi;
3834 // bool has_inner_attrs;
3835 std::vector<Attribute> inner_attrs;
3837 // bool has_extern_items;
3838 std::vector<std::unique_ptr<ExternalItem>> extern_items;
3840 location_t locus;
3842 // TODO: find another way to store this to save memory?
3843 bool marked_for_strip = false;
3845 public:
3846 std::string as_string () const override;
3848 // Returns whether extern block has inner attributes.
3849 bool has_inner_attrs () const { return !inner_attrs.empty (); }
3851 // Returns whether extern block has extern items.
3852 bool has_extern_items () const { return !extern_items.empty (); }
3854 // Returns whether extern block has ABI name.
3855 bool has_abi () const { return !abi.empty (); }
3857 std::string get_abi () const { return abi; }
3859 ExternBlock (std::string abi,
3860 std::vector<std::unique_ptr<ExternalItem>> extern_items,
3861 Visibility vis, std::vector<Attribute> inner_attrs,
3862 std::vector<Attribute> outer_attrs, location_t locus)
3863 : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
3864 inner_attrs (std::move (inner_attrs)),
3865 extern_items (std::move (extern_items)), locus (locus)
3868 // Copy constructor with vector clone
3869 ExternBlock (ExternBlock const &other)
3870 : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
3871 locus (other.locus), marked_for_strip (other.marked_for_strip)
3873 extern_items.reserve (other.extern_items.size ());
3874 for (const auto &e : other.extern_items)
3875 extern_items.push_back (e->clone_external_item ());
3878 // Overloaded assignment operator with vector clone
3879 ExternBlock &operator= (ExternBlock const &other)
3881 VisItem::operator= (other);
3882 abi = other.abi;
3883 inner_attrs = other.inner_attrs;
3884 locus = other.locus;
3885 marked_for_strip = other.marked_for_strip;
3887 extern_items.reserve (other.extern_items.size ());
3888 for (const auto &e : other.extern_items)
3889 extern_items.push_back (e->clone_external_item ());
3891 return *this;
3894 // move constructors
3895 ExternBlock (ExternBlock &&other) = default;
3896 ExternBlock &operator= (ExternBlock &&other) = default;
3898 location_t get_locus () const override final { return locus; }
3900 void accept_vis (ASTVisitor &vis) override;
3902 // Can't think of any invalid invariants, so store boolean.
3903 void mark_for_strip () override { marked_for_strip = true; }
3904 bool is_marked_for_strip () const override { return marked_for_strip; }
3906 // TODO: think of better way to do this
3907 const std::vector<std::unique_ptr<ExternalItem>> &get_extern_items () const
3909 return extern_items;
3911 std::vector<std::unique_ptr<ExternalItem>> &get_extern_items ()
3913 return extern_items;
3916 // TODO: think of better way to do this
3917 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3918 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3920 protected:
3921 /* Use covariance to implement clone function as returning this object
3922 * rather than base */
3923 ExternBlock *clone_item_impl () const override
3925 return new ExternBlock (*this);
3929 class MacroRulesDefinition;
3930 } // namespace AST
3931 } // namespace Rust
3933 #endif