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