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