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