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