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
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
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
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"
37 // Technically is meant to be STRING_LITERAL
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
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;
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
66 std::unique_ptr
<Type
> type
;
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
;
116 node_id
= other
.node_id
;
118 // guard to prevent null pointer dereference
119 if (other
.type
!= nullptr)
120 type
= other
.type
->clone_type ();
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 ());
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?
146 rust_assert (type
!= nullptr);
150 std::unique_ptr
<Type
> &get_type_ptr ()
152 rust_assert (type
!= nullptr);
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
;
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
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;
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
203 std::vector
<Lifetime
> lifetime_bounds
;
208 LifetimeWhereClauseItem (Lifetime lifetime
,
209 std::vector
<Lifetime
> lifetime_bounds
,
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
; }
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
;
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
,
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 ());
289 TypeBoundWhereClauseItem (TypeBoundWhereClauseItem
&&other
) = default;
290 TypeBoundWhereClauseItem
&operator= (TypeBoundWhereClauseItem
&&other
)
293 std::string
as_string () const override
;
295 void accept_vis (ASTVisitor
&vis
) override
;
299 rust_assert (bound_type
!= nullptr);
303 std::unique_ptr
<Type
> &get_type_ptr ()
305 rust_assert (bound_type
!= nullptr);
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
; }
326 // Clone function implementation as (not pure) virtual method
327 TypeBoundWhereClauseItem
*clone_where_clause_item_impl () const override
329 return new TypeBoundWhereClauseItem (*this);
336 std::vector
<std::unique_ptr
<WhereClauseItem
>> where_clause_items
;
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 ());
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
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;
426 std::vector
<Attribute
> outer_attrs
;
431 // A self parameter in a method
432 class SelfParam
: public Param
436 // bool has_lifetime; // only possible if also ref
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
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
;
501 node_id
= other
.node_id
;
502 outer_attrs
= other
.outer_attrs
;
504 if (other
.type
!= nullptr)
505 type
= other
.type
->clone_type ();
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?
533 rust_assert (has_type ());
537 std::unique_ptr
<Type
> &get_type_ptr ()
539 rust_assert (has_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
556 Unsafety unsafe_status
;
558 std::string extern_abi
;
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
;
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
;
616 node_id
= other
.node_id
;
617 if (other
.param_name
!= nullptr)
618 param_name
= other
.param_name
->clone_pattern ();
620 param_name
= nullptr;
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);
638 const Pattern
&get_pattern () const
640 rust_assert (param_name
!= nullptr);
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
;
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
)
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 ();
686 param_name
= nullptr;
687 if (other
.type
!= nullptr)
688 type
= other
.type
->clone_type ();
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);
721 bool has_name () const { return param_name
!= nullptr; }
723 // TODO: is this better? Or is a "vis_block" better?
726 rust_assert (type
!= nullptr);
730 std::unique_ptr
<Type
> &get_type_ptr ()
732 rust_assert (type
!= nullptr);
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
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.
759 Identifier
get_name () const { return module_name
; }
761 AST::Kind
get_ast_kind () const override
{ return AST::Kind::MODULE
; }
764 Identifier module_name
;
769 // Name of the file including the module
770 std::string outer_filename
;
771 // bool has_inner_attrs;
772 std::vector
<Attribute
> inner_attrs
;
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 ());
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
);
835 // Overloaded assignment operator with vector clone
836 Module
&operator= (Module
const &other
)
838 VisItem::operator= (other
);
840 module_name
= other
.module_name
;
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
849 clone_items (other
.items
);
856 // Search for the filename associated with an external module, storing it in
858 void process_file_path ();
859 // Load the items contained in an external module
862 void accept_vis (ASTVisitor
&vis
) override
;
864 /* Override that runs the function recursively on all items contained within
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
);
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 (); }
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
;
921 "extern crate foo as _"
923 "extern crate std as cool_std" */
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
932 bool references_self () const { return referenced_crate
== "self"; }
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 ();
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
986 virtual ~UseTree () {}
988 // Overload assignment operator to clone
989 UseTree
&operator= (UseTree
const &other
)
996 UseTree (const UseTree
&other
) = default;
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;
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
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
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 ());
1072 SimplePath
&get_path () { return path
; }
1074 /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory
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
1100 std::vector
<std::unique_ptr
<UseTree
>> trees
;
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
;
1134 trees
.reserve (other
.trees
.size ());
1135 for (const auto &e
: other
.trees
)
1136 trees
.push_back (e
->clone_use_tree ());
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 ());
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
1173 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
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
1198 NewBindType bind_type
;
1199 Identifier identifier
; // only if NewBindType is IDENTIFIER
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 ());
1228 SimplePath
&get_path () { return path
; }
1230 const Identifier
&get_identifier () const
1232 rust_assert (has_identifier ());
1236 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
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
;
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 ();
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; }
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);
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
;
1327 bool is_external_function
;
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 ());
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
; }
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
;
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
,
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
)
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 ();
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 ());
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
; }
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
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
;
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
; }
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 ());
1688 // move constructors
1689 Struct (Struct
&&other
) = default;
1690 Struct
&operator= (Struct
&&other
) = default;
1693 // A single field in a struct
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
;
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
)
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
),
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 ();
1749 field_type
= nullptr;
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 (),
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);
1789 std::unique_ptr
<Type
> &get_field_type_ptr ()
1791 rust_assert (field_type
!= nullptr);
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
;
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
)),
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
; }
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
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
;
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
1873 bool has_visibility () const { return !visibility
.is_error (); }
1875 // Complete constructor
1876 TupleField (std::unique_ptr
<Type
> field_type
, Visibility vis
,
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 ();
1908 field_type
= nullptr;
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);
1946 std::unique_ptr
<Type
> &get_field_type_ptr ()
1948 rust_assert (field_type
!= nullptr);
1953 // Rust tuple declared using struct keyword AST node
1954 class TupleStruct
: public Struct
1956 std::vector
<TupleField
> fields
;
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
; }
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
1990 class EnumItem
: public VisItem
1992 Identifier variant_name
;
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 (); }
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
;
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
;
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
;
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
;
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
;
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;
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?
2145 rust_assert (expression
!= nullptr);
2149 std::unique_ptr
<Expr
> &get_expr_ptr ()
2151 rust_assert (expression
!= nullptr);
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
;
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 (); }
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
)),
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 ());
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
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
; }
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
;
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
)),
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
),
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 ());
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
; }
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
;
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 ();
2431 if (other
.const_expr
!= nullptr)
2432 const_expr
= other
.const_expr
->clone_expr ();
2434 const_expr
= nullptr;
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
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?
2467 rust_assert (const_expr
!= nullptr);
2471 std::unique_ptr
<Expr
> &get_expr_ptr ()
2473 rust_assert (const_expr
!= nullptr);
2477 // TODO: is this better? Or is a "vis_block" better?
2480 rust_assert (type
!= nullptr);
2484 std::unique_ptr
<Type
> &get_type_ptr ()
2486 rust_assert (type
!= nullptr);
2490 std::string
get_identifier () const { return identifier
; }
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
2510 class StaticItem
: public VisItem
2514 std::unique_ptr
<Type
> type
;
2515 std::unique_ptr
<Expr
> expr
;
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
)),
2529 // Copy constructor with clone
2530 StaticItem (StaticItem
const &other
)
2531 : VisItem (other
), has_mut (other
.has_mut
), name (other
.name
),
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
);
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 ();
2554 if (other
.expr
!= nullptr)
2555 expr
= other
.expr
->clone_expr ();
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
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?
2586 rust_assert (expr
!= nullptr);
2590 std::unique_ptr
<Expr
> &get_expr_ptr ()
2592 rust_assert (expr
!= nullptr);
2596 // TODO: is this better? Or is a "vis_block" better?
2599 rust_assert (type
!= nullptr);
2603 std::unique_ptr
<Type
> &get_type_ptr ()
2605 rust_assert (type
!= nullptr);
2609 bool is_mutable () const { return has_mut
; }
2611 Identifier
get_identifier () const { return name
; }
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
;
2627 std::unique_ptr
<Type
> type
;
2629 // bool has_expression;
2630 std::unique_ptr
<Expr
> expr
;
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
),
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
;
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 ();
2674 // guard to prevent null dereference (only for error state)
2675 if (other
.type
!= nullptr)
2676 type
= other
.type
->clone_type ();
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?
2706 rust_assert (has_expr ());
2710 std::unique_ptr
<Expr
> &get_expr_ptr ()
2712 rust_assert (has_expr ());
2716 // TODO: is this better? Or is a "vis_block" better?
2719 rust_assert (type
!= nullptr);
2723 std::unique_ptr
<Type
> &get_type_ptr ()
2725 rust_assert (type
!= nullptr);
2729 Identifier
get_identifier () const { return name
; }
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
;
2746 // bool has_type_param_bounds;
2747 // TypeParamBounds type_param_bounds;
2748 std::vector
<std::unique_ptr
<TypeParamBound
>>
2749 type_param_bounds
; // inlined form
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
,
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
),
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
;
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 ());
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
; }
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
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
;
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
; }
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
);
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 ());
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
2945 std::vector
<std::unique_ptr
<AssociatedItem
>> &get_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
> &¶m
)
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
);
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
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
;
3009 // doesn't really need to be protected as write access probably not needed
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?
3047 rust_assert (trait_type
!= nullptr);
3051 std::unique_ptr
<Type
> &get_type_ptr ()
3053 rust_assert (trait_type
!= nullptr);
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
)
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 ();
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 ());
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
;
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 (); }
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 ());
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
3165 std::vector
<std::unique_ptr
<AssociatedItem
>> &get_impl_items ()
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
3184 TypePath trait_path
;
3186 // bool has_impl_items;
3187 std::vector
<std::unique_ptr
<AssociatedItem
>> impl_items
;
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 (); }
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 ());
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
3248 std::vector
<std::unique_ptr
<AssociatedItem
>> &get_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?
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); }
3267 // Abstract base class for an item used inside an extern block
3270 // bool has_outer_attrs;
3271 std::vector
<Attribute
> outer_attrs
;
3273 // bool has_visibility;
3274 Visibility visibility
;
3276 Identifier item_name
;
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 (); };
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
)
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
;
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
; }
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
;
3355 bool marked_for_strip
;
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)
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
;
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
; }
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
;
3435 std::unique_ptr
<Type
> item_type
;
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
))
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 ();
3472 item_type
= nullptr;
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?
3504 rust_assert (item_type
!= nullptr);
3508 std::unique_ptr
<Type
> &get_type_ptr ()
3510 rust_assert (item_type
!= nullptr);
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
; }
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 _
3537 std::unique_ptr
<Type
> param_type
;
3539 // seemingly new since writing this node
3540 std::vector
<Attribute
> outer_attrs
;
3547 /* Returns whether the named function parameter has a name (i.e. name is not
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
),
3580 NamedFunctionParam (std::string name
, std::vector
<Attribute
> outer_attrs
,
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
),
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
),
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 ();
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
;
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 ();
3621 param_type
= nullptr;
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?
3643 rust_assert (param_type
!= nullptr);
3647 std::unique_ptr
<Type
> &get_type_ptr ()
3649 rust_assert (param_type
!= nullptr);
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
;
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
;
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
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 ();
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 ());
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 ());
3817 Identifier
get_identifier () const { return item_name
; };
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
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
;
3842 // TODO: find another way to store this to save memory?
3843 bool marked_for_strip
= false;
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
);
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 ());
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
; }
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
;