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