]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/ast/rust-type.h
1bb521d858502f78aa008f15658fe4df307a37d6
[thirdparty/gcc.git] / gcc / rust / ast / rust-type.h
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_TYPE_H
20 #define RUST_AST_TYPE_H
21
22 #include "rust-ast.h"
23 #include "rust-path.h"
24
25 namespace Rust {
26 namespace AST {
27 // definitions moved to rust-ast.h
28 class TypeParamBound;
29 class Lifetime;
30
31 // A trait bound
32 class TraitBound : public TypeParamBound
33 {
34 bool in_parens;
35 bool opening_question_mark;
36
37 // bool has_for_lifetimes;
38 // LifetimeParams for_lifetimes;
39 std::vector<LifetimeParam> for_lifetimes; // inlined LifetimeParams
40
41 TypePath type_path;
42
43 location_t locus;
44
45 public:
46 // Returns whether trait bound has "for" lifetimes
47 bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
48
49 std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
50
51 const std::vector<LifetimeParam> &get_for_lifetimes () const
52 {
53 return for_lifetimes;
54 }
55
56 TraitBound (TypePath type_path, location_t locus, bool in_parens = false,
57 bool opening_question_mark = false,
58 std::vector<LifetimeParam> for_lifetimes
59 = std::vector<LifetimeParam> ())
60 : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
61 in_parens (in_parens), opening_question_mark (opening_question_mark),
62 for_lifetimes (std::move (for_lifetimes)),
63 type_path (std::move (type_path)), locus (locus)
64 {}
65
66 TraitBound (NodeId id, TypePath type_path, location_t locus,
67 bool in_parens = false, bool opening_question_mark = false,
68 std::vector<LifetimeParam> for_lifetimes
69 = std::vector<LifetimeParam> ())
70 : TypeParamBound (id), in_parens (in_parens),
71 opening_question_mark (opening_question_mark),
72 for_lifetimes (std::move (for_lifetimes)),
73 type_path (std::move (type_path)), locus (locus)
74 {}
75
76 std::string as_string () const override;
77
78 location_t get_locus () const override final { return locus; }
79
80 void accept_vis (ASTVisitor &vis) override;
81
82 // TODO: this mutable getter seems kinda dodgy
83 TypePath &get_type_path () { return type_path; }
84 const TypePath &get_type_path () const { return type_path; }
85
86 bool is_in_parens () const { return in_parens; }
87 bool has_opening_question_mark () const { return opening_question_mark; }
88
89 TypeParamBoundType get_bound_type () const override
90 {
91 return TypeParamBound::TypeParamBoundType::TRAIT;
92 }
93
94 protected:
95 /* Use covariance to implement clone function as returning this object rather
96 * than base */
97 TraitBound *clone_type_param_bound_impl () const override
98 {
99 return new TraitBound (node_id, type_path, locus, in_parens,
100 opening_question_mark, for_lifetimes);
101 }
102 };
103
104 // definition moved to rust-ast.h
105 class TypeNoBounds;
106
107 // An impl trait? Poor reference material here.
108 class ImplTraitType : public Type
109 {
110 // TypeParamBounds type_param_bounds;
111 // inlined form
112 std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
113
114 location_t locus;
115
116 protected:
117 /* Use covariance to implement clone function as returning this object rather
118 * than base */
119 ImplTraitType *clone_type_impl () const override
120 {
121 return new ImplTraitType (*this);
122 }
123
124 public:
125 ImplTraitType (
126 std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
127 location_t locus)
128 : type_param_bounds (std::move (type_param_bounds)), locus (locus)
129 {}
130
131 // copy constructor with vector clone
132 ImplTraitType (ImplTraitType const &other) : locus (other.locus)
133 {
134 type_param_bounds.reserve (other.type_param_bounds.size ());
135 for (const auto &e : other.type_param_bounds)
136 type_param_bounds.push_back (e->clone_type_param_bound ());
137 }
138
139 // overloaded assignment operator to clone
140 ImplTraitType &operator= (ImplTraitType const &other)
141 {
142 locus = other.locus;
143
144 type_param_bounds.reserve (other.type_param_bounds.size ());
145 for (const auto &e : other.type_param_bounds)
146 type_param_bounds.push_back (e->clone_type_param_bound ());
147
148 return *this;
149 }
150
151 // move constructors
152 ImplTraitType (ImplTraitType &&other) = default;
153 ImplTraitType &operator= (ImplTraitType &&other) = default;
154
155 std::string as_string () const override;
156
157 location_t get_locus () const override final { return locus; }
158
159 void accept_vis (ASTVisitor &vis) override;
160
161 // TODO: mutable getter seems kinda dodgy
162 std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
163 {
164 return type_param_bounds;
165 }
166 const std::vector<std::unique_ptr<TypeParamBound> > &
167 get_type_param_bounds () const
168 {
169 return type_param_bounds;
170 }
171 };
172
173 // An opaque value of another type that implements a set of traits
174 class TraitObjectType : public Type
175 {
176 bool has_dyn;
177 std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
178 location_t locus;
179
180 protected:
181 /* Use covariance to implement clone function as returning this object rather
182 * than base */
183 TraitObjectType *clone_type_impl () const override
184 {
185 return new TraitObjectType (*this);
186 }
187
188 public:
189 TraitObjectType (
190 std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
191 location_t locus, bool is_dyn_dispatch)
192 : has_dyn (is_dyn_dispatch),
193 type_param_bounds (std::move (type_param_bounds)), locus (locus)
194 {}
195
196 // copy constructor with vector clone
197 TraitObjectType (TraitObjectType const &other)
198 : has_dyn (other.has_dyn), locus (other.locus)
199 {
200 type_param_bounds.reserve (other.type_param_bounds.size ());
201 for (const auto &e : other.type_param_bounds)
202 type_param_bounds.push_back (e->clone_type_param_bound ());
203 }
204
205 // overloaded assignment operator to clone
206 TraitObjectType &operator= (TraitObjectType const &other)
207 {
208 has_dyn = other.has_dyn;
209 locus = other.locus;
210 type_param_bounds.reserve (other.type_param_bounds.size ());
211 for (const auto &e : other.type_param_bounds)
212 type_param_bounds.push_back (e->clone_type_param_bound ());
213
214 return *this;
215 }
216
217 // move constructors
218 TraitObjectType (TraitObjectType &&other) = default;
219 TraitObjectType &operator= (TraitObjectType &&other) = default;
220
221 std::string as_string () const override;
222
223 location_t get_locus () const override final { return locus; }
224
225 void accept_vis (ASTVisitor &vis) override;
226
227 bool is_dyn () const { return has_dyn; }
228
229 // TODO: mutable getter seems kinda dodgy
230 std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
231 {
232 return type_param_bounds;
233 }
234 const std::vector<std::unique_ptr<TypeParamBound> > &
235 get_type_param_bounds () const
236 {
237 return type_param_bounds;
238 }
239 };
240
241 // A type with parentheses around it, used to avoid ambiguity.
242 class ParenthesisedType : public TypeNoBounds
243 {
244 std::unique_ptr<Type> type_in_parens;
245 location_t locus;
246
247 protected:
248 /* Use covariance to implement clone function as returning this object rather
249 * than base */
250 ParenthesisedType *clone_type_no_bounds_impl () const override
251 {
252 return new ParenthesisedType (*this);
253 }
254
255 public:
256 // Constructor uses Type pointer for polymorphism
257 ParenthesisedType (std::unique_ptr<Type> type_inside_parens, location_t locus)
258 : type_in_parens (std::move (type_inside_parens)), locus (locus)
259 {}
260
261 /* Copy constructor uses custom deep copy method for type to preserve
262 * polymorphism */
263 ParenthesisedType (ParenthesisedType const &other)
264 : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus)
265 {}
266
267 // overload assignment operator to use custom clone method
268 ParenthesisedType &operator= (ParenthesisedType const &other)
269 {
270 type_in_parens = other.type_in_parens->clone_type ();
271 locus = other.locus;
272 return *this;
273 }
274
275 // default move semantics
276 ParenthesisedType (ParenthesisedType &&other) = default;
277 ParenthesisedType &operator= (ParenthesisedType &&other) = default;
278
279 std::string as_string () const override
280 {
281 return "(" + type_in_parens->as_string () + ")";
282 }
283
284 // Creates a trait bound (clone of this one's trait bound) - HACK
285 TraitBound *to_trait_bound (bool) const override
286 {
287 /* NOTE: obviously it is unknown whether the internal type is a trait bound
288 * due to polymorphism, so just let the internal type handle it. As
289 * parenthesised type, it must be in parentheses. */
290 return type_in_parens->to_trait_bound (true);
291 }
292
293 location_t get_locus () const override final { return locus; }
294
295 void accept_vis (ASTVisitor &vis) override;
296
297 // TODO: would a "vis_type" be better?
298 std::unique_ptr<Type> &get_type_in_parens ()
299 {
300 rust_assert (type_in_parens != nullptr);
301 return type_in_parens;
302 }
303 };
304
305 // Impl trait with a single bound? Poor reference material here.
306 class ImplTraitTypeOneBound : public TypeNoBounds
307 {
308 TraitBound trait_bound;
309 location_t locus;
310
311 protected:
312 /* Use covariance to implement clone function as returning this object rather
313 * than base */
314 ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override
315 {
316 return new ImplTraitTypeOneBound (*this);
317 }
318
319 public:
320 ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus)
321 : trait_bound (std::move (trait_bound)), locus (locus)
322 {}
323
324 std::string as_string () const override;
325
326 location_t get_locus () const override final { return locus; }
327
328 void accept_vis (ASTVisitor &vis) override;
329
330 // TODO: would a "vis_type" be better?
331 TraitBound &get_trait_bound ()
332 {
333 // TODO: check to ensure invariants are met?
334 return trait_bound;
335 }
336 };
337
338 /* A trait object with a single trait bound. The "trait bound" is really just
339 * the trait. Basically like using an interface as a type in an OOP language. */
340 class TraitObjectTypeOneBound : public TypeNoBounds
341 {
342 bool has_dyn;
343 TraitBound trait_bound;
344 location_t locus;
345
346 protected:
347 /* Use covariance to implement clone function as returning this object rather
348 * than base */
349 TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override
350 {
351 return new TraitObjectTypeOneBound (*this);
352 }
353
354 public:
355 TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
356 bool is_dyn_dispatch = false)
357 : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)),
358 locus (locus)
359 {}
360
361 std::string as_string () const override;
362
363 // Creates a trait bound (clone of this one's trait bound) - HACK
364 TraitBound *to_trait_bound (bool) const override
365 {
366 /* NOTE: this assumes there is no dynamic dispatch specified- if there was,
367 * this cloning would not be required as parsing is unambiguous. */
368 return new TraitBound (trait_bound);
369 }
370
371 location_t get_locus () const override final { return locus; }
372
373 void accept_vis (ASTVisitor &vis) override;
374
375 // TODO: would a "vis_type" be better?
376 TraitBound &get_trait_bound ()
377 {
378 // TODO: check to ensure invariants are met?
379 return trait_bound;
380 }
381
382 bool is_dyn () const { return has_dyn; }
383 };
384
385 class TypePath; // definition moved to "rust-path.h"
386
387 /* A type consisting of the "product" of others (the tuple's elements) in a
388 * specific order */
389 class TupleType : public TypeNoBounds
390 {
391 std::vector<std::unique_ptr<Type> > elems;
392 location_t locus;
393
394 public:
395 // Returns whether the tuple type is the unit type, i.e. has no elements.
396 bool is_unit_type () const { return elems.empty (); }
397
398 TupleType (std::vector<std::unique_ptr<Type> > elems, location_t locus)
399 : elems (std::move (elems)), locus (locus)
400 {}
401
402 // copy constructor with vector clone
403 TupleType (TupleType const &other) : locus (other.locus)
404 {
405 elems.reserve (other.elems.size ());
406 for (const auto &e : other.elems)
407 elems.push_back (e->clone_type ());
408 }
409
410 // overloaded assignment operator to clone
411 TupleType &operator= (TupleType const &other)
412 {
413 locus = other.locus;
414
415 elems.reserve (other.elems.size ());
416 for (const auto &e : other.elems)
417 elems.push_back (e->clone_type ());
418
419 return *this;
420 }
421
422 // move constructors
423 TupleType (TupleType &&other) = default;
424 TupleType &operator= (TupleType &&other) = default;
425
426 std::string as_string () const override;
427
428 location_t get_locus () const override final { return locus; }
429
430 void accept_vis (ASTVisitor &vis) override;
431
432 // TODO: mutable getter seems kinda dodgy
433 std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
434 const std::vector<std::unique_ptr<Type> > &get_elems () const
435 {
436 return elems;
437 }
438
439 protected:
440 /* Use covariance to implement clone function as returning this object rather
441 * than base */
442 TupleType *clone_type_no_bounds_impl () const override
443 {
444 return new TupleType (*this);
445 }
446 };
447
448 /* A type with no values, representing the result of computations that never
449 * complete. Expressions of NeverType can be coerced into any other types.
450 * Represented as "!". */
451 class NeverType : public TypeNoBounds
452 {
453 location_t locus;
454
455 protected:
456 /* Use covariance to implement clone function as returning this object rather
457 * than base */
458 NeverType *clone_type_no_bounds_impl () const override
459 {
460 return new NeverType (*this);
461 }
462
463 public:
464 NeverType (location_t locus) : locus (locus) {}
465
466 std::string as_string () const override { return "! (never type)"; }
467
468 location_t get_locus () const override final { return locus; }
469
470 void accept_vis (ASTVisitor &vis) override;
471 };
472
473 // A type consisting of a pointer without safety or liveness guarantees
474 class RawPointerType : public TypeNoBounds
475 {
476 public:
477 enum PointerType
478 {
479 MUT,
480 CONST
481 };
482
483 private:
484 PointerType pointer_type;
485 std::unique_ptr<TypeNoBounds> type;
486 location_t locus;
487
488 public:
489 // Returns whether the pointer is mutable or constant.
490 PointerType get_pointer_type () const { return pointer_type; }
491
492 // Constructor requires pointer for polymorphism reasons
493 RawPointerType (PointerType pointer_type,
494 std::unique_ptr<TypeNoBounds> type_no_bounds,
495 location_t locus)
496 : pointer_type (pointer_type), type (std::move (type_no_bounds)),
497 locus (locus)
498 {}
499
500 // Copy constructor calls custom polymorphic clone function
501 RawPointerType (RawPointerType const &other)
502 : pointer_type (other.pointer_type),
503 type (other.type->clone_type_no_bounds ()), locus (other.locus)
504 {}
505
506 // overload assignment operator to use custom clone method
507 RawPointerType &operator= (RawPointerType const &other)
508 {
509 pointer_type = other.pointer_type;
510 type = other.type->clone_type_no_bounds ();
511 locus = other.locus;
512 return *this;
513 }
514
515 // default move semantics
516 RawPointerType (RawPointerType &&other) = default;
517 RawPointerType &operator= (RawPointerType &&other) = default;
518
519 std::string as_string () const override;
520
521 location_t get_locus () const override final { return locus; }
522
523 void accept_vis (ASTVisitor &vis) override;
524
525 // TODO: would a "vis_type" be better?
526 TypeNoBounds &get_type_pointed_to ()
527 {
528 rust_assert (type != nullptr);
529 return *type;
530 }
531
532 protected:
533 /* Use covariance to implement clone function as returning this object rather
534 * than base */
535 RawPointerType *clone_type_no_bounds_impl () const override
536 {
537 return new RawPointerType (*this);
538 }
539 };
540
541 // A type pointing to memory owned by another value
542 class ReferenceType : public TypeNoBounds
543 {
544 // bool has_lifetime; // TODO: handle in lifetime or something?
545 tl::optional<Lifetime> lifetime;
546
547 bool has_mut;
548 std::unique_ptr<TypeNoBounds> type;
549 location_t locus;
550
551 public:
552 // Returns whether the reference is mutable or immutable.
553 bool is_mut () const { return has_mut; }
554
555 // Returns whether the reference has a lifetime.
556 bool has_lifetime () const { return lifetime.has_value (); }
557
558 // Constructor
559 ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
560 location_t locus,
561 tl::optional<Lifetime> lifetime = Lifetime::elided ())
562 : lifetime (std::move (lifetime)), has_mut (is_mut),
563 type (std::move (type_no_bounds)), locus (locus)
564 {}
565
566 // Copy constructor with custom clone method
567 ReferenceType (ReferenceType const &other)
568 : lifetime (other.lifetime), has_mut (other.has_mut),
569 type (other.type->clone_type_no_bounds ()), locus (other.locus)
570 {}
571
572 // Operator overload assignment operator to custom clone the unique pointer
573 ReferenceType &operator= (ReferenceType const &other)
574 {
575 lifetime = other.lifetime;
576 has_mut = other.has_mut;
577 type = other.type->clone_type_no_bounds ();
578 locus = other.locus;
579
580 return *this;
581 }
582
583 // move constructors
584 ReferenceType (ReferenceType &&other) = default;
585 ReferenceType &operator= (ReferenceType &&other) = default;
586
587 std::string as_string () const override;
588
589 location_t get_locus () const override final { return locus; }
590
591 void accept_vis (ASTVisitor &vis) override;
592
593 // TODO: would a "vis_type" be better?
594 TypeNoBounds &get_type_referenced ()
595 {
596 rust_assert (type != nullptr);
597 return *type;
598 }
599
600 bool get_has_mut () const { return has_mut; }
601
602 Lifetime &get_lifetime () { return lifetime.value (); }
603 const Lifetime &get_lifetime () const { return lifetime.value (); }
604
605 TypeNoBounds &get_base_type () { return *type; }
606
607 protected:
608 /* Use covariance to implement clone function as returning this object rather
609 * than base */
610 ReferenceType *clone_type_no_bounds_impl () const override
611 {
612 return new ReferenceType (*this);
613 }
614 };
615
616 // A fixed-size sequence of elements of a specified type
617 class ArrayType : public TypeNoBounds
618 {
619 std::unique_ptr<Type> elem_type;
620 std::unique_ptr<Expr> size;
621 location_t locus;
622
623 public:
624 // Constructor requires pointers for polymorphism
625 ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
626 location_t locus)
627 : elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
628 {}
629
630 // Copy constructor requires deep copies of both unique pointers
631 ArrayType (ArrayType const &other)
632 : elem_type (other.elem_type->clone_type ()),
633 size (other.size->clone_expr ()), locus (other.locus)
634 {}
635
636 // Overload assignment operator to deep copy pointers
637 ArrayType &operator= (ArrayType const &other)
638 {
639 elem_type = other.elem_type->clone_type ();
640 size = other.size->clone_expr ();
641 locus = other.locus;
642 return *this;
643 }
644
645 // move constructors
646 ArrayType (ArrayType &&other) = default;
647 ArrayType &operator= (ArrayType &&other) = default;
648
649 std::string as_string () const override;
650
651 location_t get_locus () const override final { return locus; }
652
653 void accept_vis (ASTVisitor &vis) override;
654
655 // TODO: would a "vis_type" be better?
656 Type &get_elem_type ()
657 {
658 rust_assert (elem_type != nullptr);
659 return *elem_type;
660 }
661
662 // TODO: would a "vis_expr" be better?
663 Expr &get_size_expr ()
664 {
665 rust_assert (size != nullptr);
666 return *size;
667 }
668
669 protected:
670 /* Use covariance to implement clone function as returning this object rather
671 * than base */
672 ArrayType *clone_type_no_bounds_impl () const override
673 {
674 return new ArrayType (*this);
675 }
676 };
677
678 /* A dynamically-sized type representing a "view" into a sequence of elements of
679 * a type */
680 class SliceType : public TypeNoBounds
681 {
682 std::unique_ptr<Type> elem_type;
683 location_t locus;
684
685 public:
686 // Constructor requires pointer for polymorphism
687 SliceType (std::unique_ptr<Type> type, location_t locus)
688 : elem_type (std::move (type)), locus (locus)
689 {}
690
691 // Copy constructor requires deep copy of Type smart pointer
692 SliceType (SliceType const &other)
693 : elem_type (other.elem_type->clone_type ()), locus (other.locus)
694 {}
695
696 // Overload assignment operator to deep copy
697 SliceType &operator= (SliceType const &other)
698 {
699 elem_type = other.elem_type->clone_type ();
700 locus = other.locus;
701
702 return *this;
703 }
704
705 // move constructors
706 SliceType (SliceType &&other) = default;
707 SliceType &operator= (SliceType &&other) = default;
708
709 std::string as_string () const override;
710
711 location_t get_locus () const override final { return locus; }
712
713 void accept_vis (ASTVisitor &vis) override;
714
715 // TODO: would a "vis_type" be better?
716 Type &get_elem_type ()
717 {
718 rust_assert (elem_type != nullptr);
719 return *elem_type;
720 }
721
722 protected:
723 /* Use covariance to implement clone function as returning this object rather
724 * than base */
725 SliceType *clone_type_no_bounds_impl () const override
726 {
727 return new SliceType (*this);
728 }
729 };
730
731 /* Type used in generic arguments to explicitly request type inference (wildcard
732 * pattern) */
733 class InferredType : public TypeNoBounds
734 {
735 location_t locus;
736
737 // e.g. Vec<_> = whatever
738 protected:
739 /* Use covariance to implement clone function as returning this object rather
740 * than base */
741 InferredType *clone_type_no_bounds_impl () const override
742 {
743 return new InferredType (*this);
744 }
745
746 public:
747 InferredType (location_t locus) : locus (locus) {}
748
749 std::string as_string () const override;
750
751 location_t get_locus () const override final { return locus; }
752
753 void accept_vis (ASTVisitor &vis) override;
754 };
755
756 class QualifiedPathInType; // definition moved to "rust-path.h"
757
758 // A possibly named param used in a BaseFunctionType
759 struct MaybeNamedParam
760 {
761 public:
762 enum ParamKind
763 {
764 UNNAMED,
765 IDENTIFIER,
766 WILDCARD
767 };
768
769 private:
770 std::vector<Attribute> outer_attrs;
771
772 std::unique_ptr<Type> param_type;
773
774 ParamKind param_kind;
775 Identifier name; // technically, can be an identifier or '_'
776
777 location_t locus;
778
779 public:
780 MaybeNamedParam (Identifier name, ParamKind param_kind,
781 std::unique_ptr<Type> param_type,
782 std::vector<Attribute> outer_attrs, location_t locus)
783 : outer_attrs (std::move (outer_attrs)),
784 param_type (std::move (param_type)), param_kind (param_kind),
785 name (std::move (name)), locus (locus)
786 {}
787
788 // Copy constructor with clone
789 MaybeNamedParam (MaybeNamedParam const &other)
790 : outer_attrs (other.outer_attrs), param_kind (other.param_kind),
791 name (other.name), locus (other.locus)
792 {
793 // guard to prevent null dereference
794 if (other.param_type != nullptr)
795 param_type = other.param_type->clone_type ();
796 }
797
798 ~MaybeNamedParam () = default;
799
800 // Overloaded assignment operator with clone
801 MaybeNamedParam &operator= (MaybeNamedParam const &other)
802 {
803 outer_attrs = other.outer_attrs;
804 name = other.name;
805 param_kind = other.param_kind;
806 locus = other.locus;
807
808 // guard to prevent null dereference
809 if (other.param_type != nullptr)
810 param_type = other.param_type->clone_type ();
811 else
812 param_type = nullptr;
813
814 return *this;
815 }
816
817 // move constructors
818 MaybeNamedParam (MaybeNamedParam &&other) = default;
819 MaybeNamedParam &operator= (MaybeNamedParam &&other) = default;
820
821 std::string as_string () const;
822
823 // Returns whether the param is in an error state.
824 bool is_error () const { return param_type == nullptr; }
825
826 // Creates an error state param.
827 static MaybeNamedParam create_error ()
828 {
829 return MaybeNamedParam ({""}, UNNAMED, nullptr, {}, UNDEF_LOCATION);
830 }
831
832 location_t get_locus () const { return locus; }
833
834 // TODO: this mutable getter seems really dodgy. Think up better way.
835 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
836 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
837
838 // TODO: would a "vis_type" be better?
839 Type &get_type ()
840 {
841 rust_assert (param_type != nullptr);
842 return *param_type;
843 }
844
845 std::unique_ptr<Type> &get_type_ptr ()
846 {
847 rust_assert (param_type != nullptr);
848 return param_type;
849 }
850
851 ParamKind get_param_kind () const { return param_kind; }
852
853 Identifier get_name () const { return name; }
854 };
855
856 /* A function pointer type - can be created via coercion from function items and
857 * non-capturing closures. */
858 class BareFunctionType : public TypeNoBounds
859 {
860 // bool has_for_lifetimes;
861 // ForLifetimes for_lifetimes;
862 std::vector<LifetimeParam> for_lifetimes; // inlined version
863
864 FunctionQualifiers function_qualifiers;
865 std::vector<MaybeNamedParam> params;
866 bool _is_variadic;
867 std::vector<Attribute> variadic_attrs;
868
869 // bool has_return_type;
870 // BareFunctionReturnType return_type;
871 std::unique_ptr<TypeNoBounds> return_type; // inlined version
872
873 location_t locus;
874
875 public:
876 // Whether a return type is defined with the function.
877 bool has_return_type () const { return return_type != nullptr; }
878
879 // Whether the function has ForLifetimes.
880 bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
881
882 std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
883
884 bool is_variadic () const { return _is_variadic; }
885
886 std::vector<Attribute> &get_variadic_attr () { return variadic_attrs; };
887 const std::vector<Attribute> &get_variadic_attr () const
888 {
889 return variadic_attrs;
890 };
891
892 BareFunctionType (std::vector<LifetimeParam> lifetime_params,
893 FunctionQualifiers qualifiers,
894 std::vector<MaybeNamedParam> named_params, bool is_variadic,
895 std::vector<Attribute> variadic_attrs,
896 std::unique_ptr<TypeNoBounds> type, location_t locus)
897 : for_lifetimes (std::move (lifetime_params)),
898 function_qualifiers (std::move (qualifiers)),
899 params (std::move (named_params)), _is_variadic (is_variadic),
900 variadic_attrs (std::move (variadic_attrs)),
901 return_type (std::move (type)), locus (locus)
902 {
903 if (!variadic_attrs.empty ())
904 is_variadic = true;
905 }
906
907 // Copy constructor with clone
908 BareFunctionType (BareFunctionType const &other)
909 : for_lifetimes (other.for_lifetimes),
910 function_qualifiers (other.function_qualifiers), params (other.params),
911 _is_variadic (other._is_variadic), variadic_attrs (other.variadic_attrs),
912 locus (other.locus)
913 {
914 // guard to prevent null dereference
915 if (other.return_type != nullptr)
916 return_type = other.return_type->clone_type_no_bounds ();
917 }
918
919 // Overload assignment operator to deep copy
920 BareFunctionType &operator= (BareFunctionType const &other)
921 {
922 for_lifetimes = other.for_lifetimes;
923 function_qualifiers = other.function_qualifiers;
924 params = other.params;
925 _is_variadic = other._is_variadic;
926 variadic_attrs = other.variadic_attrs;
927 locus = other.locus;
928
929 // guard to prevent null dereference
930 if (other.return_type != nullptr)
931 return_type = other.return_type->clone_type_no_bounds ();
932 else
933 return_type = nullptr;
934
935 return *this;
936 }
937
938 // move constructors
939 BareFunctionType (BareFunctionType &&other) = default;
940 BareFunctionType &operator= (BareFunctionType &&other) = default;
941
942 std::string as_string () const override;
943
944 location_t get_locus () const override final { return locus; }
945
946 void accept_vis (ASTVisitor &vis) override;
947
948 // TODO: this mutable getter seems kinda dodgy
949 std::vector<MaybeNamedParam> &get_function_params () { return params; }
950 const std::vector<MaybeNamedParam> &get_function_params () const
951 {
952 return params;
953 }
954
955 // TODO: would a "vis_type" be better?
956 TypeNoBounds &get_return_type ()
957 {
958 rust_assert (has_return_type ());
959 return *return_type;
960 }
961
962 FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
963
964 protected:
965 /* Use covariance to implement clone function as returning this object rather
966 * than base */
967 BareFunctionType *clone_type_no_bounds_impl () const override
968 {
969 return new BareFunctionType (*this);
970 }
971 };
972
973 // Forward decl - defined in rust-macro.h
974 class MacroInvocation;
975
976 /* TODO: possible types
977 * struct type?
978 * "enum" (tagged union) type?
979 * C-like union type?
980 * function item type?
981 * closure expression types?
982 * primitive types (bool, int, float, char, str (the slice))
983 * Although supposedly TypePaths are used to reference these types (including
984 * primitives) */
985
986 /* FIXME: Incomplete spec references:
987 * anonymous type parameters, aka "impl Trait in argument position" - impl then
988 * trait bounds abstract return types, aka "impl Trait in return position" -
989 * impl then trait bounds */
990 } // namespace AST
991 } // namespace Rust
992
993 #endif