]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/ast/rust-item.h
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / ast / rust-item.h
CommitLineData
a945c346 1// Copyright (C) 2020-2024 Free Software Foundation, Inc.
438ae944
JP
2
3// This file is part of GCC.
4
5// GCC is free software; you can redistribute it and/or modify it under
6// the terms of the GNU General Public License as published by the Free
7// Software Foundation; either version 3, or (at your option) any later
8// version.
9
10// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13// for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with GCC; see the file COPYING3. If not see
17// <http://www.gnu.org/licenses/>.
18
19#ifndef RUST_AST_ITEM_H
20#define RUST_AST_ITEM_H
21
22#include "rust-ast.h"
23#include "rust-path.h"
24#include "rust-common.h"
1c57244d 25#include "rust-expr.h"
438ae944
JP
26
27namespace Rust {
28namespace AST {
29// forward decls
438ae944
JP
30class TypePath;
31
32// TODO: inline?
33/*struct AbiName {
34 std::string abi_name;
35 // Technically is meant to be STRING_LITERAL
36
37 public:
38 // Returns whether abi name is empty, i.e. doesn't exist.
39 bool is_empty() const {
40 return abi_name.empty();
41 }
42
43 AbiName(std::string name) : abi_name(std::move(name)) {}
44
45 // Empty AbiName constructor
46 AbiName() {}
47};*/
48
49// A type generic parameter (as opposed to a lifetime generic parameter)
50class TypeParam : public GenericParam
51{
52 // bool has_outer_attribute;
53 // std::unique_ptr<Attribute> outer_attr;
54 Attribute outer_attr;
55
56 Identifier type_representation;
57
58 // bool has_type_param_bounds;
59 // TypeParamBounds type_param_bounds;
60 std::vector<std::unique_ptr<TypeParamBound>>
61 type_param_bounds; // inlined form
62
63 // bool has_type;
64 std::unique_ptr<Type> type;
65
66 Location locus;
67
68public:
69 Identifier get_type_representation () const { return type_representation; }
70
71 // Returns whether the type of the type param has been specified.
72 bool has_type () const { return type != nullptr; }
73
74 // Returns whether the type param has type param bounds.
75 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
76
77 // Returns whether the type param has an outer attribute.
78 bool has_outer_attribute () const { return !outer_attr.is_empty (); }
79
80 TypeParam (Identifier type_representation, Location locus = Location (),
81 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
82 = std::vector<std::unique_ptr<TypeParamBound>> (),
83 std::unique_ptr<Type> type = nullptr,
84 Attribute outer_attr = Attribute::create_empty ())
85 : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()),
86 outer_attr (std::move (outer_attr)),
87 type_representation (std::move (type_representation)),
88 type_param_bounds (std::move (type_param_bounds)),
89 type (std::move (type)), locus (locus)
90 {}
91
92 // Copy constructor uses clone
93 TypeParam (TypeParam const &other)
94 : GenericParam (other.node_id), outer_attr (other.outer_attr),
95 type_representation (other.type_representation), locus (other.locus)
96 {
97 // guard to prevent null pointer dereference
98 if (other.type != nullptr)
99 type = other.type->clone_type ();
100
101 type_param_bounds.reserve (other.type_param_bounds.size ());
102 for (const auto &e : other.type_param_bounds)
103 type_param_bounds.push_back (e->clone_type_param_bound ());
104 }
105
106 // Overloaded assignment operator to clone
107 TypeParam &operator= (TypeParam const &other)
108 {
109 type_representation = other.type_representation;
110 outer_attr = other.outer_attr;
111 locus = other.locus;
112 node_id = other.node_id;
113
114 // guard to prevent null pointer dereference
115 if (other.type != nullptr)
116 type = other.type->clone_type ();
117 else
118 type = nullptr;
119
120 type_param_bounds.reserve (other.type_param_bounds.size ());
121 for (const auto &e : other.type_param_bounds)
122 type_param_bounds.push_back (e->clone_type_param_bound ());
123
124 return *this;
125 }
126
127 // move constructors
128 TypeParam (TypeParam &&other) = default;
129 TypeParam &operator= (TypeParam &&other) = default;
130
131 std::string as_string () const override;
132
133 Location get_locus () const override final { return locus; }
134
135 Kind get_kind () const override final { return Kind::Type; }
136
137 void accept_vis (ASTVisitor &vis) override;
138
139 // TODO: is this better? Or is a "vis_block" better?
140 std::unique_ptr<Type> &get_type ()
141 {
142 rust_assert (type != nullptr);
143 return type;
144 }
145
146 // TODO: mutable getter seems kinda dodgy
147 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
148 {
149 return type_param_bounds;
150 }
151 const std::vector<std::unique_ptr<TypeParamBound>> &
152 get_type_param_bounds () const
153 {
154 return type_param_bounds;
155 }
156
157protected:
158 // Clone function implementation as virtual method
159 TypeParam *clone_generic_param_impl () const override
160 {
161 return new TypeParam (*this);
162 }
163};
164
165/* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
166 * TypeBoundWhereClauseItem */
167class WhereClauseItem
168{
169public:
170 virtual ~WhereClauseItem () {}
171
172 // Unique pointer custom clone function
173 std::unique_ptr<WhereClauseItem> clone_where_clause_item () const
174 {
175 return std::unique_ptr<WhereClauseItem> (clone_where_clause_item_impl ());
176 }
177
178 virtual std::string as_string () const = 0;
179
180 virtual void accept_vis (ASTVisitor &vis) = 0;
181
182 virtual NodeId get_node_id () const = 0;
183
184protected:
185 // Clone function implementation as pure virtual method
186 virtual WhereClauseItem *clone_where_clause_item_impl () const = 0;
187};
188
189// A lifetime where clause item
190class LifetimeWhereClauseItem : public WhereClauseItem
191{
192 Lifetime lifetime;
193 std::vector<Lifetime> lifetime_bounds;
194 Location locus;
195 NodeId node_id;
196
197public:
198 LifetimeWhereClauseItem (Lifetime lifetime,
199 std::vector<Lifetime> lifetime_bounds,
200 Location locus)
201 : lifetime (std::move (lifetime)),
202 lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
203 node_id (Analysis::Mappings::get ()->get_next_node_id ())
204 {}
205
206 std::string as_string () const override;
207
208 void accept_vis (ASTVisitor &vis) override;
209
210 NodeId get_node_id () const override final { return node_id; }
211
212 Lifetime &get_lifetime () { return lifetime; }
213
214 std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
215
216 Location get_locus () const { return locus; }
217
218protected:
219 // Clone function implementation as (not pure) virtual method
220 LifetimeWhereClauseItem *clone_where_clause_item_impl () const override
221 {
222 return new LifetimeWhereClauseItem (*this);
223 }
224};
225
226// A type bound where clause item
227class TypeBoundWhereClauseItem : public WhereClauseItem
228{
229 std::vector<LifetimeParam> for_lifetimes;
230 std::unique_ptr<Type> bound_type;
231 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
232 NodeId node_id;
233 Location locus;
234
235public:
236 // Returns whether the item has ForLifetimes
237 bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
238
bd2240d3
JD
239 std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
240
438ae944
JP
241 // Returns whether the item has type param bounds
242 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
243
244 TypeBoundWhereClauseItem (
245 std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type,
246 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
247 Location locus)
248 : for_lifetimes (std::move (for_lifetimes)),
249 bound_type (std::move (bound_type)),
250 type_param_bounds (std::move (type_param_bounds)),
251 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
252 {}
253
254 // Copy constructor requires clone
255 TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
256 : for_lifetimes (other.for_lifetimes),
257 bound_type (other.bound_type->clone_type ())
258 {
259 node_id = other.node_id;
260 type_param_bounds.reserve (other.type_param_bounds.size ());
261 for (const auto &e : other.type_param_bounds)
262 type_param_bounds.push_back (e->clone_type_param_bound ());
263 }
264
265 // Overload assignment operator to clone
266 TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other)
267 {
268 node_id = other.node_id;
269 for_lifetimes = other.for_lifetimes;
270 bound_type = other.bound_type->clone_type ();
271 type_param_bounds.reserve (other.type_param_bounds.size ());
272 for (const auto &e : other.type_param_bounds)
273 type_param_bounds.push_back (e->clone_type_param_bound ());
274
275 return *this;
276 }
277
278 // move constructors
279 TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default;
280 TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other)
281 = default;
282
283 std::string as_string () const override;
284
285 void accept_vis (ASTVisitor &vis) override;
286
287 std::unique_ptr<Type> &get_type ()
288 {
289 rust_assert (bound_type != nullptr);
290 return bound_type;
291 }
292
293 // TODO: this mutable getter seems really dodgy. Think up better way.
294 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
295 {
296 return type_param_bounds;
297 }
298
299 const std::vector<std::unique_ptr<TypeParamBound>> &
300 get_type_param_bounds () const
301 {
302 return type_param_bounds;
303 }
304
305 NodeId get_node_id () const override final { return node_id; }
306
307 Location get_locus () const { return locus; }
308
309protected:
310 // Clone function implementation as (not pure) virtual method
311 TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
312 {
313 return new TypeBoundWhereClauseItem (*this);
314 }
315};
316
317// A where clause
318struct WhereClause
319{
320private:
321 std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
322 NodeId node_id;
323
324public:
325 WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
326 : where_clause_items (std::move (where_clause_items)),
327 node_id (Analysis::Mappings::get ()->get_next_node_id ())
328 {}
329
330 // copy constructor with vector clone
331 WhereClause (WhereClause const &other)
332 {
333 node_id = other.node_id;
334 where_clause_items.reserve (other.where_clause_items.size ());
335 for (const auto &e : other.where_clause_items)
336 where_clause_items.push_back (e->clone_where_clause_item ());
337 }
338
339 // overloaded assignment operator with vector clone
340 WhereClause &operator= (WhereClause const &other)
341 {
342 node_id = other.node_id;
343 where_clause_items.reserve (other.where_clause_items.size ());
344 for (const auto &e : other.where_clause_items)
345 where_clause_items.push_back (e->clone_where_clause_item ());
346
347 return *this;
348 }
349
350 // move constructors
351 WhereClause (WhereClause &&other) = default;
352 WhereClause &operator= (WhereClause &&other) = default;
353
354 // Creates a WhereClause with no items.
355 static WhereClause create_empty ()
356 {
357 return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
358 }
359
360 // Returns whether the WhereClause has no items.
361 bool is_empty () const { return where_clause_items.empty (); }
362
363 std::string as_string () const;
364
365 NodeId get_node_id () const { return node_id; }
366
367 // TODO: this mutable getter seems kinda dodgy
368 std::vector<std::unique_ptr<WhereClauseItem>> &get_items ()
369 {
370 return where_clause_items;
371 }
372 const std::vector<std::unique_ptr<WhereClauseItem>> &get_items () const
373 {
374 return where_clause_items;
375 }
376};
377
378// A self parameter in a method
379struct SelfParam
380{
381private:
382 bool has_ref;
383 bool is_mut;
384 // bool has_lifetime; // only possible if also ref
385 Lifetime lifetime;
386
387 // bool has_type; // only possible if not ref
388 std::unique_ptr<Type> type;
389
390 NodeId node_id;
391
392 Location locus;
393
394 // Unrestricted constructor used for error state
395 SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
396 : has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)),
397 type (type), node_id (Analysis::Mappings::get ()->get_next_node_id ())
398 {}
399 // this is ok as no outside classes can ever call this
400
401 // TODO: self param can have outer attributes
402
403public:
404 // Returns whether the self-param has a type field.
405 bool has_type () const { return type != nullptr; }
406
407 // Returns whether the self-param has a valid lifetime.
408 bool has_lifetime () const { return !lifetime.is_error (); }
409
410 // Returns whether the self-param is in an error state.
411 bool is_error () const
412 {
413 return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
414 // not having either is not an error
415 }
416
417 // Creates an error state self-param.
418 static SelfParam create_error ()
419 {
420 // cannot have no ref but have a lifetime at the same time
421 return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
422 }
423
424 // Type-based self parameter (not ref, no lifetime)
425 SelfParam (std::unique_ptr<Type> type, bool is_mut, Location locus)
426 : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()),
427 type (std::move (type)),
428 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
429 {}
430
431 // Lifetime-based self parameter (is ref, no type)
432 SelfParam (Lifetime lifetime, bool is_mut, Location locus)
433 : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)),
434 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
435 {}
436
437 // Copy constructor requires clone
438 SelfParam (SelfParam const &other)
439 : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime),
440 node_id (Analysis::Mappings::get ()->get_next_node_id ()),
441 locus (other.locus)
442 {
443 node_id = other.node_id;
444 if (other.type != nullptr)
445 type = other.type->clone_type ();
446 }
447
448 // Overload assignment operator to use clone
449 SelfParam &operator= (SelfParam const &other)
450 {
451 is_mut = other.is_mut;
452 has_ref = other.has_ref;
453 lifetime = other.lifetime;
454 locus = other.locus;
455 node_id = other.node_id;
456
457 if (other.type != nullptr)
458 type = other.type->clone_type ();
459 else
460 type = nullptr;
461
462 return *this;
463 }
464
465 // move constructors
466 SelfParam (SelfParam &&other) = default;
467 SelfParam &operator= (SelfParam &&other) = default;
468
469 std::string as_string () const;
470
471 Location get_locus () const { return locus; }
472
473 bool get_has_ref () const { return has_ref; };
474 bool get_is_mut () const { return is_mut; }
475
476 Lifetime get_lifetime () const { return lifetime; }
477
478 NodeId get_node_id () const { return node_id; }
479
480 // TODO: is this better? Or is a "vis_block" better?
481 std::unique_ptr<Type> &get_type ()
482 {
483 rust_assert (has_type ());
484 return type;
485 }
486};
487
488// Qualifiers for function, i.e. const, unsafe, extern etc.
489struct FunctionQualifiers
490{
491private:
492 AsyncConstStatus const_status;
493 bool has_unsafe;
494 bool has_extern;
495 std::string extern_abi;
496 Location locus;
497
498public:
499 FunctionQualifiers (Location locus, AsyncConstStatus const_status,
500 bool has_unsafe, bool has_extern = false,
501 std::string extern_abi = std::string ())
502 : const_status (const_status), has_unsafe (has_unsafe),
503 has_extern (has_extern), extern_abi (std::move (extern_abi)),
504 locus (locus)
505 {
506 if (!this->extern_abi.empty ())
507 {
508 // having extern is required; not having it is an implementation error
509 rust_assert (has_extern);
510 }
511 }
512
513 std::string as_string () const;
514
515 AsyncConstStatus get_const_status () const { return const_status; }
516 bool is_unsafe () const { return has_unsafe; }
517 bool is_extern () const { return has_extern; }
518 std::string get_extern_abi () const { return extern_abi; }
519 bool has_abi () const { return !extern_abi.empty (); }
520
521 Location get_locus () const { return locus; }
522};
523
524// A function parameter
525struct FunctionParam
526{
527private:
528 std::vector<Attribute> outer_attrs;
529 Location locus;
530 std::unique_ptr<Pattern> param_name;
531 std::unique_ptr<Type> type;
532
533public:
534 FunctionParam (std::unique_ptr<Pattern> param_name,
535 std::unique_ptr<Type> param_type,
536 std::vector<Attribute> outer_attrs, Location locus)
537 : outer_attrs (std::move (outer_attrs)), locus (locus),
538 param_name (std::move (param_name)), type (std::move (param_type)),
539 node_id (Analysis::Mappings::get ()->get_next_node_id ())
540 {}
541
542 // Copy constructor uses clone
543 FunctionParam (FunctionParam const &other)
544 : locus (other.locus), node_id (other.node_id)
545 {
546 // guard to prevent nullptr dereference
547 if (other.param_name != nullptr)
548 param_name = other.param_name->clone_pattern ();
549 if (other.type != nullptr)
550 type = other.type->clone_type ();
551 }
552
553 // Overload assignment operator to use clone
554 FunctionParam &operator= (FunctionParam const &other)
555 {
556 locus = other.locus;
557 node_id = other.node_id;
558
559 // guard to prevent nullptr dereference
560 if (other.param_name != nullptr)
561 param_name = other.param_name->clone_pattern ();
562 else
563 param_name = nullptr;
564 if (other.type != nullptr)
565 type = other.type->clone_type ();
566 else
567 type = nullptr;
568
569 return *this;
570 }
571
572 // move constructors
573 FunctionParam (FunctionParam &&other) = default;
574 FunctionParam &operator= (FunctionParam &&other) = default;
575
576 // Returns whether FunctionParam is in an invalid state.
577 bool is_error () const { return param_name == nullptr || type == nullptr; }
578
579 // Creates an error FunctionParam.
580 static FunctionParam create_error ()
581 {
582 return FunctionParam (nullptr, nullptr, {}, Location ());
583 }
584
585 std::string as_string () const;
586
587 Location get_locus () const { return locus; }
588
589 // TODO: seems kinda dodgy. Think of better way.
590 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
591 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
592
593 // TODO: is this better? Or is a "vis_block" better?
594 std::unique_ptr<Pattern> &get_pattern ()
595 {
596 rust_assert (param_name != nullptr);
597 return param_name;
598 }
599
600 // TODO: is this better? Or is a "vis_block" better?
601 std::unique_ptr<Type> &get_type ()
602 {
603 rust_assert (type != nullptr);
604 return type;
605 }
606 NodeId get_node_id () const { return node_id; }
607
608protected:
609 NodeId node_id;
610};
611
612// Visibility of item - if the item has it, then it is some form of public
613struct Visibility
614{
615public:
616 enum VisType
617 {
618 PRIV,
619 PUB,
620 PUB_CRATE,
621 PUB_SELF,
622 PUB_SUPER,
623 PUB_IN_PATH
624 };
625
626private:
627 VisType vis_type;
628 // Only assigned if vis_type is IN_PATH
629 SimplePath in_path;
b8422289 630 Location locus;
438ae944
JP
631
632 // should this store location info?
633
634public:
635 // Creates a Visibility - TODO make constructor protected or private?
78c70a50 636 Visibility (VisType vis_type, SimplePath in_path, Location locus)
b8422289 637 : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
438ae944
JP
638 {}
639
70808544 640 VisType get_vis_type () const { return vis_type; }
438ae944
JP
641
642 // Returns whether visibility is in an error state.
643 bool is_error () const
644 {
645 return vis_type == PUB_IN_PATH && in_path.is_empty ();
646 }
647
648 // Returns whether a visibility has a path
649 bool has_path () const { return !(is_error ()) && vis_type == PUB_IN_PATH; }
650
651 // Returns whether visibility is public or not.
652 bool is_public () const { return vis_type != PRIV && !is_error (); }
653
b8422289
D
654 Location get_locus () const { return locus; }
655
78c70a50 656 // empty?
438ae944
JP
657 // Creates an error visibility.
658 static Visibility create_error ()
659 {
78c70a50 660 return Visibility (PUB_IN_PATH, SimplePath::create_empty (), Location ());
438ae944
JP
661 }
662
663 // Unique pointer custom clone function
664 /*std::unique_ptr<Visibility> clone_visibility() const {
665 return std::unique_ptr<Visibility>(clone_visibility_impl());
666 }*/
667
668 /* TODO: think of a way to only allow valid Visibility states - polymorphism
669 * is one idea but may be too resource-intensive. */
670
671 // Creates a public visibility with no further features/arguments.
78c70a50
D
672 // empty?
673 static Visibility create_public (Location pub_vis_location)
438ae944 674 {
78c70a50 675 return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
438ae944
JP
676 }
677
678 // Creates a public visibility with crate-relative paths
78c70a50
D
679 static Visibility create_crate (Location crate_tok_location,
680 Location crate_vis_location)
438ae944
JP
681 {
682 return Visibility (PUB_CRATE,
b8422289 683 SimplePath::from_str ("crate", crate_tok_location),
78c70a50 684 crate_vis_location);
438ae944
JP
685 }
686
687 // Creates a public visibility with self-relative paths
78c70a50
D
688 static Visibility create_self (Location self_tok_location,
689 Location self_vis_location)
438ae944
JP
690 {
691 return Visibility (PUB_SELF,
b8422289 692 SimplePath::from_str ("self", self_tok_location),
78c70a50 693 self_vis_location);
438ae944
JP
694 }
695
696 // Creates a public visibility with parent module-relative paths
78c70a50
D
697 static Visibility create_super (Location super_tok_location,
698 Location super_vis_location)
438ae944
JP
699 {
700 return Visibility (PUB_SUPER,
b8422289 701 SimplePath::from_str ("super", super_tok_location),
78c70a50 702 super_vis_location);
438ae944
JP
703 }
704
705 // Creates a private visibility
706 static Visibility create_private ()
707 {
78c70a50 708 return Visibility (PRIV, SimplePath::create_empty (), Location ());
438ae944
JP
709 }
710
711 // Creates a public visibility with a given path or whatever.
78c70a50
D
712 static Visibility create_in_path (SimplePath in_path,
713 Location in_path_vis_location)
438ae944 714 {
78c70a50 715 return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
438ae944
JP
716 }
717
718 std::string as_string () const;
719 const SimplePath &get_path () const { return in_path; }
720 SimplePath &get_path () { return in_path; }
721
722protected:
723 // Clone function implementation - not currently virtual but may be if
724 // polymorphism used
725 /*virtual*/ Visibility *clone_visibility_impl () const
726 {
727 return new Visibility (*this);
728 }
729};
730
731// A method (function belonging to a type)
732class Method : public InherentImplItem, public TraitImplItem
733{
734 std::vector<Attribute> outer_attrs;
735 Visibility vis;
736 FunctionQualifiers qualifiers;
737 Identifier method_name;
738 std::vector<std::unique_ptr<GenericParam>> generic_params;
739 SelfParam self_param;
740 std::vector<FunctionParam> function_params;
741 std::unique_ptr<Type> return_type;
742 WhereClause where_clause;
743 std::unique_ptr<BlockExpr> function_body;
744 Location locus;
745 NodeId node_id;
746
747public:
748 // Returns whether the method is in an error state.
749 bool is_error () const
750 {
751 return function_body == nullptr || method_name.empty ()
752 || self_param.is_error ();
753 }
754
755 // Creates an error state method.
756 static Method create_error ()
757 {
758 return Method ("", FunctionQualifiers (Location (), NONE, true),
759 std::vector<std::unique_ptr<GenericParam>> (),
760 SelfParam::create_error (), std::vector<FunctionParam> (),
761 nullptr, WhereClause::create_empty (), nullptr,
762 Visibility::create_error (), std::vector<Attribute> (), {});
763 }
764
765 // Returns whether the method has generic parameters.
766 bool has_generics () const { return !generic_params.empty (); }
767
768 // Returns whether the method has parameters.
769 bool has_params () const { return !function_params.empty (); }
770
771 // Returns whether the method has a return type (void otherwise).
772 bool has_return_type () const { return return_type != nullptr; }
773
774 // Returns whether the where clause exists (i.e. has items)
775 bool has_where_clause () const { return !where_clause.is_empty (); }
776
777 // Returns whether method has a non-default visibility.
778 bool has_visibility () const { return !vis.is_error (); }
779
780 // Mega-constructor with all possible fields
781 Method (Identifier method_name, FunctionQualifiers qualifiers,
782 std::vector<std::unique_ptr<GenericParam>> generic_params,
783 SelfParam self_param, std::vector<FunctionParam> function_params,
784 std::unique_ptr<Type> return_type, WhereClause where_clause,
785 std::unique_ptr<BlockExpr> function_body, Visibility vis,
786 std::vector<Attribute> outer_attrs, Location locus)
787 : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)),
788 qualifiers (std::move (qualifiers)),
789 method_name (std::move (method_name)),
790 generic_params (std::move (generic_params)),
791 self_param (std::move (self_param)),
792 function_params (std::move (function_params)),
793 return_type (std::move (return_type)),
794 where_clause (std::move (where_clause)),
795 function_body (std::move (function_body)), locus (locus),
796 node_id (Analysis::Mappings::get ()->get_next_node_id ())
797 {}
798
799 // TODO: add constructor with less fields
800
801 // Copy constructor with clone
802 Method (Method const &other)
803 : outer_attrs (other.outer_attrs), vis (other.vis),
804 qualifiers (other.qualifiers), method_name (other.method_name),
805 self_param (other.self_param), function_params (other.function_params),
806 where_clause (other.where_clause), locus (other.locus)
807 {
808 // guard to prevent null dereference (always required)
809 if (other.return_type != nullptr)
810 return_type = other.return_type->clone_type ();
811
812 // guard to prevent null dereference (only required if error state)
813 if (other.function_body != nullptr)
814 function_body = other.function_body->clone_block_expr ();
815
816 generic_params.reserve (other.generic_params.size ());
817 for (const auto &e : other.generic_params)
818 generic_params.push_back (e->clone_generic_param ());
819
820 node_id = other.node_id;
821 }
822
823 // Overloaded assignment operator to clone
824 Method &operator= (Method const &other)
825 {
826 method_name = other.method_name;
827 outer_attrs = other.outer_attrs;
828 vis = other.vis;
829 qualifiers = other.qualifiers;
830 self_param = other.self_param;
831 function_params = other.function_params;
832 where_clause = other.where_clause;
833 locus = other.locus;
834
835 // guard to prevent null dereference (always required)
836 if (other.return_type != nullptr)
837 return_type = other.return_type->clone_type ();
838 else
839 return_type = nullptr;
840
841 // guard to prevent null dereference (only required if error state)
842 if (other.function_body != nullptr)
843 function_body = other.function_body->clone_block_expr ();
844 else
845 function_body = nullptr;
846
847 generic_params.reserve (other.generic_params.size ());
848 for (const auto &e : other.generic_params)
849 generic_params.push_back (e->clone_generic_param ());
850
851 node_id = other.node_id;
852
853 return *this;
854 }
855
856 // move constructors
857 Method (Method &&other) = default;
858 Method &operator= (Method &&other) = default;
859
860 std::string as_string () const override;
861
862 void accept_vis (ASTVisitor &vis) override;
863
864 // Invalid if block is null, so base stripping on that.
865 void mark_for_strip () override { function_body = nullptr; }
866 bool is_marked_for_strip () const override
867 {
868 return function_body == nullptr;
869 }
870
871 // TODO: this mutable getter seems really dodgy. Think up better way.
872 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
873 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
874
875 std::vector<FunctionParam> &get_function_params () { return function_params; }
876 const std::vector<FunctionParam> &get_function_params () const
877 {
878 return function_params;
879 }
880
881 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
882 {
883 return generic_params;
884 }
885 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
886 {
887 return generic_params;
888 }
889
890 // TODO: is this better? Or is a "vis_block" better?
891 std::unique_ptr<BlockExpr> &get_definition ()
892 {
893 rust_assert (function_body != nullptr);
894 return function_body;
895 }
896
897 SelfParam &get_self_param () { return self_param; }
898 const SelfParam &get_self_param () const { return self_param; }
899
900 // TODO: is this better? Or is a "vis_block" better?
901 std::unique_ptr<Type> &get_return_type ()
902 {
903 rust_assert (has_return_type ());
904 return return_type;
905 }
906
907 // TODO: is this better? Or is a "vis_block" better?
908 WhereClause &get_where_clause () { return where_clause; }
909
910 Identifier get_method_name () const { return method_name; }
911
912 NodeId get_node_id () const { return node_id; }
913
914 Location get_locus () const override final { return locus; }
915
916 FunctionQualifiers get_qualifiers () { return qualifiers; }
917
907d1119 918 Visibility &get_visibility () { return vis; }
438ae944
JP
919 const Visibility &get_visibility () const { return vis; }
920
921protected:
922 /* Use covariance to implement clone function as returning this object
923 * rather than base */
924 Method *clone_inherent_impl_item_impl () const final override
925 {
926 return clone_method_impl ();
927 }
928
929 /* Use covariance to implement clone function as returning this object
930 * rather than base */
931 Method *clone_trait_impl_item_impl () const final override
932 {
933 return clone_method_impl ();
934 }
935
936 /*virtual*/ Method *clone_method_impl () const { return new Method (*this); }
937};
938
939// Item that supports visibility - abstract base class
940class VisItem : public Item
941{
942 Visibility visibility;
943 std::vector<Attribute> outer_attrs;
944
945protected:
946 // Visibility constructor
947 VisItem (Visibility visibility,
948 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
949 : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
950 {}
951
952 // Visibility copy constructor
953 VisItem (VisItem const &other)
954 : visibility (other.visibility), outer_attrs (other.outer_attrs)
955 {}
956
957 // Overload assignment operator to clone
958 VisItem &operator= (VisItem const &other)
959 {
960 visibility = other.visibility;
961 outer_attrs = other.outer_attrs;
962
963 return *this;
964 }
965
966 // move constructors
967 VisItem (VisItem &&other) = default;
968 VisItem &operator= (VisItem &&other) = default;
969
970public:
971 /* Does the item have some kind of public visibility (non-default
972 * visibility)? */
973 bool has_visibility () const { return visibility.is_public (); }
974
975 std::string as_string () const override;
976
977 // TODO: this mutable getter seems really dodgy. Think up better way.
978 Visibility &get_visibility () { return visibility; }
979 const Visibility &get_visibility () const { return visibility; }
980
981 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
982 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
983};
984
985// Rust module item - abstract base class
986class Module : public VisItem
987{
988public:
989 // Type of the current module. A module can be either loaded or unloaded,
990 // meaning that the items of the module can already be present or not. For
991 // example, the following module would be loaded: `mod foo { fn bar() {} }`.
992 // However, the module would be unloaded if it refers to an external file (i.e
993 // `mod foo;`) and then become loaded upon expansion.
994 enum ModuleKind
995 {
996 LOADED,
997 UNLOADED,
998 };
999
1000 Identifier get_name () const { return module_name; }
1001
1002private:
1003 Identifier module_name;
1004 Location locus;
1005 ModuleKind kind;
1006
1007 // Name of the file including the module
1008 std::string outer_filename;
1009 // bool has_inner_attrs;
1010 std::vector<Attribute> inner_attrs;
1011 // bool has_items;
1012 std::vector<std::unique_ptr<Item>> items;
1013 // Names of including inline modules (immediate parent is last in the list)
1014 std::vector<std::string> module_scope;
1015
1016 // Filename the module refers to. Empty string on LOADED modules or if an
1017 // error occured when dealing with UNLOADED modules
1018 std::string module_file;
1019
1020 void clone_items (const std::vector<std::unique_ptr<Item>> &other_items)
1021 {
1022 items.reserve (other_items.size ());
1023 for (const auto &e : other_items)
1024 items.push_back (e->clone_item ());
1025 }
1026
1027public:
1028 // Returns whether the module has items in its body.
1029 bool has_items () const { return !items.empty (); }
1030
1031 // Returns whether the module has any inner attributes.
1032 bool has_inner_attrs () const { return !inner_attrs.empty (); }
1033
1034 // Unloaded module constructor
1035 Module (Identifier module_name, Visibility visibility,
1036 std::vector<Attribute> outer_attrs, Location locus,
1037 std::string outer_filename, std::vector<std::string> module_scope)
1038 : VisItem (std::move (visibility), std::move (outer_attrs)),
1039 module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
1040 outer_filename (outer_filename), inner_attrs (std::vector<Attribute> ()),
1041 items (std::vector<std::unique_ptr<Item>> ()),
1042 module_scope (std::move (module_scope))
1043 {}
1044
1045 // Loaded module constructor, with items
1046 Module (Identifier name, Location locus,
1047 std::vector<std::unique_ptr<Item>> items,
1048 Visibility visibility = Visibility::create_error (),
1049 std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
1050 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1051 : VisItem (std::move (visibility), std::move (outer_attrs)),
1052 module_name (name), locus (locus), kind (ModuleKind::LOADED),
1053 outer_filename (std::string ()), inner_attrs (std::move (inner_attrs)),
1054 items (std::move (items))
1055 {}
1056
1057 // Copy constructor with vector clone
1058 Module (Module const &other)
1059 : VisItem (other), module_name (other.module_name), locus (other.locus),
1060 kind (other.kind), inner_attrs (other.inner_attrs),
1061 module_scope (other.module_scope)
1062 {
1063 // We need to check whether we are copying a loaded module or an unloaded
1064 // one. In the second case, clear the `items` vector.
1065 if (other.kind == LOADED)
1066 clone_items (other.items);
1067 else
1068 items.clear ();
1069 }
1070
1071 // Overloaded assignment operator with vector clone
1072 Module &operator= (Module const &other)
1073 {
1074 VisItem::operator= (other);
1075
1076 module_name = other.module_name;
1077 locus = other.locus;
1078 kind = other.kind;
1079 inner_attrs = other.inner_attrs;
1080 module_scope = other.module_scope;
1081
1082 // Likewise, we need to clear the `items` vector in case the other module is
1083 // unloaded
1084 if (kind == LOADED)
1085 clone_items (other.items);
1086 else
1087 items.clear ();
1088
1089 return *this;
1090 }
1091
1092 // Search for the filename associated with an external module, storing it in
1093 // module_file
1094 void process_file_path ();
1095 // Load the items contained in an external module
1096 void load_items ();
1097
1098 void accept_vis (ASTVisitor &vis) override;
1099
1100 /* Override that runs the function recursively on all items contained within
1101 * the module. */
1102 void add_crate_name (std::vector<std::string> &names) const override;
1103
1104 // Returns the kind of the module
1105 enum ModuleKind get_kind () const { return kind; }
1106
1107 // TODO: think of better way to do this - mutable getter seems dodgy
1108 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
1109 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
1110
1111 const std::vector<std::unique_ptr<Item>> &get_items () const { return items; }
1112 std::vector<std::unique_ptr<Item>> &get_items () { return items; }
1113
1114 // move constructors
1115 Module (Module &&other) = default;
1116 Module &operator= (Module &&other) = default;
1117
1118 std::string as_string () const override;
1119
1120 Location get_locus () const override final { return locus; }
1121
1122 // Invalid if name is empty, so base stripping on that.
1123 void mark_for_strip () override { module_name = ""; }
1124 bool is_marked_for_strip () const override { return module_name.empty (); }
1125
1126protected:
1127 /* Use covariance to implement clone function as returning this object
1128 * rather than base */
1129 Module *clone_item_impl () const override { return new Module (*this); }
1130};
1131
1132// Rust extern crate declaration AST node
1133class ExternCrate : public VisItem
1134{
1135 // this is either an identifier or "self", with self parsed to string
1136 std::string referenced_crate;
1137 // bool has_as_clause;
1138 // AsClause as_clause;
1139 // this is either an identifier or "_", with _ parsed to string
1140 std::string as_clause_name;
1141
1142 Location locus;
1143
1144 /* e.g.
1145 "extern crate foo as _"
1146 "extern crate foo"
1147 "extern crate std as cool_std" */
1148public:
1149 std::string as_string () const override;
1150
1151 // Returns whether extern crate declaration has an as clause.
1152 bool has_as_clause () const { return !as_clause_name.empty (); }
1153
1154 /* Returns whether extern crate declaration references the current crate
1155 * (i.e. self). */
1156 bool references_self () const { return referenced_crate == "self"; }
1157
1158 // Constructor
1159 ExternCrate (std::string referenced_crate, Visibility visibility,
1160 std::vector<Attribute> outer_attrs, Location locus,
1161 std::string as_clause_name = std::string ())
1162 : VisItem (std::move (visibility), std::move (outer_attrs)),
1163 referenced_crate (std::move (referenced_crate)),
1164 as_clause_name (std::move (as_clause_name)), locus (locus)
1165 {}
1166
1167 Location get_locus () const override final { return locus; }
1168
1169 void accept_vis (ASTVisitor &vis) override;
1170
1171 const std::string &get_referenced_crate () const { return referenced_crate; }
1172 const std::string &get_as_clause () const { return as_clause_name; }
1173
1174 // Override that adds extern crate name in decl to passed list of names.
1175 void add_crate_name (std::vector<std::string> &names) const override
1176 {
1177 names.push_back (referenced_crate);
1178 }
1179
1180 // Invalid if crate name is empty, so base stripping on that.
1181 void mark_for_strip () override { referenced_crate = ""; }
1182 bool is_marked_for_strip () const override
1183 {
1184 return referenced_crate.empty ();
1185 }
1186
1187protected:
1188 /* Use covariance to implement clone function as returning this object
1189 * rather than base */
1190 ExternCrate *clone_item_impl () const override
1191 {
1192 return new ExternCrate (*this);
1193 }
1194};
1195
1196// The path-ish thing referred to in a use declaration - abstract base class
1197class UseTree
1198{
1199 Location locus;
1200
1201public:
1202 enum Kind
1203 {
1204 Glob,
1205 Rebind,
1206 List,
1207 };
1208
1209 virtual ~UseTree () {}
1210
1211 // Overload assignment operator to clone
1212 UseTree &operator= (UseTree const &other)
1213 {
1214 locus = other.locus;
1215
1216 return *this;
1217 }
1218
1219 UseTree (const UseTree &other) = default;
1220
1221 // move constructors
1222 UseTree (UseTree &&other) = default;
1223 UseTree &operator= (UseTree &&other) = default;
1224
1225 // Unique pointer custom clone function
1226 std::unique_ptr<UseTree> clone_use_tree () const
1227 {
1228 return std::unique_ptr<UseTree> (clone_use_tree_impl ());
1229 }
1230
1231 virtual std::string as_string () const = 0;
1232 virtual Kind get_kind () const = 0;
1233
1234 Location get_locus () const { return locus; }
1235
1236 virtual void accept_vis (ASTVisitor &vis) = 0;
1237
1238protected:
1239 // Clone function implementation as pure virtual method
1240 virtual UseTree *clone_use_tree_impl () const = 0;
1241
1242 UseTree (Location locus) : locus (locus) {}
1243};
1244
1245// Use tree with a glob (wildcard) operator
1246class UseTreeGlob : public UseTree
1247{
1248public:
1249 enum PathType
1250 {
1251 NO_PATH,
1252 GLOBAL,
1253 PATH_PREFIXED
1254 };
1255
1256private:
1257 PathType glob_type;
1258 SimplePath path;
1259
1260public:
1261 UseTreeGlob (PathType glob_type, SimplePath path, Location locus)
1262 : UseTree (locus), glob_type (glob_type), path (std::move (path))
1263 {
1264 if (this->glob_type != PATH_PREFIXED)
1265 {
1266 // compiler implementation error if there is a path with a
1267 // non-path-prefixed use tree glob
1268 rust_assert (!has_path ());
1269 }
1270 // TODO: do path-prefixed paths also have to have a path? If so, have an
1271 // assert for that too.
1272 }
1273
1274 /* Returns whether has path. Should be made redundant by PathType
1275 * PATH_PREFIXED. */
1276 bool has_path () const { return !path.is_empty (); }
1277
1278 std::string as_string () const override;
1279
1280 void accept_vis (ASTVisitor &vis) override;
1281
1282 Kind get_kind () const override { return Glob; }
1283
1284 SimplePath get_path () const
1285 {
1286 rust_assert (has_path ());
1287 return path;
1288 }
1289
1290 /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory
1291 * methods? */
1292protected:
1293 /* Use covariance to implement clone function as returning this object
1294 * rather than base */
1295 UseTreeGlob *clone_use_tree_impl () const override
1296 {
1297 return new UseTreeGlob (*this);
1298 }
1299};
1300
1301// Use tree with a list of paths with a common prefix
1302class UseTreeList : public UseTree
1303{
1304public:
1305 enum PathType
1306 {
1307 NO_PATH,
1308 GLOBAL,
1309 PATH_PREFIXED
1310 };
1311
1312private:
1313 PathType path_type;
1314 SimplePath path;
1315
1316 std::vector<std::unique_ptr<UseTree>> trees;
1317
1318public:
1319 UseTreeList (PathType path_type, SimplePath path,
1320 std::vector<std::unique_ptr<UseTree>> trees, Location locus)
1321 : UseTree (locus), path_type (path_type), path (std::move (path)),
1322 trees (std::move (trees))
1323 {
1324 if (this->path_type != PATH_PREFIXED)
1325 {
1326 // compiler implementation error if there is a path with a
1327 // non-path-prefixed use tree glob
1328 rust_assert (!has_path ());
1329 }
1330 // TODO: do path-prefixed paths also have to have a path? If so, have an
1331 // assert for that too.
1332 }
1333
1334 // copy constructor with vector clone
1335 UseTreeList (UseTreeList const &other)
1336 : UseTree (other), path_type (other.path_type), path (other.path)
1337 {
1338 trees.reserve (other.trees.size ());
1339 for (const auto &e : other.trees)
1340 trees.push_back (e->clone_use_tree ());
1341 }
1342
1343 // overloaded assignment operator with vector clone
1344 UseTreeList &operator= (UseTreeList const &other)
1345 {
1346 UseTree::operator= (other);
1347 path_type = other.path_type;
1348 path = other.path;
1349
1350 trees.reserve (other.trees.size ());
1351 for (const auto &e : other.trees)
1352 trees.push_back (e->clone_use_tree ());
1353
1354 return *this;
1355 }
1356
1357 // move constructors
1358 UseTreeList (UseTreeList &&other) = default;
1359 UseTreeList &operator= (UseTreeList &&other) = default;
1360
1361 // Returns whether has path. Should be made redundant by path_type.
1362 bool has_path () const { return !path.is_empty (); }
1363
1364 // Returns whether has inner tree elements.
1365 bool has_trees () const { return !trees.empty (); }
1366
1367 std::string as_string () const override;
1368
1369 void accept_vis (ASTVisitor &vis) override;
1370
1371 Kind get_kind () const override { return List; }
1372 SimplePath get_path () const
1373 {
1374 rust_assert (has_path ());
1375 return path;
1376 }
1377
1378 const std::vector<std::unique_ptr<UseTree>> &get_trees () const
1379 {
1380 return trees;
1381 }
1382
1383 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1384 // methods?
1385protected:
1386 /* Use covariance to implement clone function as returning this object
1387 * rather than base */
1388 UseTreeList *clone_use_tree_impl () const override
1389 {
1390 return new UseTreeList (*this);
1391 }
1392};
1393
1394// Use tree where it rebinds the module name as something else
1395class UseTreeRebind : public UseTree
1396{
1397public:
1398 enum NewBindType
1399 {
1400 NONE,
1401 IDENTIFIER,
1402 WILDCARD
1403 };
1404
1405private:
1406 SimplePath path;
1407
1408 NewBindType bind_type;
1409 Identifier identifier; // only if NewBindType is IDENTIFIER
1410
1411public:
1412 UseTreeRebind (NewBindType bind_type, SimplePath path, Location locus,
1413 Identifier identifier = std::string ())
1414 : UseTree (locus), path (std::move (path)), bind_type (bind_type),
1415 identifier (std::move (identifier))
1416 {}
1417
1418 // Returns whether has path (this should always be true).
1419 bool has_path () const { return !path.is_empty (); }
1420
1421 // Returns whether has identifier (or, rather, is allowed to).
1422 bool has_identifier () const { return bind_type == IDENTIFIER; }
1423
1424 std::string as_string () const override;
1425
1426 void accept_vis (ASTVisitor &vis) override;
1427
1428 Kind get_kind () const override { return Rebind; }
1429
1430 SimplePath get_path () const
1431 {
1432 rust_assert (has_path ());
1433 return path;
1434 }
1435
1436 const Identifier &get_identifier () const
1437 {
1438 rust_assert (has_identifier ());
1439 return identifier;
1440 }
1441
1442 // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory
1443 // methods?
1444protected:
1445 /* Use covariance to implement clone function as returning this object
1446 * rather than base */
1447 virtual UseTreeRebind *clone_use_tree_impl () const override
1448 {
1449 return new UseTreeRebind (*this);
1450 }
1451};
1452
1453// Rust use declaration (i.e. for modules) AST node
1454class UseDeclaration : public VisItem
1455{
1456 std::unique_ptr<UseTree> use_tree;
1457 Location locus;
1458
1459public:
1460 std::string as_string () const override;
1461
1462 UseDeclaration (std::unique_ptr<UseTree> use_tree, Visibility visibility,
1463 std::vector<Attribute> outer_attrs, Location locus)
1464 : VisItem (std::move (visibility), std::move (outer_attrs)),
1465 use_tree (std::move (use_tree)), locus (locus)
1466 {}
1467
1468 // Copy constructor with clone
1469 UseDeclaration (UseDeclaration const &other)
1470 : VisItem (other), locus (other.locus)
1471 {
1472 // guard to prevent null dereference (only required if error state)
1473 if (other.use_tree != nullptr)
1474 use_tree = other.use_tree->clone_use_tree ();
1475 }
1476
1477 // Overloaded assignment operator to clone
1478 UseDeclaration &operator= (UseDeclaration const &other)
1479 {
1480 VisItem::operator= (other);
1481 // visibility = other.visibility->clone_visibility();
1482 // outer_attrs = other.outer_attrs;
1483 locus = other.locus;
1484
1485 // guard to prevent null dereference (only required if error state)
1486 if (other.use_tree != nullptr)
1487 use_tree = other.use_tree->clone_use_tree ();
1488 else
1489 use_tree = nullptr;
1490
1491 return *this;
1492 }
1493
1494 // move constructors
1495 UseDeclaration (UseDeclaration &&other) = default;
1496 UseDeclaration &operator= (UseDeclaration &&other) = default;
1497
1498 Location get_locus () const override final { return locus; }
1499 const std::unique_ptr<UseTree> &get_tree () const { return use_tree; }
1500
1501 void accept_vis (ASTVisitor &vis) override;
1502
1503 // Invalid if use tree is null, so base stripping on that.
1504 void mark_for_strip () override { use_tree = nullptr; }
1505 bool is_marked_for_strip () const override { return use_tree == nullptr; }
1506
1507protected:
1508 /* Use covariance to implement clone function as returning this object
1509 * rather than base */
1510 UseDeclaration *clone_item_impl () const override
1511 {
1512 return new UseDeclaration (*this);
1513 }
1514};
1515
1516class LetStmt;
1517
1518// Rust function declaration AST node
1519class Function : public VisItem, public InherentImplItem, public TraitImplItem
1520{
1521 FunctionQualifiers qualifiers;
1522 Identifier function_name;
1523 std::vector<std::unique_ptr<GenericParam>> generic_params;
1524 std::vector<FunctionParam> function_params;
1525 std::unique_ptr<Type> return_type;
1526 WhereClause where_clause;
1527 std::unique_ptr<BlockExpr> function_body;
1528 Location locus;
1529
1530public:
1531 std::string as_string () const override;
1532
1533 // Returns whether function has generic parameters.
1534 bool has_generics () const { return !generic_params.empty (); }
1535
1536 // Returns whether function has regular parameters.
1537 bool has_function_params () const { return !function_params.empty (); }
1538
1539 // Returns whether function has return type - if not, it is void.
1540 bool has_return_type () const { return return_type != nullptr; }
1541
1542 // Returns whether function has a where clause.
1543 bool has_where_clause () const { return !where_clause.is_empty (); }
1544
1545 // Mega-constructor with all possible fields
1546 Function (Identifier function_name, FunctionQualifiers qualifiers,
1547 std::vector<std::unique_ptr<GenericParam>> generic_params,
1548 std::vector<FunctionParam> function_params,
1549 std::unique_ptr<Type> return_type, WhereClause where_clause,
1550 std::unique_ptr<BlockExpr> function_body, Visibility vis,
1551 std::vector<Attribute> outer_attrs, Location locus)
1552 : VisItem (std::move (vis), std::move (outer_attrs)),
1553 qualifiers (std::move (qualifiers)),
1554 function_name (std::move (function_name)),
1555 generic_params (std::move (generic_params)),
1556 function_params (std::move (function_params)),
1557 return_type (std::move (return_type)),
1558 where_clause (std::move (where_clause)),
1559 function_body (std::move (function_body)), locus (locus)
1560 {}
1561
1562 // TODO: add constructor with less fields
1563
1564 // Copy constructor with clone
1565 Function (Function const &other)
1566 : VisItem (other), qualifiers (other.qualifiers),
1567 function_name (other.function_name),
1568 function_params (other.function_params),
1569 where_clause (other.where_clause), locus (other.locus)
1570 {
1571 // guard to prevent null dereference (always required)
1572 if (other.return_type != nullptr)
1573 return_type = other.return_type->clone_type ();
1574
1575 // guard to prevent null dereference (only required if error state)
1576 if (other.function_body != nullptr)
1577 function_body = other.function_body->clone_block_expr ();
1578
1579 generic_params.reserve (other.generic_params.size ());
1580 for (const auto &e : other.generic_params)
1581 generic_params.push_back (e->clone_generic_param ());
1582 }
1583
1584 // Overloaded assignment operator to clone
1585 Function &operator= (Function const &other)
1586 {
1587 VisItem::operator= (other);
1588 function_name = other.function_name;
1589 qualifiers = other.qualifiers;
1590 function_params = other.function_params;
1591 where_clause = other.where_clause;
1592 // visibility = other.visibility->clone_visibility();
1593 // outer_attrs = other.outer_attrs;
1594 locus = other.locus;
1595
1596 // guard to prevent null dereference (always required)
1597 if (other.return_type != nullptr)
1598 return_type = other.return_type->clone_type ();
1599 else
1600 return_type = nullptr;
1601
1602 // guard to prevent null dereference (only required if error state)
1603 if (other.function_body != nullptr)
1604 function_body = other.function_body->clone_block_expr ();
1605 else
1606 function_body = nullptr;
1607
1608 generic_params.reserve (other.generic_params.size ());
1609 for (const auto &e : other.generic_params)
1610 generic_params.push_back (e->clone_generic_param ());
1611
1612 return *this;
1613 }
1614
1615 // move constructors
1616 Function (Function &&other) = default;
1617 Function &operator= (Function &&other) = default;
1618
1619 Location get_locus () const override final { return locus; }
1620
1621 void accept_vis (ASTVisitor &vis) override;
1622
1623 // Invalid if block is null, so base stripping on that.
1624 void mark_for_strip () override { function_body = nullptr; }
1625 bool is_marked_for_strip () const override
1626 {
1627 return function_body == nullptr;
1628 }
1629
1630 std::vector<FunctionParam> &get_function_params () { return function_params; }
1631 const std::vector<FunctionParam> &get_function_params () const
1632 {
1633 return function_params;
1634 }
1635
1636 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1637 {
1638 return generic_params;
1639 }
1640 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1641 {
1642 return generic_params;
1643 }
1644
1645 // TODO: is this better? Or is a "vis_block" better?
1646 std::unique_ptr<BlockExpr> &get_definition ()
1647 {
1648 rust_assert (function_body != nullptr);
1649 return function_body;
1650 }
1651
1652 const FunctionQualifiers &get_qualifiers () const { return qualifiers; }
1653
1654 Identifier get_function_name () const { return function_name; }
1655
1656 // TODO: is this better? Or is a "vis_block" better?
1657 WhereClause &get_where_clause () { return where_clause; }
1658
1659 // TODO: is this better? Or is a "vis_block" better?
1660 std::unique_ptr<Type> &get_return_type ()
1661 {
1662 rust_assert (has_return_type ());
1663 return return_type;
1664 }
1665
1666protected:
1667 /* Use covariance to implement clone function as returning this object
1668 * rather than base */
1669 Function *clone_item_impl () const override { return new Function (*this); }
1670
1671 /* Use covariance to implement clone function as returning this object
1672 * rather than base */
1673 Function *clone_inherent_impl_item_impl () const override
1674 {
1675 return new Function (*this);
1676 }
1677
1678 /* Use covariance to implement clone function as returning this object
1679 * rather than base */
1680 Function *clone_trait_impl_item_impl () const override
1681 {
1682 return new Function (*this);
1683 }
1684};
1685
1686// Rust type alias (i.e. typedef) AST node
1687class TypeAlias : public VisItem, public TraitImplItem
1688{
1689 Identifier new_type_name;
1690
1691 // bool has_generics;
1692 // Generics generic_params;
1693 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1694
1695 // bool has_where_clause;
1696 WhereClause where_clause;
1697
1698 std::unique_ptr<Type> existing_type;
1699
1700 Location locus;
1701
1702public:
1703 std::string as_string () const override;
1704
1705 // Returns whether type alias has generic parameters.
1706 bool has_generics () const { return !generic_params.empty (); }
1707
1708 // Returns whether type alias has a where clause.
1709 bool has_where_clause () const { return !where_clause.is_empty (); }
1710
1711 // Mega-constructor with all possible fields
1712 TypeAlias (Identifier new_type_name,
1713 std::vector<std::unique_ptr<GenericParam>> generic_params,
1714 WhereClause where_clause, std::unique_ptr<Type> existing_type,
1715 Visibility vis, std::vector<Attribute> outer_attrs, Location locus)
1716 : VisItem (std::move (vis), std::move (outer_attrs)),
1717 new_type_name (std::move (new_type_name)),
1718 generic_params (std::move (generic_params)),
1719 where_clause (std::move (where_clause)),
1720 existing_type (std::move (existing_type)), locus (locus)
1721 {}
1722
1723 // Copy constructor
1724 TypeAlias (TypeAlias const &other)
1725 : VisItem (other), new_type_name (other.new_type_name),
1726 where_clause (other.where_clause), locus (other.locus)
1727 {
1728 // guard to prevent null dereference (only required if error state)
1729 if (other.existing_type != nullptr)
1730 existing_type = other.existing_type->clone_type ();
1731
1732 generic_params.reserve (other.generic_params.size ());
1733 for (const auto &e : other.generic_params)
1734 generic_params.push_back (e->clone_generic_param ());
1735 }
1736
1737 // Overloaded assignment operator to clone
1738 TypeAlias &operator= (TypeAlias const &other)
1739 {
1740 VisItem::operator= (other);
1741 new_type_name = other.new_type_name;
1742 where_clause = other.where_clause;
1743 // visibility = other.visibility->clone_visibility();
1744 // outer_attrs = other.outer_attrs;
1745 locus = other.locus;
1746
1747 // guard to prevent null dereference (only required if error state)
1748 if (other.existing_type != nullptr)
1749 existing_type = other.existing_type->clone_type ();
1750 else
1751 existing_type = nullptr;
1752
1753 generic_params.reserve (other.generic_params.size ());
1754 for (const auto &e : other.generic_params)
1755 generic_params.push_back (e->clone_generic_param ());
1756
1757 return *this;
1758 }
1759
1760 // move constructors
1761 TypeAlias (TypeAlias &&other) = default;
1762 TypeAlias &operator= (TypeAlias &&other) = default;
1763
1764 Location get_locus () const override final { return locus; }
1765
1766 void accept_vis (ASTVisitor &vis) override;
1767
1768 // Invalid if existing type is null, so base stripping on that.
1769 void mark_for_strip () override { existing_type = nullptr; }
1770 bool is_marked_for_strip () const override
1771 {
1772 return existing_type == nullptr;
1773 }
1774
1775 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1776 {
1777 return generic_params;
1778 }
1779 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1780 {
1781 return generic_params;
1782 }
1783
1784 // TODO: is this better? Or is a "vis_block" better?
1785 WhereClause &get_where_clause () { return where_clause; }
1786
1787 // TODO: is this better? Or is a "vis_block" better?
1788 std::unique_ptr<Type> &get_type_aliased ()
1789 {
1790 rust_assert (existing_type != nullptr);
1791 return existing_type;
1792 }
1793
1794 Identifier get_new_type_name () const { return new_type_name; }
1795
1796protected:
1797 /* Use covariance to implement clone function as returning this object
1798 * rather than base */
1799 TypeAlias *clone_item_impl () const override { return new TypeAlias (*this); }
1800
1801 /* Use covariance to implement clone function as returning this object
1802 * rather than base */
1803 TypeAlias *clone_trait_impl_item_impl () const override
1804 {
1805 return new TypeAlias (*this);
1806 }
1807};
1808
1809// Rust base struct declaration AST node - abstract base class
1810class Struct : public VisItem
1811{
1812protected:
1813 // protected to enable access by derived classes - allows better as_string
1814 Identifier struct_name;
1815
1816 // bool has_generics;
1817 // Generics generic_params;
1818 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
1819
1820 // bool has_where_clause;
1821 WhereClause where_clause;
1822
1823private:
1824 Location locus;
1825
1826public:
1827 // Returns whether struct has generic parameters.
1828 bool has_generics () const { return !generic_params.empty (); }
1829
1830 // Returns whether struct has a where clause.
1831 bool has_where_clause () const { return !where_clause.is_empty (); }
1832
1833 Location get_locus () const override final { return locus; }
1834
1835 // Invalid if name is empty, so base stripping on that.
1836 void mark_for_strip () override { struct_name = ""; }
1837 bool is_marked_for_strip () const override { return struct_name.empty (); }
1838
1839 Identifier get_struct_name () const { return struct_name; }
1840
1841 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
1842 {
1843 return generic_params;
1844 }
1845 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
1846 {
1847 return generic_params;
1848 }
1849
1850 // TODO: is this better? Or is a "vis_block" better?
1851 WhereClause &get_where_clause () { return where_clause; }
1852
1853 Identifier get_identifier () const { return struct_name; }
1854
1855protected:
1856 Struct (Identifier struct_name,
1857 std::vector<std::unique_ptr<GenericParam>> generic_params,
1858 WhereClause where_clause, Visibility vis, Location locus,
1859 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1860 : VisItem (std::move (vis), std::move (outer_attrs)),
1861 struct_name (std::move (struct_name)),
1862 generic_params (std::move (generic_params)),
1863 where_clause (std::move (where_clause)), locus (locus)
1864 {}
1865
1866 // Copy constructor with vector clone
1867 Struct (Struct const &other)
1868 : VisItem (other), struct_name (other.struct_name),
1869 where_clause (other.where_clause), locus (other.locus)
1870 {
1871 generic_params.reserve (other.generic_params.size ());
1872 for (const auto &e : other.generic_params)
1873 generic_params.push_back (e->clone_generic_param ());
1874 }
1875
1876 // Overloaded assignment operator with vector clone
1877 Struct &operator= (Struct const &other)
1878 {
1879 VisItem::operator= (other);
1880 struct_name = other.struct_name;
1881 where_clause = other.where_clause;
1882 locus = other.locus;
1883
1884 generic_params.reserve (other.generic_params.size ());
1885 for (const auto &e : other.generic_params)
1886 generic_params.push_back (e->clone_generic_param ());
1887
1888 return *this;
1889 }
1890
1891 // move constructors
1892 Struct (Struct &&other) = default;
1893 Struct &operator= (Struct &&other) = default;
1894};
1895
1896// A single field in a struct
1897struct StructField
1898{
1899private:
1900 // bool has_outer_attributes;
1901 std::vector<Attribute> outer_attrs;
1902
1903 // bool has_visibility;
1904 Visibility visibility;
1905
1906 Identifier field_name;
1907 std::unique_ptr<Type> field_type;
1908
1909 NodeId node_id;
1910
1911 Location locus;
1912
1913public:
1914 // Returns whether struct field has any outer attributes.
1915 bool has_outer_attributes () const { return !outer_attrs.empty (); }
1916
1917 // Returns whether struct field has a non-private (non-default) visibility.
1918 bool has_visibility () const { return !visibility.is_error (); }
1919
1920 StructField (Identifier field_name, std::unique_ptr<Type> field_type,
1921 Visibility vis, Location locus,
1922 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1923 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
1924 field_name (std::move (field_name)), field_type (std::move (field_type)),
1925 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
1926 {}
1927
1928 // Copy constructor
1929 StructField (StructField const &other)
1930 : outer_attrs (other.outer_attrs), visibility (other.visibility),
1931 field_name (other.field_name), node_id (other.node_id),
1932 locus (other.locus)
1933 {
1934 // guard to prevent null dereference
1935 if (other.field_type != nullptr)
1936 field_type = other.field_type->clone_type ();
1937 }
1938
1939 ~StructField () = default;
1940
1941 // Overloaded assignment operator to clone
1942 StructField &operator= (StructField const &other)
1943 {
1944 field_name = other.field_name;
1945 visibility = other.visibility;
1946 outer_attrs = other.outer_attrs;
1947 node_id = other.node_id;
1948
1949 // guard to prevent null dereference
1950 if (other.field_type != nullptr)
1951 field_type = other.field_type->clone_type ();
1952 else
1953 field_type = nullptr;
1954
1955 return *this;
1956 }
1957
1958 // move constructors
1959 StructField (StructField &&other) = default;
1960 StructField &operator= (StructField &&other) = default;
1961
1962 // Returns whether struct field is in an error state.
1963 bool is_error () const
1964 {
1965 return field_name.empty () && field_type == nullptr;
1966 // this should really be an or since neither are allowed
1967 }
1968
1969 // Creates an error state struct field.
1970 static StructField create_error ()
1971 {
1972 return StructField (std::string (""), nullptr, Visibility::create_error (),
1973 Location ());
1974 }
1975
1976 std::string as_string () const;
1977
1978 // TODO: this mutable getter seems really dodgy. Think up better way.
1979 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
1980 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1981
1982 Identifier get_field_name () const { return field_name; }
1983
1984 Location get_locus () const { return locus; }
1985
1986 // TODO: is this better? Or is a "vis_block" better?
1987 std::unique_ptr<Type> &get_field_type ()
1988 {
1989 rust_assert (field_type != nullptr);
1990 return field_type;
1991 }
1992
907d1119 1993 Visibility &get_visibility () { return visibility; }
438ae944
JP
1994 const Visibility &get_visibility () const { return visibility; }
1995
1996 NodeId get_node_id () const { return node_id; }
1997};
1998
1999// Rust struct declaration with true struct type AST node
2000class StructStruct : public Struct
2001{
2002 std::vector<StructField> fields;
2003 bool is_unit;
2004
2005public:
2006 std::string as_string () const override;
2007
2008 // Mega-constructor with all possible fields
2009 StructStruct (std::vector<StructField> fields, Identifier struct_name,
2010 std::vector<std::unique_ptr<GenericParam>> generic_params,
2011 WhereClause where_clause, bool is_unit, Visibility vis,
2012 std::vector<Attribute> outer_attrs, Location locus)
2013 : Struct (std::move (struct_name), std::move (generic_params),
2014 std::move (where_clause), std::move (vis), locus,
2015 std::move (outer_attrs)),
2016 fields (std::move (fields)), is_unit (is_unit)
2017 {}
2018
2019 // Unit struct constructor
2020 StructStruct (Identifier struct_name,
2021 std::vector<std::unique_ptr<GenericParam>> generic_params,
2022 WhereClause where_clause, Visibility vis,
2023 std::vector<Attribute> outer_attrs, Location locus)
2024 : Struct (std::move (struct_name), std::move (generic_params),
2025 std::move (where_clause), std::move (vis), locus,
2026 std::move (outer_attrs)),
2027 is_unit (true)
2028 {}
2029
2030 /* Returns whether the struct is a unit struct - struct defined without
2031 * fields. This is important because it also means an implicit constant of its
2032 * type is defined. */
2033 bool is_unit_struct () const { return is_unit; }
2034
2035 void accept_vis (ASTVisitor &vis) override;
2036
2037 // TODO: this mutable getter seems really dodgy. Think up better way.
2038 std::vector<StructField> &get_fields () { return fields; }
2039 const std::vector<StructField> &get_fields () const { return fields; }
2040
2041protected:
2042 /* Use covariance to implement clone function as returning this object
2043 * rather than base */
2044 StructStruct *clone_item_impl () const override
2045 {
2046 return new StructStruct (*this);
2047 }
2048};
2049
2050// A single field in a tuple
2051struct TupleField
2052{
2053private:
2054 // bool has_outer_attributes;
2055 std::vector<Attribute> outer_attrs;
2056
2057 // bool has_visibility;
2058 Visibility visibility;
2059
2060 std::unique_ptr<Type> field_type;
2061
2062 NodeId node_id;
2063
2064 Location locus;
2065
2066public:
2067 // Returns whether tuple field has outer attributes.
2068 bool has_outer_attributes () const { return !outer_attrs.empty (); }
2069
2070 /* Returns whether tuple field has a non-default visibility (i.e. a public
2071 * one) */
2072 bool has_visibility () const { return !visibility.is_error (); }
2073
2074 // Complete constructor
2075 TupleField (std::unique_ptr<Type> field_type, Visibility vis, Location locus,
2076 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
2077 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
2078 field_type (std::move (field_type)),
2079 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
2080 {}
2081
2082 // Copy constructor with clone
2083 TupleField (TupleField const &other)
2084 : outer_attrs (other.outer_attrs), visibility (other.visibility),
2085 node_id (other.node_id), locus (other.locus)
2086 {
2087 // guard to prevent null dereference (only required if error)
2088 if (other.field_type != nullptr)
2089 field_type = other.field_type->clone_type ();
2090 }
2091
2092 ~TupleField () = default;
2093
2094 // Overloaded assignment operator to clone
2095 TupleField &operator= (TupleField const &other)
2096 {
2097 visibility = other.visibility;
2098 outer_attrs = other.outer_attrs;
2099 node_id = other.node_id;
2100 locus = other.locus;
2101
2102 // guard to prevent null dereference (only required if error)
2103 if (other.field_type != nullptr)
2104 field_type = other.field_type->clone_type ();
2105 else
2106 field_type = nullptr;
2107
2108 return *this;
2109 }
2110
2111 // move constructors
2112 TupleField (TupleField &&other) = default;
2113 TupleField &operator= (TupleField &&other) = default;
2114
2115 // Returns whether tuple field is in an error state.
2116 bool is_error () const { return field_type == nullptr; }
2117
2118 // Creates an error state tuple field.
2119 static TupleField create_error ()
2120 {
2121 return TupleField (nullptr, Visibility::create_error (), Location ());
2122 }
2123
2124 std::string as_string () const;
2125
2126 NodeId get_node_id () const { return node_id; }
2127
907d1119 2128 Visibility &get_visibility () { return visibility; }
438ae944
JP
2129 const Visibility &get_visibility () const { return visibility; }
2130
2131 Location get_locus () const { return locus; }
2132
2133 // TODO: this mutable getter seems really dodgy. Think up better way.
2134 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2135 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2136
2137 // TODO: is this better? Or is a "vis_block" better?
2138 std::unique_ptr<Type> &get_field_type ()
2139 {
2140 rust_assert (field_type != nullptr);
2141 return field_type;
2142 }
2143};
2144
2145// Rust tuple declared using struct keyword AST node
2146class TupleStruct : public Struct
2147{
2148 std::vector<TupleField> fields;
2149
2150public:
2151 std::string as_string () const override;
2152
2153 // Mega-constructor with all possible fields
2154 TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
2155 std::vector<std::unique_ptr<GenericParam>> generic_params,
2156 WhereClause where_clause, Visibility vis,
2157 std::vector<Attribute> outer_attrs, Location locus)
2158 : Struct (std::move (struct_name), std::move (generic_params),
2159 std::move (where_clause), std::move (vis), locus,
2160 std::move (outer_attrs)),
2161 fields (std::move (fields))
2162 {}
2163
2164 void accept_vis (ASTVisitor &vis) override;
2165
2166 // TODO: this mutable getter seems really dodgy. Think up better way.
2167 std::vector<TupleField> &get_fields () { return fields; }
2168 const std::vector<TupleField> &get_fields () const { return fields; }
2169
2170protected:
2171 /* Use covariance to implement clone function as returning this object
2172 * rather than base */
2173 TupleStruct *clone_item_impl () const override
2174 {
2175 return new TupleStruct (*this);
2176 }
2177};
2178
2179/* An item used in an "enum" tagged union - not abstract: base represents a
2180 * name-only enum. EnumItems (variants) syntactically allow a Visibility
2181 * annotation. */
2182class EnumItem : public VisItem
2183{
2184 Identifier variant_name;
2185
2186 Location locus;
2187
2188public:
2189 virtual ~EnumItem () {}
2190
2191 EnumItem (Identifier variant_name, Visibility vis,
2192 std::vector<Attribute> outer_attrs, Location locus)
2193 : VisItem (std::move (vis), std::move (outer_attrs)),
2194 variant_name (std::move (variant_name)), locus (locus)
2195 {}
2196
2197 // Unique pointer custom clone function
2198 std::unique_ptr<EnumItem> clone_enum_item () const
2199 {
2200 return std::unique_ptr<EnumItem> (clone_item_impl ());
2201 }
2202
2203 virtual std::string as_string () const;
2204
2205 // not pure virtual as not abstract
2206 virtual void accept_vis (ASTVisitor &vis);
2207
2208 Location get_locus () const { return locus; }
2209
2210 Identifier get_identifier () const { return variant_name; }
2211
2212 // Based on idea that name is never empty.
2213 void mark_for_strip () { variant_name = ""; }
2214 bool is_marked_for_strip () const { return variant_name.empty (); }
2215
2216protected:
2217 EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
2218};
2219
2220// A tuple item used in an "enum" tagged union
2221class EnumItemTuple : public EnumItem
2222{
2223 // bool has_tuple_fields;
2224 std::vector<TupleField> tuple_fields;
2225
2226public:
2227 // Returns whether tuple enum item has tuple fields.
2228 bool has_tuple_fields () const { return !tuple_fields.empty (); }
2229
2230 EnumItemTuple (Identifier variant_name, Visibility vis,
2231 std::vector<TupleField> tuple_fields,
2232 std::vector<Attribute> outer_attrs, Location locus)
2233 : EnumItem (std::move (variant_name), std::move (vis),
2234 std::move (outer_attrs), locus),
2235 tuple_fields (std::move (tuple_fields))
2236 {}
2237
2238 std::string as_string () const override;
2239
2240 void accept_vis (ASTVisitor &vis) override;
2241
2242 // TODO: this mutable getter seems really dodgy. Think up better way.
2243 std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
2244 const std::vector<TupleField> &get_tuple_fields () const
2245 {
2246 return tuple_fields;
2247 }
2248
2249protected:
2250 // Clone function implementation as (not pure) virtual method
2251 EnumItemTuple *clone_item_impl () const override
2252 {
2253 return new EnumItemTuple (*this);
2254 }
2255};
2256
2257// A struct item used in an "enum" tagged union
2258class EnumItemStruct : public EnumItem
2259{
2260 // bool has_struct_fields;
2261 std::vector<StructField> struct_fields;
2262
2263public:
2264 // Returns whether struct enum item has struct fields.
2265 bool has_struct_fields () const { return !struct_fields.empty (); }
2266
2267 EnumItemStruct (Identifier variant_name, Visibility vis,
2268 std::vector<StructField> struct_fields,
2269 std::vector<Attribute> outer_attrs, Location locus)
2270 : EnumItem (std::move (variant_name), std::move (vis),
2271 std::move (outer_attrs), locus),
2272 struct_fields (std::move (struct_fields))
2273 {}
2274
2275 std::string as_string () const override;
2276
2277 void accept_vis (ASTVisitor &vis) override;
2278
2279 // TODO: this mutable getter seems really dodgy. Think up better way.
2280 std::vector<StructField> &get_struct_fields () { return struct_fields; }
2281 const std::vector<StructField> &get_struct_fields () const
2282 {
2283 return struct_fields;
2284 }
2285
2286protected:
2287 // Clone function implementation as (not pure) virtual method
2288 EnumItemStruct *clone_item_impl () const override
2289 {
2290 return new EnumItemStruct (*this);
2291 }
2292};
2293
2294// A discriminant (numbered enum) item used in an "enum" tagged union
2295class EnumItemDiscriminant : public EnumItem
2296{
2297 std::unique_ptr<Expr> expression;
2298
2299public:
2300 EnumItemDiscriminant (Identifier variant_name, Visibility vis,
2301 std::unique_ptr<Expr> expr,
2302 std::vector<Attribute> outer_attrs, Location locus)
2303 : EnumItem (std::move (variant_name), std::move (vis),
2304 std::move (outer_attrs), locus),
2305 expression (std::move (expr))
2306 {}
2307
2308 // Copy constructor with clone
2309 EnumItemDiscriminant (EnumItemDiscriminant const &other)
2310 : EnumItem (other), expression (other.expression->clone_expr ())
2311 {}
2312
2313 // Overloaded assignment operator to clone
2314 EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other)
2315 {
2316 EnumItem::operator= (other);
2317 expression = other.expression->clone_expr ();
2318 // variant_name = other.variant_name;
2319 // outer_attrs = other.outer_attrs;
2320
2321 return *this;
2322 }
2323
2324 // move constructors
2325 EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
2326 EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
2327
2328 std::string as_string () const override;
2329
2330 void accept_vis (ASTVisitor &vis) override;
2331
2332 // TODO: is this better? Or is a "vis_block" better?
2333 std::unique_ptr<Expr> &get_expr ()
2334 {
2335 rust_assert (expression != nullptr);
2336 return expression;
2337 }
2338
2339protected:
2340 // Clone function implementation as (not pure) virtual method
2341 EnumItemDiscriminant *clone_item_impl () const override
2342 {
2343 return new EnumItemDiscriminant (*this);
2344 }
2345};
2346
2347// AST node for Rust "enum" - tagged union
2348class Enum : public VisItem
2349{
2350 Identifier enum_name;
2351
2352 // bool has_generics;
2353 // Generics generic_params;
2354 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2355
2356 // bool has_where_clause;
2357 WhereClause where_clause;
2358
2359 std::vector<std::unique_ptr<EnumItem>> items;
2360
2361 Location locus;
2362
2363public:
2364 std::string as_string () const override;
2365
2366 // Returns whether "enum" has generic parameters.
2367 bool has_generics () const { return !generic_params.empty (); }
2368
2369 // Returns whether "enum" has a where clause.
2370 bool has_where_clause () const { return !where_clause.is_empty (); }
2371
2372 /* Returns whether enum is a "zero-variant" (no possible variant) enum,
2373 * which cannot be instantiated. */
2374 bool is_zero_variant () const { return items.empty (); }
2375
2376 // Mega-constructor
2377 Enum (Identifier enum_name, Visibility vis,
2378 std::vector<std::unique_ptr<GenericParam>> generic_params,
2379 WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
2380 std::vector<Attribute> outer_attrs, Location locus)
2381 : VisItem (std::move (vis), std::move (outer_attrs)),
2382 enum_name (std::move (enum_name)),
2383 generic_params (std::move (generic_params)),
2384 where_clause (std::move (where_clause)), items (std::move (items)),
2385 locus (locus)
2386 {}
2387
2388 // TODO: constructor with less arguments
2389
2390 // Copy constructor with vector clone
2391 Enum (Enum const &other)
2392 : VisItem (other), enum_name (other.enum_name),
2393 where_clause (other.where_clause), locus (other.locus)
2394 {
2395 generic_params.reserve (other.generic_params.size ());
2396 for (const auto &e : other.generic_params)
2397 generic_params.push_back (e->clone_generic_param ());
2398
2399 items.reserve (other.items.size ());
2400 for (const auto &e : other.items)
2401 items.push_back (e->clone_enum_item ());
2402 }
2403
2404 // Overloaded assignment operator with vector clone
2405 Enum &operator= (Enum const &other)
2406 {
2407 VisItem::operator= (other);
2408 enum_name = other.enum_name;
2409 where_clause = other.where_clause;
2410 locus = other.locus;
2411
2412 generic_params.reserve (other.generic_params.size ());
2413 for (const auto &e : other.generic_params)
2414 generic_params.push_back (e->clone_generic_param ());
2415
2416 items.reserve (other.items.size ());
2417 for (const auto &e : other.items)
2418 items.push_back (e->clone_enum_item ());
2419
2420 return *this;
2421 }
2422
2423 // Move constructors
2424 Enum (Enum &&other) = default;
2425 Enum &operator= (Enum &&other) = default;
2426
2427 Location get_locus () const override final { return locus; }
2428
2429 void accept_vis (ASTVisitor &vis) override;
2430
2431 Identifier get_identifier () const { return enum_name; }
2432
2433 // Invalid if name is empty, so base stripping on that.
2434 void mark_for_strip () override { enum_name = ""; }
2435 bool is_marked_for_strip () const override { return enum_name.empty (); }
2436
2437 // TODO: this mutable getter seems really dodgy. Think up better way.
2438 std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
2439 const std::vector<std::unique_ptr<EnumItem>> &get_variants () const
2440 {
2441 return items;
2442 }
2443
2444 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2445 {
2446 return generic_params;
2447 }
2448 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2449 {
2450 return generic_params;
2451 }
2452
2453 // TODO: is this better? Or is a "vis_block" better?
2454 WhereClause &get_where_clause () { return where_clause; }
2455
2456protected:
2457 /* Use covariance to implement clone function as returning this object
2458 * rather than base */
2459 Enum *clone_item_impl () const override { return new Enum (*this); }
2460};
2461
2462// Rust untagged union used for C compat AST node
2463class Union : public VisItem
2464{
2465 Identifier union_name;
2466
2467 // bool has_generics;
2468 // Generics generic_params;
2469 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2470
2471 // bool has_where_clause;
2472 WhereClause where_clause;
2473
2474 std::vector<StructField> variants;
2475
2476 Location locus;
2477
2478public:
2479 std::string as_string () const override;
2480
2481 // Returns whether union has generic params.
2482 bool has_generics () const { return !generic_params.empty (); }
2483
2484 // Returns whether union has where clause.
2485 bool has_where_clause () const { return !where_clause.is_empty (); }
2486
2487 Union (Identifier union_name, Visibility vis,
2488 std::vector<std::unique_ptr<GenericParam>> generic_params,
2489 WhereClause where_clause, std::vector<StructField> variants,
2490 std::vector<Attribute> outer_attrs, Location locus)
2491 : VisItem (std::move (vis), std::move (outer_attrs)),
2492 union_name (std::move (union_name)),
2493 generic_params (std::move (generic_params)),
2494 where_clause (std::move (where_clause)), variants (std::move (variants)),
2495 locus (locus)
2496 {}
2497
2498 // copy constructor with vector clone
2499 Union (Union const &other)
2500 : VisItem (other), union_name (other.union_name),
2501 where_clause (other.where_clause), variants (other.variants),
2502 locus (other.locus)
2503 {
2504 generic_params.reserve (other.generic_params.size ());
2505 for (const auto &e : other.generic_params)
2506 generic_params.push_back (e->clone_generic_param ());
2507 }
2508
2509 // overloaded assignment operator with vector clone
2510 Union &operator= (Union const &other)
2511 {
2512 VisItem::operator= (other);
2513 union_name = other.union_name;
2514 where_clause = other.where_clause;
2515 variants = other.variants;
2516 locus = other.locus;
2517
2518 generic_params.reserve (other.generic_params.size ());
2519 for (const auto &e : other.generic_params)
2520 generic_params.push_back (e->clone_generic_param ());
2521
2522 return *this;
2523 }
2524
2525 // move constructors
2526 Union (Union &&other) = default;
2527 Union &operator= (Union &&other) = default;
2528
2529 Location get_locus () const override final { return locus; }
2530
2531 void accept_vis (ASTVisitor &vis) override;
2532
2533 // Invalid if name is empty, so base stripping on that.
2534 void mark_for_strip () override { union_name = ""; }
2535 bool is_marked_for_strip () const override { return union_name.empty (); }
2536
2537 // TODO: this mutable getter seems really dodgy. Think up better way.
2538 std::vector<StructField> &get_variants () { return variants; }
2539 const std::vector<StructField> &get_variants () const { return variants; }
2540
2541 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2542 {
2543 return generic_params;
2544 }
2545 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2546 {
2547 return generic_params;
2548 }
2549
2550 // TODO: is this better? Or is a "vis_block" better?
2551 WhereClause &get_where_clause () { return where_clause; }
2552
2553 Identifier get_identifier () const { return union_name; }
2554
2555protected:
2556 /* Use covariance to implement clone function as returning this object
2557 * rather than base */
2558 Union *clone_item_impl () const override { return new Union (*this); }
2559};
2560
2561/* "Constant item" AST node - used for constant, compile-time expressions
2562 * within module scope (like constexpr) */
2563class ConstantItem : public VisItem,
2564 public InherentImplItem,
2565 public TraitImplItem
2566{
2567 // either has an identifier or "_" - maybe handle in identifier?
2568 // bool identifier_is_underscore;
2569 // if no identifier declared, identifier will be "_"
2570 std::string identifier;
2571
2572 std::unique_ptr<Type> type;
2573 std::unique_ptr<Expr> const_expr;
2574
2575 Location locus;
2576
2577public:
2578 std::string as_string () const override;
2579
2580 ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
2581 std::unique_ptr<Expr> const_expr,
2582 std::vector<Attribute> outer_attrs, Location locus)
2583 : VisItem (std::move (vis), std::move (outer_attrs)),
2584 identifier (std::move (ident)), type (std::move (type)),
2585 const_expr (std::move (const_expr)), locus (locus)
2586 {}
2587
2588 ConstantItem (ConstantItem const &other)
2589 : VisItem (other), identifier (other.identifier), locus (other.locus)
2590 {
2591 // guard to prevent null dereference (only required if error state)
2592 if (other.type != nullptr)
2593 type = other.type->clone_type ();
2594 if (other.const_expr != nullptr)
2595 const_expr = other.const_expr->clone_expr ();
2596 }
2597
2598 // Overload assignment operator to clone
2599 ConstantItem &operator= (ConstantItem const &other)
2600 {
2601 VisItem::operator= (other);
2602 identifier = other.identifier;
2603 locus = other.locus;
2604
2605 // guard to prevent null dereference (only required if error state)
2606 if (other.type != nullptr)
2607 type = other.type->clone_type ();
2608 else
2609 type = nullptr;
2610 if (other.const_expr != nullptr)
2611 const_expr = other.const_expr->clone_expr ();
2612 else
2613 const_expr = nullptr;
2614
2615 return *this;
2616 }
2617
2618 // move constructors
2619 ConstantItem (ConstantItem &&other) = default;
2620 ConstantItem &operator= (ConstantItem &&other) = default;
2621
2622 /* Returns whether constant item is an "unnamed" (wildcard underscore used
2623 * as identifier) constant. */
2624 bool is_unnamed () const { return identifier == "_"; }
2625
2626 Location get_locus () const override final { return locus; }
2627
2628 void accept_vis (ASTVisitor &vis) override;
2629
2630 // Invalid if type or expression are null, so base stripping on that.
2631 void mark_for_strip () override
2632 {
2633 type = nullptr;
2634 const_expr = nullptr;
2635 }
2636 bool is_marked_for_strip () const override
2637 {
2638 return type == nullptr && const_expr == nullptr;
2639 }
2640
2641 // TODO: is this better? Or is a "vis_block" better?
2642 std::unique_ptr<Expr> &get_expr ()
2643 {
2644 rust_assert (const_expr != nullptr);
2645 return const_expr;
2646 }
2647
2648 // TODO: is this better? Or is a "vis_block" better?
2649 std::unique_ptr<Type> &get_type ()
2650 {
2651 rust_assert (type != nullptr);
2652 return type;
2653 }
2654
2655 std::string get_identifier () const { return identifier; }
2656
2657protected:
2658 /* Use covariance to implement clone function as returning this object
2659 * rather than base */
2660 ConstantItem *clone_item_impl () const override
2661 {
2662 return new ConstantItem (*this);
2663 }
2664
2665 /* Use covariance to implement clone function as returning this object
2666 * rather than base */
2667 ConstantItem *clone_inherent_impl_item_impl () const override
2668 {
2669 return new ConstantItem (*this);
2670 }
2671
2672 /* Use covariance to implement clone function as returning this object
2673 * rather than base */
2674 ConstantItem *clone_trait_impl_item_impl () const override
2675 {
2676 return new ConstantItem (*this);
2677 }
2678};
2679
2680/* Static item AST node - items within module scope with fixed storage
2681 * duration? */
2682class StaticItem : public VisItem
2683{
2684 bool has_mut;
2685 Identifier name;
2686 std::unique_ptr<Type> type;
2687 std::unique_ptr<Expr> expr;
2688 Location locus;
2689
2690public:
2691 std::string as_string () const override;
2692
2693 StaticItem (Identifier name, bool is_mut, std::unique_ptr<Type> type,
2694 std::unique_ptr<Expr> expr, Visibility vis,
2695 std::vector<Attribute> outer_attrs, Location locus)
2696 : VisItem (std::move (vis), std::move (outer_attrs)), has_mut (is_mut),
2697 name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
2698 locus (locus)
2699 {}
2700
2701 // Copy constructor with clone
2702 StaticItem (StaticItem const &other)
2703 : VisItem (other), has_mut (other.has_mut), name (other.name),
2704 locus (other.locus)
2705 {
2706 // guard to prevent null dereference (only required if error state)
2707 if (other.type != nullptr)
2708 type = other.type->clone_type ();
2709 if (other.expr != nullptr)
2710 expr = other.expr->clone_expr ();
2711 }
2712
2713 // Overloaded assignment operator to clone
2714 StaticItem &operator= (StaticItem const &other)
2715 {
2716 VisItem::operator= (other);
2717 name = other.name;
2718 has_mut = other.has_mut;
2719 locus = other.locus;
2720
2721 // guard to prevent null dereference (only required if error state)
2722 if (other.type != nullptr)
2723 type = other.type->clone_type ();
2724 else
2725 type = nullptr;
2726 if (other.expr != nullptr)
2727 expr = other.expr->clone_expr ();
2728 else
2729 expr = nullptr;
2730
2731 return *this;
2732 }
2733
2734 // move constructors
2735 StaticItem (StaticItem &&other) = default;
2736 StaticItem &operator= (StaticItem &&other) = default;
2737
2738 Location get_locus () const override final { return locus; }
2739
2740 void accept_vis (ASTVisitor &vis) override;
2741
2742 // Invalid if type or expression are null, so base stripping on that.
2743 void mark_for_strip () override
2744 {
2745 type = nullptr;
2746 expr = nullptr;
2747 }
2748 bool is_marked_for_strip () const override
2749 {
2750 return type == nullptr && expr == nullptr;
2751 }
2752
2753 // TODO: is this better? Or is a "vis_block" better?
2754 std::unique_ptr<Expr> &get_expr ()
2755 {
2756 rust_assert (expr != nullptr);
2757 return expr;
2758 }
2759
2760 // TODO: is this better? Or is a "vis_block" better?
2761 std::unique_ptr<Type> &get_type ()
2762 {
2763 rust_assert (type != nullptr);
2764 return type;
2765 }
2766
2767 bool is_mutable () const { return has_mut; }
2768
2769 Identifier get_identifier () const { return name; }
2770
2771protected:
2772 /* Use covariance to implement clone function as returning this object
2773 * rather than base */
2774 StaticItem *clone_item_impl () const override
2775 {
2776 return new StaticItem (*this);
2777 }
2778};
2779
2780// Function declaration in traits
2781struct TraitFunctionDecl
2782{
2783private:
2784 // TODO: delete and replace with Function decl item? no as no body in this.
2785 FunctionQualifiers qualifiers;
2786 Identifier function_name;
2787
2788 // bool has_generics;
2789 // Generics generic_params;
2790 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
2791
2792 // bool has_params;
2793 // FunctionParams function_params;
2794 std::vector<FunctionParam> function_params; // inlined
2795
2796 // bool has_return_type;
2797 std::unique_ptr<Type> return_type;
2798
2799 // bool has_where_clause;
2800 WhereClause where_clause;
2801
2802 // should this store location info?
2803
2804public:
2805 // Returns whether function decl has generic parameters.
2806 bool has_generics () const { return !generic_params.empty (); }
2807
2808 // Returns whether function decl has regular parameters.
2809 bool has_params () const { return !function_params.empty (); }
2810
2811 // Returns whether function has return type (otherwise is void).
2812 bool has_return_type () const { return return_type != nullptr; }
2813
2814 // Returns whether function has a where clause.
2815 bool has_where_clause () const { return !where_clause.is_empty (); }
2816
2817 Identifier get_identifier () const { return function_name; }
2818
2819 // Mega-constructor
2820 TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
2821 std::vector<std::unique_ptr<GenericParam>> generic_params,
2822 std::vector<FunctionParam> function_params,
2823 std::unique_ptr<Type> return_type,
2824 WhereClause where_clause)
2825 : qualifiers (std::move (qualifiers)),
2826 function_name (std::move (function_name)),
2827 generic_params (std::move (generic_params)),
2828 function_params (std::move (function_params)),
2829 return_type (std::move (return_type)),
2830 where_clause (std::move (where_clause))
2831 {}
2832
2833 // Copy constructor with clone
2834 TraitFunctionDecl (TraitFunctionDecl const &other)
2835 : qualifiers (other.qualifiers), function_name (other.function_name),
2836 function_params (other.function_params), where_clause (other.where_clause)
2837 {
2838 // guard to prevent nullptr dereference
2839 if (other.return_type != nullptr)
2840 return_type = other.return_type->clone_type ();
2841
2842 generic_params.reserve (other.generic_params.size ());
2843 for (const auto &e : other.generic_params)
2844 generic_params.push_back (e->clone_generic_param ());
2845 }
2846
2847 ~TraitFunctionDecl () = default;
2848
2849 // Overloaded assignment operator with clone
2850 TraitFunctionDecl &operator= (TraitFunctionDecl const &other)
2851 {
2852 function_name = other.function_name;
2853 qualifiers = other.qualifiers;
2854 function_params = other.function_params;
2855 where_clause = other.where_clause;
2856
2857 // guard to prevent nullptr dereference
2858 if (other.return_type != nullptr)
2859 return_type = other.return_type->clone_type ();
2860 else
2861 return_type = nullptr;
2862
2863 generic_params.reserve (other.generic_params.size ());
2864 for (const auto &e : other.generic_params)
2865 generic_params.push_back (e->clone_generic_param ());
2866
2867 return *this;
2868 }
2869
2870 // move constructors
2871 TraitFunctionDecl (TraitFunctionDecl &&other) = default;
2872 TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default;
2873
2874 std::string as_string () const;
2875
2876 // Invalid if function name is empty, so base stripping on that.
2877 void mark_for_strip () { function_name = ""; }
2878 bool is_marked_for_strip () const { return function_name.empty (); }
2879
2880 // TODO: this mutable getter seems really dodgy. Think up better way.
2881 std::vector<FunctionParam> &get_function_params () { return function_params; }
2882 const std::vector<FunctionParam> &get_function_params () const
2883 {
2884 return function_params;
2885 }
2886
2887 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
2888 {
2889 return generic_params;
2890 }
2891 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
2892 {
2893 return generic_params;
2894 }
2895
2896 // TODO: is this better? Or is a "vis_block" better?
2897 std::unique_ptr<Type> &get_return_type () { return return_type; }
2898
2899 // TODO: is this better? Or is a "vis_block" better?
2900 WhereClause &get_where_clause () { return where_clause; }
2901
2902 FunctionQualifiers get_qualifiers () { return qualifiers; }
2903};
2904
2905// Actual trait item function declaration within traits
2906class TraitItemFunc : public TraitItem
2907{
2908 std::vector<Attribute> outer_attrs;
2909 TraitFunctionDecl decl;
2910 std::unique_ptr<BlockExpr> block_expr;
438ae944
JP
2911
2912public:
2913 // Returns whether function has a definition or is just a declaration.
2914 bool has_definition () const { return block_expr != nullptr; }
2915
2916 TraitItemFunc (TraitFunctionDecl decl, std::unique_ptr<BlockExpr> block_expr,
2917 std::vector<Attribute> outer_attrs, Location locus)
fa7675df
AC
2918 : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
2919 decl (std::move (decl)), block_expr (std::move (block_expr))
438ae944
JP
2920 {}
2921
2922 // Copy constructor with clone
2923 TraitItemFunc (TraitItemFunc const &other)
fa7675df
AC
2924 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
2925 decl (other.decl)
438ae944
JP
2926 {
2927 node_id = other.node_id;
2928
2929 // guard to prevent null dereference
2930 if (other.block_expr != nullptr)
2931 block_expr = other.block_expr->clone_block_expr ();
2932 }
2933
2934 // Overloaded assignment operator to clone
2935 TraitItemFunc &operator= (TraitItemFunc const &other)
2936 {
2937 TraitItem::operator= (other);
2938 outer_attrs = other.outer_attrs;
2939 decl = other.decl;
2940 locus = other.locus;
2941 node_id = other.node_id;
2942
2943 // guard to prevent null dereference
2944 if (other.block_expr != nullptr)
2945 block_expr = other.block_expr->clone_block_expr ();
2946 else
2947 block_expr = nullptr;
2948
2949 return *this;
2950 }
2951
2952 // move constructors
2953 TraitItemFunc (TraitItemFunc &&other) = default;
2954 TraitItemFunc &operator= (TraitItemFunc &&other) = default;
2955
2956 std::string as_string () const override;
2957
438ae944
JP
2958 void accept_vis (ASTVisitor &vis) override;
2959
2960 // Invalid if trait decl is empty, so base stripping on that.
2961 void mark_for_strip () override { decl.mark_for_strip (); }
2962 bool is_marked_for_strip () const override
2963 {
2964 return decl.is_marked_for_strip ();
2965 }
2966
2967 // TODO: this mutable getter seems really dodgy. Think up better way.
2968 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
2969 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
2970
2971 // TODO: is this better? Or is a "vis_block" better?
2972 std::unique_ptr<BlockExpr> &get_definition () { return block_expr; }
2973
2974 // TODO: is this better? Or is a "vis_block" better?
2975 TraitFunctionDecl &get_trait_function_decl ()
2976 {
2977 // TODO: maybe only allow access if not marked for strip?
2978 return decl;
2979 }
2980
2981protected:
2982 // Clone function implementation as (not pure) virtual method
2983 TraitItemFunc *clone_trait_item_impl () const override
2984 {
2985 return new TraitItemFunc (*this);
2986 }
2987};
2988
2989// Method declaration within traits
2990struct TraitMethodDecl
2991{
2992private:
2993 // TODO: delete and replace with Function decl item? no as no body.
2994 FunctionQualifiers qualifiers;
2995 Identifier function_name;
2996
2997 // bool has_generics;
2998 // Generics generic_params;
2999 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3000
3001 SelfParam self_param;
3002
3003 // bool has_params;
3004 // FunctionParams function_params;
3005 std::vector<FunctionParam> function_params; // inlined
3006
3007 // bool has_return_type;
3008 std::unique_ptr<Type> return_type;
3009
3010 // bool has_where_clause;
3011 WhereClause where_clause;
3012
3013 // should this store location info?
3014
3015public:
3016 // Returns whether method decl has generic parameters.
3017 bool has_generics () const { return !generic_params.empty (); }
3018
3019 // Returns whether method decl has regular parameters.
3020 bool has_params () const { return !function_params.empty (); }
3021
3022 // Returns whether method has return type (otherwise is void).
3023 bool has_return_type () const { return return_type != nullptr; }
3024
3025 // Returns whether method has a where clause.
3026 bool has_where_clause () const { return !where_clause.is_empty (); }
3027
3028 Identifier get_identifier () const { return function_name; }
3029
3030 // Mega-constructor
3031 TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers,
3032 std::vector<std::unique_ptr<GenericParam>> generic_params,
3033 SelfParam self_param,
3034 std::vector<FunctionParam> function_params,
3035 std::unique_ptr<Type> return_type, WhereClause where_clause)
3036 : qualifiers (std::move (qualifiers)),
3037 function_name (std::move (function_name)),
3038 generic_params (std::move (generic_params)),
3039 self_param (std::move (self_param)),
3040 function_params (std::move (function_params)),
3041 return_type (std::move (return_type)),
3042 where_clause (std::move (where_clause))
3043 {}
3044
3045 // Copy constructor with clone
3046 TraitMethodDecl (TraitMethodDecl const &other)
3047 : qualifiers (other.qualifiers), function_name (other.function_name),
3048 self_param (other.self_param), function_params (other.function_params),
3049 where_clause (other.where_clause)
3050 {
3051 // guard to prevent nullptr dereference
3052 if (other.return_type != nullptr)
3053 return_type = other.return_type->clone_type ();
3054
3055 generic_params.reserve (other.generic_params.size ());
3056 for (const auto &e : other.generic_params)
3057 generic_params.push_back (e->clone_generic_param ());
3058 }
3059
3060 ~TraitMethodDecl () = default;
3061
3062 // Overloaded assignment operator with clone
3063 TraitMethodDecl &operator= (TraitMethodDecl const &other)
3064 {
3065 function_name = other.function_name;
3066 qualifiers = other.qualifiers;
3067 self_param = other.self_param;
3068 function_params = other.function_params;
3069 where_clause = other.where_clause;
3070
3071 // guard to prevent nullptr dereference
3072 if (other.return_type != nullptr)
3073 return_type = other.return_type->clone_type ();
3074 else
3075 return_type = nullptr;
3076
3077 generic_params.reserve (other.generic_params.size ());
3078 for (const auto &e : other.generic_params)
3079 generic_params.push_back (e->clone_generic_param ());
3080
3081 return *this;
3082 }
3083
3084 // move constructors
3085 TraitMethodDecl (TraitMethodDecl &&other) = default;
3086 TraitMethodDecl &operator= (TraitMethodDecl &&other) = default;
3087
3088 std::string as_string () const;
3089
3090 // Invalid if method name is empty, so base stripping on that.
3091 void mark_for_strip () { function_name = ""; }
3092 bool is_marked_for_strip () const { return function_name.empty (); }
3093
3094 // TODO: this mutable getter seems really dodgy. Think up better way.
3095 std::vector<FunctionParam> &get_function_params () { return function_params; }
3096 const std::vector<FunctionParam> &get_function_params () const
3097 {
3098 return function_params;
3099 }
3100
3101 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3102 {
3103 return generic_params;
3104 }
3105 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3106 {
3107 return generic_params;
3108 }
3109
3110 // TODO: is this better? Or is a "vis_block" better?
3111 std::unique_ptr<Type> &get_return_type () { return return_type; }
3112
3113 // TODO: is this better? Or is a "vis_block" better?
3114 WhereClause &get_where_clause () { return where_clause; }
3115
3116 SelfParam &get_self_param () { return self_param; }
3117 const SelfParam &get_self_param () const { return self_param; }
3118
3119 FunctionQualifiers get_qualifiers () { return qualifiers; }
3120};
3121
3122// Actual trait item method declaration within traits
3123class TraitItemMethod : public TraitItem
3124{
3125 std::vector<Attribute> outer_attrs;
3126 TraitMethodDecl decl;
3127 std::unique_ptr<BlockExpr> block_expr;
438ae944
JP
3128
3129public:
3130 // Returns whether method has a definition or is just a declaration.
3131 bool has_definition () const { return block_expr != nullptr; }
3132
3133 TraitItemMethod (TraitMethodDecl decl, std::unique_ptr<BlockExpr> block_expr,
3134 std::vector<Attribute> outer_attrs, Location locus)
fa7675df
AC
3135 : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
3136 decl (std::move (decl)), block_expr (std::move (block_expr))
438ae944
JP
3137 {}
3138
3139 // Copy constructor with clone
3140 TraitItemMethod (TraitItemMethod const &other)
fa7675df
AC
3141 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
3142 decl (other.decl)
438ae944
JP
3143 {
3144 node_id = other.node_id;
3145
3146 // guard to prevent null dereference
3147 if (other.block_expr != nullptr)
3148 block_expr = other.block_expr->clone_block_expr ();
3149 }
3150
3151 // Overloaded assignment operator to clone
3152 TraitItemMethod &operator= (TraitItemMethod const &other)
3153 {
3154 TraitItem::operator= (other);
3155 outer_attrs = other.outer_attrs;
3156 decl = other.decl;
3157 locus = other.locus;
3158 node_id = other.node_id;
3159
3160 // guard to prevent null dereference
3161 if (other.block_expr != nullptr)
3162 block_expr = other.block_expr->clone_block_expr ();
3163 else
3164 block_expr = nullptr;
3165
3166 return *this;
3167 }
3168
3169 // move constructors
3170 TraitItemMethod (TraitItemMethod &&other) = default;
3171 TraitItemMethod &operator= (TraitItemMethod &&other) = default;
3172
3173 std::string as_string () const override;
3174
438ae944
JP
3175 void accept_vis (ASTVisitor &vis) override;
3176
3177 // Invalid if trait decl is empty, so base stripping on that.
3178 void mark_for_strip () override { decl.mark_for_strip (); }
3179 bool is_marked_for_strip () const override
3180 {
3181 return decl.is_marked_for_strip ();
3182 }
3183
3184 // TODO: this mutable getter seems really dodgy. Think up better way.
3185 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3186 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3187
3188 // TODO: is this better? Or is a "vis_block" better?
3189 TraitMethodDecl &get_trait_method_decl ()
3190 {
3191 // TODO: maybe only allow access if not marked for strip?
3192 return decl;
3193 }
3194
3195 // TODO: is this better? Or is a "vis_block" better?
3196 std::unique_ptr<BlockExpr> &get_definition () { return block_expr; }
3197
3198protected:
3199 // Clone function implementation as (not pure) virtual method
3200 TraitItemMethod *clone_trait_item_impl () const override
3201 {
3202 return new TraitItemMethod (*this);
3203 }
3204};
3205
3206// Constant item within traits
3207class TraitItemConst : public TraitItem
3208{
3209 std::vector<Attribute> outer_attrs;
3210 Identifier name;
3211 std::unique_ptr<Type> type;
3212
3213 // bool has_expression;
3214 std::unique_ptr<Expr> expr;
3215
438ae944
JP
3216public:
3217 // Whether the constant item has an associated expression.
3218 bool has_expression () const { return expr != nullptr; }
3219
3220 TraitItemConst (Identifier name, std::unique_ptr<Type> type,
3221 std::unique_ptr<Expr> expr,
3222 std::vector<Attribute> outer_attrs, Location locus)
fa7675df
AC
3223 : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
3224 name (std::move (name)), type (std::move (type)), expr (std::move (expr))
438ae944
JP
3225 {}
3226
3227 // Copy constructor with clones
3228 TraitItemConst (TraitItemConst const &other)
fa7675df
AC
3229 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
3230 name (other.name)
438ae944
JP
3231 {
3232 node_id = other.node_id;
3233
3234 // guard to prevent null dereference
3235 if (other.expr != nullptr)
3236 expr = other.expr->clone_expr ();
3237
3238 // guard to prevent null dereference (only for error state)
3239 if (other.type != nullptr)
3240 type = other.type->clone_type ();
3241 }
3242
3243 // Overloaded assignment operator to clone
3244 TraitItemConst &operator= (TraitItemConst const &other)
3245 {
3246 TraitItem::operator= (other);
3247 outer_attrs = other.outer_attrs;
3248 name = other.name;
3249 locus = other.locus;
3250 node_id = other.node_id;
3251
3252 // guard to prevent null dereference
3253 if (other.expr != nullptr)
3254 expr = other.expr->clone_expr ();
3255 else
3256 expr = nullptr;
3257
3258 // guard to prevent null dereference (only for error state)
3259 if (other.type != nullptr)
3260 type = other.type->clone_type ();
3261 else
3262 type = nullptr;
3263
3264 return *this;
3265 }
3266
3267 // move constructors
3268 TraitItemConst (TraitItemConst &&other) = default;
3269 TraitItemConst &operator= (TraitItemConst &&other) = default;
3270
3271 std::string as_string () const override;
3272
3273 Location get_locus () const { return locus; }
3274
3275 void accept_vis (ASTVisitor &vis) override;
3276
3277 // Invalid if type is null, so base stripping on that.
3278 void mark_for_strip () override { type = nullptr; }
3279 bool is_marked_for_strip () const override { return type == nullptr; }
3280
3281 // TODO: this mutable getter seems really dodgy. Think up better way.
3282 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3283 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3284
3285 bool has_expr () const { return expr != nullptr; }
3286
3287 // TODO: is this better? Or is a "vis_block" better?
3288 std::unique_ptr<Expr> &get_expr ()
3289 {
3290 rust_assert (has_expr ());
3291 return expr;
3292 }
3293
3294 // TODO: is this better? Or is a "vis_block" better?
3295 std::unique_ptr<Type> &get_type ()
3296 {
3297 rust_assert (type != nullptr);
3298 return type;
3299 }
3300
3301 Identifier get_identifier () const { return name; }
3302
3303protected:
3304 // Clone function implementation as (not pure) virtual method
3305 TraitItemConst *clone_trait_item_impl () const override
3306 {
3307 return new TraitItemConst (*this);
3308 }
3309};
3310
3311// Type items within traits
3312class TraitItemType : public TraitItem
3313{
3314 std::vector<Attribute> outer_attrs;
3315
3316 Identifier name;
3317
3318 // bool has_type_param_bounds;
3319 // TypeParamBounds type_param_bounds;
3320 std::vector<std::unique_ptr<TypeParamBound>>
3321 type_param_bounds; // inlined form
3322
438ae944
JP
3323public:
3324 // Returns whether trait item type has type param bounds.
3325 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
3326
3327 TraitItemType (Identifier name,
3328 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
3329 std::vector<Attribute> outer_attrs, Location locus)
fa7675df
AC
3330 : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
3331 name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
438ae944
JP
3332 {}
3333
3334 // Copy constructor with vector clone
3335 TraitItemType (TraitItemType const &other)
fa7675df
AC
3336 : TraitItem (other.locus), outer_attrs (other.outer_attrs),
3337 name (other.name)
438ae944
JP
3338 {
3339 node_id = other.node_id;
3340 type_param_bounds.reserve (other.type_param_bounds.size ());
3341 for (const auto &e : other.type_param_bounds)
3342 type_param_bounds.push_back (e->clone_type_param_bound ());
3343 }
3344
3345 // Overloaded assignment operator with vector clone
3346 TraitItemType &operator= (TraitItemType const &other)
3347 {
3348 TraitItem::operator= (other);
3349 outer_attrs = other.outer_attrs;
3350 name = other.name;
3351 locus = other.locus;
3352 node_id = other.node_id;
3353
3354 type_param_bounds.reserve (other.type_param_bounds.size ());
3355 for (const auto &e : other.type_param_bounds)
3356 type_param_bounds.push_back (e->clone_type_param_bound ());
3357
3358 return *this;
3359 }
3360
3361 // default move constructors
3362 TraitItemType (TraitItemType &&other) = default;
3363 TraitItemType &operator= (TraitItemType &&other) = default;
3364
3365 std::string as_string () const override;
3366
438ae944
JP
3367 void accept_vis (ASTVisitor &vis) override;
3368
3369 // Invalid if name is empty, so base stripping on that.
3370 void mark_for_strip () override { name = ""; }
3371 bool is_marked_for_strip () const override { return name.empty (); }
3372
3373 // TODO: this mutable getter seems really dodgy. Think up better way.
3374 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3375 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3376
3377 // TODO: mutable getter seems kinda dodgy
3378 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
3379 {
3380 return type_param_bounds;
3381 }
3382 const std::vector<std::unique_ptr<TypeParamBound>> &
3383 get_type_param_bounds () const
3384 {
3385 return type_param_bounds;
3386 }
3387
3388 Identifier get_identifier () const { return name; }
3389
3390protected:
3391 // Clone function implementation as (not pure) virtual method
3392 TraitItemType *clone_trait_item_impl () const override
3393 {
3394 return new TraitItemType (*this);
3395 }
3396};
3397
3398// Rust trait item declaration AST node
3399class Trait : public VisItem
3400{
3401 bool has_unsafe;
3402 Identifier name;
3403 std::vector<std::unique_ptr<GenericParam>> generic_params;
3404 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
3405 WhereClause where_clause;
3406 std::vector<Attribute> inner_attrs;
3407 std::vector<std::unique_ptr<TraitItem>> trait_items;
3408 Location locus;
3409
3410public:
3411 std::string as_string () const override;
3412
3413 // Returns whether trait has generic parameters.
3414 bool has_generics () const { return !generic_params.empty (); }
3415
3416 // Returns whether trait has type parameter bounds.
3417 bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
3418
3419 // Returns whether trait has where clause.
3420 bool has_where_clause () const { return !where_clause.is_empty (); }
3421
3422 // Returns whether trait has trait items.
3423 bool has_trait_items () const { return !trait_items.empty (); }
3424
3425 // Returns whether trait has inner attributes.
3426 bool has_inner_attrs () const { return !inner_attrs.empty (); }
3427
3428 Identifier get_identifier () const { return name; }
3429
3430 bool is_unsafe () const { return has_unsafe; }
3431
3432 // Mega-constructor
3433 Trait (Identifier name, bool is_unsafe,
3434 std::vector<std::unique_ptr<GenericParam>> generic_params,
3435 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
3436 WhereClause where_clause,
3437 std::vector<std::unique_ptr<TraitItem>> trait_items, Visibility vis,
3438 std::vector<Attribute> outer_attrs, std::vector<Attribute> inner_attrs,
3439 Location locus)
3440 : VisItem (std::move (vis), std::move (outer_attrs)),
3441 has_unsafe (is_unsafe), name (std::move (name)),
3442 generic_params (std::move (generic_params)),
3443 type_param_bounds (std::move (type_param_bounds)),
3444 where_clause (std::move (where_clause)),
3445 inner_attrs (std::move (inner_attrs)),
3446 trait_items (std::move (trait_items)), locus (locus)
3447 {}
3448
3449 // Copy constructor with vector clone
3450 Trait (Trait const &other)
3451 : VisItem (other), has_unsafe (other.has_unsafe), name (other.name),
3452 where_clause (other.where_clause), inner_attrs (other.inner_attrs),
3453 locus (other.locus)
3454 {
3455 generic_params.reserve (other.generic_params.size ());
3456 for (const auto &e : other.generic_params)
3457 generic_params.push_back (e->clone_generic_param ());
3458
3459 type_param_bounds.reserve (other.type_param_bounds.size ());
3460 for (const auto &e : other.type_param_bounds)
3461 type_param_bounds.push_back (e->clone_type_param_bound ());
3462
3463 trait_items.reserve (other.trait_items.size ());
3464 for (const auto &e : other.trait_items)
3465 trait_items.push_back (e->clone_trait_item ());
3466 }
3467
3468 // Overloaded assignment operator with vector clone
3469 Trait &operator= (Trait const &other)
3470 {
3471 VisItem::operator= (other);
3472 name = other.name;
3473 has_unsafe = other.has_unsafe;
3474 where_clause = other.where_clause;
3475 inner_attrs = other.inner_attrs;
3476 locus = other.locus;
3477
3478 generic_params.reserve (other.generic_params.size ());
3479 for (const auto &e : other.generic_params)
3480 generic_params.push_back (e->clone_generic_param ());
3481
3482 type_param_bounds.reserve (other.type_param_bounds.size ());
3483 for (const auto &e : other.type_param_bounds)
3484 type_param_bounds.push_back (e->clone_type_param_bound ());
3485
3486 trait_items.reserve (other.trait_items.size ());
3487 for (const auto &e : other.trait_items)
3488 trait_items.push_back (e->clone_trait_item ());
3489
3490 return *this;
3491 }
3492
3493 // default move constructors
3494 Trait (Trait &&other) = default;
3495 Trait &operator= (Trait &&other) = default;
3496
3497 Location get_locus () const override final { return locus; }
3498
3499 void accept_vis (ASTVisitor &vis) override;
3500
3501 // Invalid if trait name is empty, so base stripping on that.
3502 void mark_for_strip () override { name = ""; }
3503 bool is_marked_for_strip () const override { return name.empty (); }
3504
3505 // TODO: think of better way to do this
3506 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3507 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3508
3509 const std::vector<std::unique_ptr<TraitItem>> &get_trait_items () const
3510 {
3511 return trait_items;
3512 }
3513 std::vector<std::unique_ptr<TraitItem>> &get_trait_items ()
3514 {
3515 return trait_items;
3516 }
3517
3518 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3519 {
3520 return generic_params;
3521 }
3522 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3523 {
3524 return generic_params;
3525 }
3526
3527 std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
3528 {
3529 return type_param_bounds;
3530 }
3531 const std::vector<std::unique_ptr<TypeParamBound>> &
3532 get_type_param_bounds () const
3533 {
3534 return type_param_bounds;
3535 }
3536
3537 WhereClause &get_where_clause () { return where_clause; }
3538
3539 void insert_implict_self (std::unique_ptr<AST::GenericParam> &&param)
3540 {
3541 std::vector<std::unique_ptr<GenericParam>> new_list;
3542 new_list.reserve (generic_params.size () + 1);
3543
3544 new_list.push_back (std::move (param));
3545 for (auto &p : generic_params)
3546 {
3547 new_list.push_back (std::move (p));
3548 }
3549
3550 generic_params = std::move (new_list);
3551 }
3552
3553protected:
3554 /* Use covariance to implement clone function as returning this object
3555 * rather than base */
3556 Trait *clone_item_impl () const override { return new Trait (*this); }
3557};
3558
3559// Implementation item declaration AST node - abstract base class
3560class Impl : public VisItem
3561{
3562 // must be protected to allow subclasses to access them properly
3563protected:
3564 // bool has_generics;
3565 // Generics generic_params;
3566 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
3567
3568 std::unique_ptr<Type> trait_type;
3569
3570 // bool has_where_clause;
3571 WhereClause where_clause;
3572
3573 // bool has_inner_attrs;
3574 std::vector<Attribute> inner_attrs;
3575
3576private:
3577 // doesn't really need to be protected as write access probably not needed
3578 Location locus;
3579
3580public:
3581 // Returns whether impl has generic parameters.
3582 bool has_generics () const { return !generic_params.empty (); }
3583
3584 // Returns whether impl has where clause.
3585 bool has_where_clause () const { return !where_clause.is_empty (); }
3586
3587 // Returns whether impl has inner attributes.
3588 bool has_inner_attrs () const { return !inner_attrs.empty (); }
3589
3590 Location get_locus () const override final { return locus; }
3591
3592 // Invalid if trait type is null, so base stripping on that.
3593 void mark_for_strip () override { trait_type = nullptr; }
3594 bool is_marked_for_strip () const override { return trait_type == nullptr; }
3595
3596 // TODO: think of better way to do this
3597 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
3598 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
3599
3600 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
3601 {
3602 return generic_params;
3603 }
3604 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
3605 {
3606 return generic_params;
3607 }
3608
3609 // TODO: is this better? Or is a "vis_block" better?
3610 WhereClause &get_where_clause () { return where_clause; }
3611
3612 // TODO: is this better? Or is a "vis_block" better?
3613 std::unique_ptr<Type> &get_type ()
3614 {
3615 rust_assert (trait_type != nullptr);
3616 return trait_type;
3617 }
3618
3619protected:
3620 // Mega-constructor
3621 Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
3622 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3623 Visibility vis, std::vector<Attribute> inner_attrs,
3624 std::vector<Attribute> outer_attrs, Location locus)
3625 : VisItem (std::move (vis), std::move (outer_attrs)),
3626 generic_params (std::move (generic_params)),
3627 trait_type (std::move (trait_type)),
3628 where_clause (std::move (where_clause)),
3629 inner_attrs (std::move (inner_attrs)), locus (locus)
3630 {}
3631
3632 // Copy constructor
3633 Impl (Impl const &other)
3634 : VisItem (other), where_clause (other.where_clause),
3635 inner_attrs (other.inner_attrs), locus (other.locus)
3636 {
3637 // guard to prevent null dereference (only required if error state)
3638 if (other.trait_type != nullptr)
3639 trait_type = other.trait_type->clone_type ();
3640
3641 generic_params.reserve (other.generic_params.size ());
3642 for (const auto &e : other.generic_params)
3643 generic_params.push_back (e->clone_generic_param ());
3644 }
3645
3646 // Assignment operator overload with cloning
3647 Impl &operator= (Impl const &other)
3648 {
3649 VisItem::operator= (other);
3650 where_clause = other.where_clause;
3651 inner_attrs = other.inner_attrs;
3652 locus = other.locus;
3653
3654 // guard to prevent null dereference (only required if error state)
3655 if (other.trait_type != nullptr)
3656 trait_type = other.trait_type->clone_type ();
3657 else
3658 trait_type = nullptr;
3659
3660 generic_params.reserve (other.generic_params.size ());
3661 for (const auto &e : other.generic_params)
3662 generic_params.push_back (e->clone_generic_param ());
3663
3664 return *this;
3665 }
3666
3667 // move constructors
3668 Impl (Impl &&other) = default;
3669 Impl &operator= (Impl &&other) = default;
3670};
3671
3672// Regular "impl foo" impl block declaration AST node
3673class InherentImpl : public Impl
3674{
3675 // bool has_impl_items;
3676 std::vector<std::unique_ptr<InherentImplItem>> impl_items;
3677
3678public:
3679 std::string as_string () const override;
3680
3681 // Returns whether inherent impl block has inherent impl items.
3682 bool has_impl_items () const { return !impl_items.empty (); }
3683
3684 // Mega-constructor
3685 InherentImpl (std::vector<std::unique_ptr<InherentImplItem>> impl_items,
3686 std::vector<std::unique_ptr<GenericParam>> generic_params,
3687 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3688 Visibility vis, std::vector<Attribute> inner_attrs,
3689 std::vector<Attribute> outer_attrs, Location locus)
3690 : Impl (std::move (generic_params), std::move (trait_type),
3691 std::move (where_clause), std::move (vis), std::move (inner_attrs),
3692 std::move (outer_attrs), locus),
3693 impl_items (std::move (impl_items))
3694 {}
3695
3696 // Copy constructor with vector clone
3697 InherentImpl (InherentImpl const &other) : Impl (other)
3698 {
3699 impl_items.reserve (other.impl_items.size ());
3700 for (const auto &e : other.impl_items)
3701 impl_items.push_back (e->clone_inherent_impl_item ());
3702 }
3703
3704 // Overloaded assignment operator with vector clone
3705 InherentImpl &operator= (InherentImpl const &other)
3706 {
3707 Impl::operator= (other);
3708
3709 impl_items.reserve (other.impl_items.size ());
3710 for (const auto &e : other.impl_items)
3711 impl_items.push_back (e->clone_inherent_impl_item ());
3712
3713 return *this;
3714 }
3715
3716 // default move constructors
3717 InherentImpl (InherentImpl &&other) = default;
3718 InherentImpl &operator= (InherentImpl &&other) = default;
3719
3720 void accept_vis (ASTVisitor &vis) override;
3721
3722 // TODO: think of better way to do this
3723 const std::vector<std::unique_ptr<InherentImplItem>> &get_impl_items () const
3724 {
3725 return impl_items;
3726 }
3727 std::vector<std::unique_ptr<InherentImplItem>> &get_impl_items ()
3728 {
3729 return impl_items;
3730 }
3731
3732protected:
3733 /* Use covariance to implement clone function as returning this object
3734 * rather than base */
3735 InherentImpl *clone_item_impl () const override
3736 {
3737 return new InherentImpl (*this);
3738 }
3739};
3740
3741// The "impl footrait for foo" impl block declaration AST node
3742class TraitImpl : public Impl
3743{
3744 bool has_unsafe;
3745 bool has_exclam;
3746 TypePath trait_path;
3747
3748 // bool has_impl_items;
3749 std::vector<std::unique_ptr<TraitImplItem>> impl_items;
3750
3751public:
3752 std::string as_string () const override;
3753
3754 // Returns whether trait impl has impl items.
3755 bool has_impl_items () const { return !impl_items.empty (); }
3756
3757 // Mega-constructor
3758 TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
3759 std::vector<std::unique_ptr<TraitImplItem>> impl_items,
3760 std::vector<std::unique_ptr<GenericParam>> generic_params,
3761 std::unique_ptr<Type> trait_type, WhereClause where_clause,
3762 Visibility vis, std::vector<Attribute> inner_attrs,
3763 std::vector<Attribute> outer_attrs, Location locus)
3764 : Impl (std::move (generic_params), std::move (trait_type),
3765 std::move (where_clause), std::move (vis), std::move (inner_attrs),
3766 std::move (outer_attrs), locus),
3767 has_unsafe (is_unsafe), has_exclam (has_exclam),
3768 trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
3769 {}
3770
3771 // Copy constructor with vector clone
3772 TraitImpl (TraitImpl const &other)
3773 : Impl (other), has_unsafe (other.has_unsafe),
3774 has_exclam (other.has_exclam), trait_path (other.trait_path)
3775 {
3776 impl_items.reserve (other.impl_items.size ());
3777 for (const auto &e : other.impl_items)
3778 impl_items.push_back (e->clone_trait_impl_item ());
3779 }
3780
3781 // Overloaded assignment operator with vector clone
3782 TraitImpl &operator= (TraitImpl const &other)
3783 {
3784 Impl::operator= (other);
3785 trait_path = other.trait_path;
3786 has_unsafe = other.has_unsafe;
3787 has_exclam = other.has_exclam;
3788
3789 impl_items.reserve (other.impl_items.size ());
3790 for (const auto &e : other.impl_items)
3791 impl_items.push_back (e->clone_trait_impl_item ());
3792
3793 return *this;
3794 }
3795
3796 // move constructors
3797 TraitImpl (TraitImpl &&other) = default;
3798 TraitImpl &operator= (TraitImpl &&other) = default;
3799
3800 void accept_vis (ASTVisitor &vis) override;
3801
3802 bool is_unsafe () const { return has_unsafe; };
3803 bool is_exclam () const { return has_exclam; }
3804
3805 // TODO: think of better way to do this
3806 const std::vector<std::unique_ptr<TraitImplItem>> &get_impl_items () const
3807 {
3808 return impl_items;
3809 }
3810 std::vector<std::unique_ptr<TraitImplItem>> &get_impl_items ()
3811 {
3812 return impl_items;
3813 }
3814
3815 // TODO: is this better? Or is a "vis_block" better?
3816 TypePath &get_trait_path ()
3817 {
3818 // TODO: assert that trait path is not empty?
3819 return trait_path;
3820 }
3821
3822protected:
3823 /* Use covariance to implement clone function as returning this object
3824 * rather than base */
3825 TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
3826};
3827
3828#if 0
3829// Abstract base class for an item used inside an extern block
3830class ExternalItem
3831{
3832 // bool has_outer_attrs;
3833 std::vector<Attribute> outer_attrs;
3834
3835 // bool has_visibility;
3836 Visibility visibility;
3837
3838 Identifier item_name;
3839 Location locus;
3840
3841public:
3842 virtual ~ExternalItem () {}
3843
3844 /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
3845 * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
3846 * support would require a lot of refactoring. */
3847
3848 // Returns whether item has outer attributes.
3849 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3850
3851 // Returns whether item has non-default visibility.
3852 bool has_visibility () const { return !visibility.is_error (); }
3853
3854 // Unique pointer custom clone function
3855 std::unique_ptr<ExternalItem> clone_external_item () const
3856 {
3857 return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
3858 }
3859
3860 virtual std::string as_string () const;
3861
3862 Location get_locus () const override final { return locus; }
3863
3864 virtual void accept_vis (ASTVisitor &vis) = 0;
3865
3866 // TODO: make virtual? Would be more flexible.
3867 // Based on idea that name should never be empty.
3868 void mark_for_strip () { item_name = ""; };
3869 bool is_marked_for_strip () const { return item_name.empty (); };
3870
3871protected:
3872 ExternalItem (Identifier item_name, Visibility vis,
3873 std::vector<Attribute> outer_attrs, Location locus)
3874 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
3875 item_name (std::move (item_name)), locus (locus)
3876 {}
3877
3878 // Copy constructor
3879 ExternalItem (ExternalItem const &other)
3880 : outer_attrs (other.outer_attrs), visibility (other.visibility),
3881 item_name (other.item_name), locus (other.locus)
3882 {}
3883
3884 // Overloaded assignment operator to clone
3885 ExternalItem &operator= (ExternalItem const &other)
3886 {
3887 item_name = other.item_name;
3888 visibility = other.visibility;
3889 outer_attrs = other.outer_attrs;
3890 locus = other.locus;
3891
3892 return *this;
3893 }
3894
3895 // move constructors
3896 ExternalItem (ExternalItem &&other) = default;
3897 ExternalItem &operator= (ExternalItem &&other) = default;
3898
3899 // Clone function implementation as pure virtual method
3900 virtual ExternalItem *clone_external_item_impl () const = 0;
3901
3902 // possibly make this public if required
3903 std::string get_item_name () const { return item_name; }
3904};
3905#endif
3906
3907// A static item used in an extern block
3908class ExternalStaticItem : public ExternalItem
3909{
3910 // bool has_outer_attrs;
3911 std::vector<Attribute> outer_attrs;
3912
3913 // bool has_visibility;
3914 Visibility visibility;
3915
3916 Identifier item_name;
3917 Location locus;
3918
3919 bool has_mut;
3920 std::unique_ptr<Type> item_type;
3921
3922public:
3923 ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
3924 bool is_mut, Visibility vis,
3925 std::vector<Attribute> outer_attrs, Location locus)
3926 : ExternalItem (), outer_attrs (std::move (outer_attrs)),
3927 visibility (std::move (vis)), item_name (std::move (item_name)),
3928 locus (locus), has_mut (is_mut), item_type (std::move (item_type))
3929 {}
3930
3931 // Copy constructor
3932 ExternalStaticItem (ExternalStaticItem const &other)
3933 : outer_attrs (other.outer_attrs), visibility (other.visibility),
3934 item_name (other.item_name), locus (other.locus), has_mut (other.has_mut)
3935 {
3936 node_id = other.node_id;
3937 // guard to prevent null dereference (only required if error state)
3938 if (other.item_type != nullptr)
3939 item_type = other.item_type->clone_type ();
3940 }
3941
3942 // Overloaded assignment operator to clone
3943 ExternalStaticItem &operator= (ExternalStaticItem const &other)
3944 {
3945 node_id = other.node_id;
3946 outer_attrs = other.outer_attrs;
3947 visibility = other.visibility;
3948 item_name = other.item_name;
3949 locus = other.locus;
3950 has_mut = other.has_mut;
3951
3952 // guard to prevent null dereference (only required if error state)
3953 if (other.item_type != nullptr)
3954 item_type = other.item_type->clone_type ();
3955 else
3956 item_type = nullptr;
3957
3958 return *this;
3959 }
3960
3961 // move constructors
3962 ExternalStaticItem (ExternalStaticItem &&other) = default;
3963 ExternalStaticItem &operator= (ExternalStaticItem &&other) = default;
3964
3965 std::string as_string () const override;
3966
3967 void accept_vis (ASTVisitor &vis) override;
3968
3969 // Returns whether item has outer attributes.
3970 bool has_outer_attrs () const { return !outer_attrs.empty (); }
3971
3972 // Returns whether item has non-default visibility.
3973 bool has_visibility () const { return !visibility.is_error (); }
3974
3975 Location get_locus () const { return locus; }
3976
3977 // Based on idea that type should never be null.
3978 void mark_for_strip () override { item_type = nullptr; };
3979 bool is_marked_for_strip () const override { return item_type == nullptr; };
3980
3981 // TODO: this mutable getter seems really dodgy. Think up better way.
3982 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
3983 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
3984
3985 // TODO: is this better? Or is a "vis_block" better?
3986 std::unique_ptr<Type> &get_type ()
3987 {
3988 rust_assert (item_type != nullptr);
3989 return item_type;
3990 }
3991
3992 Identifier get_identifier () const { return item_name; }
3993
3994 const Visibility &get_visibility () const { return visibility; }
3995
3996 bool is_mut () const { return has_mut; }
3997
3998protected:
3999 /* Use covariance to implement clone function as returning this object
4000 * rather than base */
4001 ExternalStaticItem *clone_external_item_impl () const override
4002 {
4003 return new ExternalStaticItem (*this);
4004 }
4005};
4006
4007// A named function parameter used in external functions
4008struct NamedFunctionParam
4009{
4010private:
4011 // bool has_name; // otherwise is _
4012 std::string name;
4013
4014 std::unique_ptr<Type> param_type;
4015
4016 // seemingly new since writing this node
4017 std::vector<Attribute> outer_attrs;
4018
4019 NodeId node_id;
4020 Location locus;
4021
4022public:
4023 /* Returns whether the named function parameter has a name (i.e. name is not
4024 * '_'). */
4025 bool has_name () const { return name != "_"; }
4026
4027 bool has_outer_attrs () const { return !outer_attrs.empty (); }
4028
4029 // Returns whether the named function parameter is in an error state.
4030 bool is_error () const
4031 {
4032 // also if identifier is "" but that is probably more costly to compute
4033 return param_type == nullptr;
4034 }
4035
4036 std::string get_name () const { return name; }
4037
4038 // Creates an error state named function parameter.
4039 static NamedFunctionParam create_error ()
4040 {
4041 return NamedFunctionParam ("", nullptr, {}, Location ());
4042 }
4043
4044 NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
4045 std::vector<Attribute> outer_attrs, Location locus)
4046 : name (std::move (name)), param_type (std::move (param_type)),
4047 outer_attrs (std::move (outer_attrs)),
4048 node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
4049 {}
4050
4051 // Copy constructor
4052 NamedFunctionParam (NamedFunctionParam const &other)
4053 : name (other.name), outer_attrs (other.outer_attrs)
4054 {
4055 node_id = other.node_id;
4056 // guard to prevent null dereference (only required if error state)
4057 if (other.param_type != nullptr)
4058 param_type = other.param_type->clone_type ();
4059 }
4060
4061 ~NamedFunctionParam () = default;
4062
4063 // Overloaded assignment operator to clone
4064 NamedFunctionParam &operator= (NamedFunctionParam const &other)
4065 {
4066 node_id = other.node_id;
4067 name = other.name;
4068 // has_name = other.has_name;
4069 outer_attrs = other.outer_attrs;
4070
4071 // guard to prevent null dereference (only required if error state)
4072 if (other.param_type != nullptr)
4073 param_type = other.param_type->clone_type ();
4074 else
4075 param_type = nullptr;
4076
4077 return *this;
4078 }
4079
4080 // move constructors
4081 NamedFunctionParam (NamedFunctionParam &&other) = default;
4082 NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
4083
4084 std::string as_string () const;
4085
4086 // Based on idea that nane should never be empty.
4087 void mark_for_strip () { param_type = nullptr; };
4088 bool is_marked_for_strip () const { return is_error (); };
4089
4090 // TODO: this mutable getter seems really dodgy. Think up better way.
4091 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
4092 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
4093
4094 // TODO: is this better? Or is a "vis_block" better?
4095 std::unique_ptr<Type> &get_type ()
4096 {
4097 rust_assert (param_type != nullptr);
4098 return param_type;
4099 }
4100
4101 NodeId get_node_id () const { return node_id; }
4102};
4103
4104// A function item used in an extern block
4105class ExternalFunctionItem : public ExternalItem
4106{
4107 // bool has_outer_attrs;
4108 std::vector<Attribute> outer_attrs;
4109
4110 // bool has_visibility;
4111 Visibility visibility;
4112
4113 Identifier item_name;
4114 Location locus;
4115
4116 // bool has_generics;
4117 // Generics generic_params;
4118 std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
4119
4120 // bool has_return_type;
4121 // FunctionReturnType return_type;
4122 std::unique_ptr<Type> return_type; // inlined
4123
4124 // bool has_where_clause;
4125 WhereClause where_clause;
4126
4127 std::vector<NamedFunctionParam> function_params;
4128 bool has_variadics;
4129 std::vector<Attribute> variadic_outer_attrs;
4130
4131public:
4132 // Returns whether item has generic parameters.
4133 bool has_generics () const { return !generic_params.empty (); }
4134
4135 // Returns whether item has a return type (otherwise void).
4136 bool has_return_type () const { return return_type != nullptr; }
4137
4138 // Returns whether item has a where clause.
4139 bool has_where_clause () const { return !where_clause.is_empty (); }
4140
4141 // Returns whether item has outer attributes.
4142 bool has_outer_attrs () const { return !outer_attrs.empty (); }
4143
4144 // Returns whether item has non-default visibility.
4145 bool has_visibility () const { return !visibility.is_error (); }
4146
4147 // Returns whether item has variadic parameters.
4148 bool is_variadic () const { return has_variadics; }
4149
4150 // Returns whether item has outer attributes on its variadic parameters.
4151 bool has_variadic_outer_attrs () const
4152 {
4153 return !variadic_outer_attrs.empty ();
4154 }
4155
4156 Location get_locus () const { return locus; }
4157
907d1119 4158 Visibility &get_visibility () { return visibility; }
438ae944
JP
4159 const Visibility &get_visibility () const { return visibility; }
4160
4161 ExternalFunctionItem (
4162 Identifier item_name,
4163 std::vector<std::unique_ptr<GenericParam>> generic_params,
4164 std::unique_ptr<Type> return_type, WhereClause where_clause,
4165 std::vector<NamedFunctionParam> function_params, bool has_variadics,
4166 std::vector<Attribute> variadic_outer_attrs, Visibility vis,
4167 std::vector<Attribute> outer_attrs, Location locus)
4168 : ExternalItem (), outer_attrs (std::move (outer_attrs)),
4169 visibility (std::move (vis)), item_name (std::move (item_name)),
4170 locus (locus), generic_params (std::move (generic_params)),
4171 return_type (std::move (return_type)),
4172 where_clause (std::move (where_clause)),
4173 function_params (std::move (function_params)),
4174 has_variadics (has_variadics),
4175 variadic_outer_attrs (std::move (variadic_outer_attrs))
4176 {
4177 // TODO: assert that if has variadic outer attrs, then has_variadics is
4178 // true?
4179 }
4180
4181 // Copy constructor with clone
4182 ExternalFunctionItem (ExternalFunctionItem const &other)
4183 : outer_attrs (other.outer_attrs), visibility (other.visibility),
4184 item_name (other.item_name), locus (other.locus),
4185 where_clause (other.where_clause),
4186 function_params (other.function_params),
4187 has_variadics (other.has_variadics),
4188 variadic_outer_attrs (other.variadic_outer_attrs)
4189 {
4190 node_id = other.node_id;
4191 // guard to prevent null pointer dereference
4192 if (other.return_type != nullptr)
4193 return_type = other.return_type->clone_type ();
4194
4195 generic_params.reserve (other.generic_params.size ());
4196 for (const auto &e : other.generic_params)
4197 generic_params.push_back (e->clone_generic_param ());
4198 }
4199
4200 // Overloaded assignment operator with clone
4201 ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
4202 {
4203 outer_attrs = other.outer_attrs;
4204 visibility = other.visibility;
4205 item_name = other.item_name;
4206 locus = other.locus;
4207 where_clause = other.where_clause;
4208 function_params = other.function_params;
4209 has_variadics = other.has_variadics;
4210 variadic_outer_attrs = other.variadic_outer_attrs;
4211 node_id = other.node_id;
4212
4213 // guard to prevent null pointer dereference
4214 if (other.return_type != nullptr)
4215 return_type = other.return_type->clone_type ();
4216 else
4217 return_type = nullptr;
4218
4219 generic_params.reserve (other.generic_params.size ());
4220 for (const auto &e : other.generic_params)
4221 generic_params.push_back (e->clone_generic_param ());
4222
4223 return *this;
4224 }
4225
4226 // move constructors
4227 ExternalFunctionItem (ExternalFunctionItem &&other) = default;
4228 ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default;
4229
4230 std::string as_string () const override;
4231
4232 void accept_vis (ASTVisitor &vis) override;
4233
4234 // Based on idea that nane should never be empty.
4235 void mark_for_strip () override { item_name = ""; };
4236 bool is_marked_for_strip () const override { return item_name.empty (); };
4237
4238 // TODO: this mutable getter seems really dodgy. Think up better way.
4239 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
4240 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
4241
4242 std::vector<NamedFunctionParam> &get_function_params ()
4243 {
4244 return function_params;
4245 }
4246 const std::vector<NamedFunctionParam> &get_function_params () const
4247 {
4248 return function_params;
4249 }
4250
4251 std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
4252 {
4253 return generic_params;
4254 }
4255 const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
4256 {
4257 return generic_params;
4258 }
4259
4260 // TODO: is this better? Or is a "vis_block" better?
4261 WhereClause &get_where_clause () { return where_clause; }
4262
4263 // TODO: is this better? Or is a "vis_block" better?
4264 std::unique_ptr<Type> &get_return_type ()
4265 {
4266 rust_assert (has_return_type ());
4267 return return_type;
4268 }
4269
4270 Identifier get_identifier () const { return item_name; };
4271
4272protected:
4273 /* Use covariance to implement clone function as returning this object
4274 * rather than base */
4275 ExternalFunctionItem *clone_external_item_impl () const override
4276 {
4277 return new ExternalFunctionItem (*this);
4278 }
4279};
4280
4281// An extern block AST node
4282class ExternBlock : public VisItem
4283{
4284 // bool has_abi;
4285 std::string abi;
4286
4287 // bool has_inner_attrs;
4288 std::vector<Attribute> inner_attrs;
4289
4290 // bool has_extern_items;
4291 std::vector<std::unique_ptr<ExternalItem>> extern_items;
4292
4293 Location locus;
4294
4295 // TODO: find another way to store this to save memory?
4296 bool marked_for_strip = false;
4297
4298public:
4299 std::string as_string () const override;
4300
4301 // Returns whether extern block has inner attributes.
4302 bool has_inner_attrs () const { return !inner_attrs.empty (); }
4303
4304 // Returns whether extern block has extern items.
4305 bool has_extern_items () const { return !extern_items.empty (); }
4306
4307 // Returns whether extern block has ABI name.
4308 bool has_abi () const { return !abi.empty (); }
4309
4310 std::string get_abi () const { return abi; }
4311
4312 ExternBlock (std::string abi,
4313 std::vector<std::unique_ptr<ExternalItem>> extern_items,
4314 Visibility vis, std::vector<Attribute> inner_attrs,
4315 std::vector<Attribute> outer_attrs, Location locus)
4316 : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
4317 inner_attrs (std::move (inner_attrs)),
4318 extern_items (std::move (extern_items)), locus (locus)
4319 {}
4320
4321 // Copy constructor with vector clone
4322 ExternBlock (ExternBlock const &other)
4323 : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
4324 locus (other.locus), marked_for_strip (other.marked_for_strip)
4325 {
4326 extern_items.reserve (other.extern_items.size ());
4327 for (const auto &e : other.extern_items)
4328 extern_items.push_back (e->clone_external_item ());
4329 }
4330
4331 // Overloaded assignment operator with vector clone
4332 ExternBlock &operator= (ExternBlock const &other)
4333 {
4334 VisItem::operator= (other);
4335 abi = other.abi;
4336 inner_attrs = other.inner_attrs;
4337 locus = other.locus;
4338 marked_for_strip = other.marked_for_strip;
4339
4340 extern_items.reserve (other.extern_items.size ());
4341 for (const auto &e : other.extern_items)
4342 extern_items.push_back (e->clone_external_item ());
4343
4344 return *this;
4345 }
4346
4347 // move constructors
4348 ExternBlock (ExternBlock &&other) = default;
4349 ExternBlock &operator= (ExternBlock &&other) = default;
4350
4351 Location get_locus () const override final { return locus; }
4352
4353 void accept_vis (ASTVisitor &vis) override;
4354
4355 // Can't think of any invalid invariants, so store boolean.
4356 void mark_for_strip () override { marked_for_strip = true; }
4357 bool is_marked_for_strip () const override { return marked_for_strip; }
4358
4359 // TODO: think of better way to do this
4360 const std::vector<std::unique_ptr<ExternalItem>> &get_extern_items () const
4361 {
4362 return extern_items;
4363 }
4364 std::vector<std::unique_ptr<ExternalItem>> &get_extern_items ()
4365 {
4366 return extern_items;
4367 }
4368
4369 // TODO: think of better way to do this
4370 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
4371 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
4372
4373protected:
4374 /* Use covariance to implement clone function as returning this object
4375 * rather than base */
4376 ExternBlock *clone_item_impl () const override
4377 {
4378 return new ExternBlock (*this);
4379 }
4380};
4381
438ae944
JP
4382class MacroRulesDefinition;
4383} // namespace AST
4384} // namespace Rust
4385
4386#endif