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 : 183 : bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
50 : :
51 : 29993 : 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 : 2279 : 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 : 2279 : : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
63 : 2279 : in_parens (in_parens), opening_question_mark (opening_question_mark),
64 : 2279 : for_lifetimes (std::move (for_lifetimes)),
65 : 2279 : type_path (std::move (type_path)), locus (locus)
66 : 2279 : {}
67 : :
68 : 75 : 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 : 75 : : TypeParamBound (id), in_parens (in_parens),
73 : 75 : opening_question_mark (opening_question_mark),
74 : 75 : for_lifetimes (std::move (for_lifetimes)),
75 : 75 : type_path (std::move (type_path)), locus (locus)
76 : 75 : {}
77 : :
78 : 518 : TraitBound (TraitBound const &other)
79 : 518 : : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens),
80 : 518 : opening_question_mark (other.opening_question_mark),
81 : 518 : for_lifetimes (other.for_lifetimes), type_path (other.type_path),
82 : 518 : locus (other.locus)
83 : 518 : {}
84 : :
85 : : std::string as_string () const override;
86 : :
87 : 1814 : 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 : 37058 : TypePath &get_type_path () { return type_path; }
93 : 2 : const TypePath &get_type_path () const { return type_path; }
94 : :
95 : 1764 : bool is_in_parens () const { return in_parens; }
96 : 1947 : 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 : 75 : TraitBound *clone_type_param_bound_impl () const override
107 : : {
108 : 225 : return new TraitBound (node_id, type_path, locus, in_parens,
109 : 75 : 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 : : // TODO: mutable getter seems kinda dodgy
181 : 0 : std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
182 : : {
183 : 0 : 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 : 2 : TraitObjectType *clone_type_impl () const override
203 : : {
204 : 2 : 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 : 14 : TraitObjectType (
214 : : std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
215 : : location_t locus, bool is_dyn_dispatch)
216 : 28 : : has_dyn (is_dyn_dispatch),
217 : 14 : type_param_bounds (std::move (type_param_bounds)), locus (locus)
218 : : {}
219 : :
220 : : // copy constructor with vector clone
221 : 2 : TraitObjectType (TraitObjectType const &other)
222 : 2 : : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
223 : : {
224 : 2 : type_param_bounds.reserve (other.type_param_bounds.size ());
225 : 8 : for (const auto &e : other.type_param_bounds)
226 : 6 : type_param_bounds.push_back (e->clone_type_param_bound ());
227 : 2 : }
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 : 36 : 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 : 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 : :
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 : 4 : ParenthesisedType (std::unique_ptr<Type> type_inside_parens, location_t locus)
286 : 4 : : 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 : 14 : 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 : 78 : std::unique_ptr<Type> &get_type_in_parens ()
327 : : {
328 : 78 : rust_assert (type_in_parens != nullptr);
329 : 78 : 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 : 134 : ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound,
341 : : location_t locus)
342 : 134 : : 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 : 545 : location_t get_locus () const override final { return locus; }
353 : :
354 : : void accept_vis (ASTVisitor &vis) override;
355 : :
356 : 1819 : 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 : 39 : TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override
380 : : {
381 : 39 : 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 : 156 : TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
390 : : bool is_dyn_dispatch = false)
391 : 312 : : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)),
392 : 156 : 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 : 257 : 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 : 2587 : TraitBound &get_trait_bound ()
411 : : {
412 : : // TODO: check to ensure invariants are met?
413 : 2587 : return trait_bound;
414 : : }
415 : :
416 : 215 : 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 : 4689 : TupleType (std::vector<std::unique_ptr<Type> > elems, location_t locus)
433 : 4689 : : elems (std::move (elems)), locus (locus)
434 : 4689 : {}
435 : :
436 : : // copy constructor with vector clone
437 : 601 : TupleType (TupleType const &other) : locus (other.locus)
438 : : {
439 : 601 : elems.reserve (other.elems.size ());
440 : 1653 : for (const auto &e : other.elems)
441 : 1052 : elems.push_back (e->clone_type ());
442 : 601 : }
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 : 398 : 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 : 9246 : 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 : 601 : TupleType *clone_type_no_bounds_impl () const override
477 : : {
478 : 601 : return new TupleType (*this);
479 : : }
480 : 0 : TupleType *reconstruct_impl () const override
481 : : {
482 : 0 : 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 : 0 : 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 : 0 : NeverType *clone_type_no_bounds_impl () const override
497 : : {
498 : 0 : return new NeverType (*this);
499 : : }
500 : 0 : NeverType *reconstruct_impl () const override
501 : : {
502 : 0 : return new NeverType (locus);
503 : : }
504 : :
505 : : public:
506 : 46 : NeverType (location_t locus) : locus (locus) {}
507 : :
508 : 0 : std::string as_string () const override { return "! (never type)"; }
509 : :
510 : 59 : 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 : 6506 : PointerType get_pointer_type () const { return pointer_type; }
533 : :
534 : : // Constructor requires pointer for polymorphism reasons
535 : 6317 : RawPointerType (PointerType pointer_type,
536 : : std::unique_ptr<TypeNoBounds> type_no_bounds,
537 : : location_t locus)
538 : 12634 : : pointer_type (pointer_type), type (std::move (type_no_bounds)),
539 : 6317 : locus (locus)
540 : : {}
541 : :
542 : : // Copy constructor calls custom polymorphic clone function
543 : 994 : RawPointerType (RawPointerType const &other)
544 : 1988 : : pointer_type (other.pointer_type),
545 : 994 : type (other.type->clone_type_no_bounds ()), locus (other.locus)
546 : 994 : {}
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 : 7702 : 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 : 182578 : TypeNoBounds &get_type_pointed_to ()
569 : : {
570 : 182578 : rust_assert (type != nullptr);
571 : 182578 : return *type;
572 : : }
573 : :
574 : : // Getter for direct access to the type unique_ptr
575 : 0 : std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
576 : :
577 : : protected:
578 : : /* Use covariance to implement clone function as returning this object rather
579 : : * than base */
580 : 994 : RawPointerType *clone_type_no_bounds_impl () const override
581 : : {
582 : 994 : return new RawPointerType (*this);
583 : : }
584 : 0 : RawPointerType *reconstruct_impl () const override
585 : : {
586 : 0 : return new RawPointerType (pointer_type, type->reconstruct (), locus);
587 : : }
588 : : };
589 : :
590 : : // A type pointing to memory owned by another value
591 : : class ReferenceType : public TypeNoBounds
592 : : {
593 : : // bool has_lifetime; // TODO: handle in lifetime or something?
594 : : tl::optional<Lifetime> lifetime;
595 : :
596 : : bool has_mut;
597 : : std::unique_ptr<TypeNoBounds> type;
598 : : location_t locus;
599 : :
600 : : public:
601 : : // Returns whether the reference is mutable or immutable.
602 : 0 : bool is_mut () const { return has_mut; }
603 : :
604 : : // Returns whether the reference has a lifetime.
605 : 536 : bool has_lifetime () const { return lifetime.has_value (); }
606 : :
607 : : // Constructor
608 : 4463 : ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
609 : : location_t locus,
610 : : tl::optional<Lifetime> lifetime = Lifetime::elided ())
611 : 13389 : : lifetime (std::move (lifetime)), has_mut (is_mut),
612 : 4463 : type (std::move (type_no_bounds)), locus (locus)
613 : : {}
614 : :
615 : : // Copy constructor with custom clone method
616 : 3899 : ReferenceType (ReferenceType const &other)
617 : 11697 : : lifetime (other.lifetime), has_mut (other.has_mut),
618 : 3899 : type (other.type->clone_type_no_bounds ()), locus (other.locus)
619 : 3899 : {}
620 : :
621 : : // Operator overload assignment operator to custom clone the unique pointer
622 : : ReferenceType &operator= (ReferenceType const &other)
623 : : {
624 : : lifetime = other.lifetime;
625 : : has_mut = other.has_mut;
626 : : type = other.type->clone_type_no_bounds ();
627 : : locus = other.locus;
628 : :
629 : : return *this;
630 : : }
631 : :
632 : : // move constructors
633 : : ReferenceType (ReferenceType &&other) = default;
634 : : ReferenceType &operator= (ReferenceType &&other) = default;
635 : :
636 : : std::string as_string () const override;
637 : :
638 : 6443 : location_t get_locus () const override final { return locus; }
639 : :
640 : : void accept_vis (ASTVisitor &vis) override;
641 : :
642 : : // TODO: would a "vis_type" be better?
643 : 36166 : TypeNoBounds &get_type_referenced ()
644 : : {
645 : 36166 : rust_assert (type != nullptr);
646 : 36166 : return *type;
647 : : }
648 : :
649 : 4880 : bool get_has_mut () const { return has_mut; }
650 : :
651 : 95749 : Lifetime &get_lifetime () { return lifetime.value (); }
652 : 0 : const Lifetime &get_lifetime () const { return lifetime.value (); }
653 : :
654 : 95213 : TypeNoBounds &get_base_type () { return *type; }
655 : :
656 : : // Getter for direct access to the type unique_ptr
657 : 14 : std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
658 : :
659 : : protected:
660 : : /* Use covariance to implement clone function as returning this object rather
661 : : * than base */
662 : 3899 : ReferenceType *clone_type_no_bounds_impl () const override
663 : : {
664 : 3899 : return new ReferenceType (*this);
665 : : }
666 : 0 : ReferenceType *reconstruct_impl () const override
667 : : {
668 : 0 : return new ReferenceType (has_mut, type->reconstruct (), locus,
669 : : // TODO: Improve this - it's ugly!
670 : 0 : has_lifetime () ? tl::make_optional<Lifetime> (
671 : 0 : lifetime->get_lifetime_type (),
672 : 0 : lifetime->get_lifetime_name (),
673 : 0 : lifetime->get_locus ())
674 : 0 : : tl::nullopt);
675 : : }
676 : : };
677 : :
678 : : // A fixed-size sequence of elements of a specified type
679 : : class ArrayType : public TypeNoBounds
680 : : {
681 : : std::unique_ptr<Type> elem_type;
682 : : AnonConst size;
683 : : location_t locus;
684 : :
685 : : public:
686 : : // Constructor requires pointers for polymorphism
687 : 598 : ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
688 : 598 : : elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
689 : 598 : {}
690 : :
691 : : // Copy constructor requires deep copies of both unique pointers
692 : 1612 : ArrayType (ArrayType const &other)
693 : 1612 : : elem_type (other.elem_type->clone_type ()), size (other.size),
694 : 1612 : locus (other.locus)
695 : 1612 : {}
696 : :
697 : : // Overload assignment operator to deep copy pointers
698 : : ArrayType &operator= (ArrayType const &other)
699 : : {
700 : : elem_type = other.elem_type->clone_type ();
701 : : size = other.size;
702 : : locus = other.locus;
703 : : return *this;
704 : : }
705 : :
706 : : // move constructors
707 : : ArrayType (ArrayType &&other) = default;
708 : : ArrayType &operator= (ArrayType &&other) = default;
709 : :
710 : : std::string as_string () const override;
711 : :
712 : 611 : location_t get_locus () const override final { return locus; }
713 : :
714 : : void accept_vis (ASTVisitor &vis) override;
715 : :
716 : : // TODO: would a "vis_type" be better?
717 : 17524 : Type &get_elem_type ()
718 : : {
719 : 17524 : rust_assert (elem_type != nullptr);
720 : 17524 : return *elem_type;
721 : : }
722 : :
723 : : // TODO: would a "vis_expr" be better?
724 : 16928 : AnonConst &get_size_expr ()
725 : : {
726 : : // rust_assert (size != nullptr);
727 : :
728 : 16928 : return size;
729 : : }
730 : :
731 : 343 : std::unique_ptr<Type> &get_element_type () { return elem_type; }
732 : :
733 : : protected:
734 : : /* Use covariance to implement clone function as returning this object rather
735 : : * than base */
736 : 1612 : ArrayType *clone_type_no_bounds_impl () const override
737 : : {
738 : 1612 : return new ArrayType (*this);
739 : : }
740 : 0 : ArrayType *reconstruct_impl () const override
741 : : {
742 : 0 : return new ArrayType (elem_type->reconstruct (),
743 : 0 : size /* FIXME: This should be `reconstruct_expr()` */,
744 : 0 : locus);
745 : : }
746 : : };
747 : :
748 : : /* A dynamically-sized type representing a "view" into a sequence of elements of
749 : : * a type */
750 : : class SliceType : public TypeNoBounds
751 : : {
752 : : std::unique_ptr<Type> elem_type;
753 : : location_t locus;
754 : :
755 : : public:
756 : : // Constructor requires pointer for polymorphism
757 : 832 : SliceType (std::unique_ptr<Type> type, location_t locus)
758 : 832 : : elem_type (std::move (type)), locus (locus)
759 : : {}
760 : :
761 : : // Copy constructor requires deep copy of Type smart pointer
762 : 361 : SliceType (SliceType const &other)
763 : 361 : : elem_type (other.elem_type->clone_type ()), locus (other.locus)
764 : 361 : {}
765 : :
766 : : // Overload assignment operator to deep copy
767 : : SliceType &operator= (SliceType const &other)
768 : : {
769 : : elem_type = other.elem_type->clone_type ();
770 : : locus = other.locus;
771 : :
772 : : return *this;
773 : : }
774 : :
775 : : // move constructors
776 : : SliceType (SliceType &&other) = default;
777 : : SliceType &operator= (SliceType &&other) = default;
778 : :
779 : : std::string as_string () const override;
780 : :
781 : 1351 : location_t get_locus () const override final { return locus; }
782 : :
783 : : void accept_vis (ASTVisitor &vis) override;
784 : :
785 : : // TODO: would a "vis_type" be better?
786 : 19559 : Type &get_elem_type ()
787 : : {
788 : 19559 : rust_assert (elem_type != nullptr);
789 : 19559 : return *elem_type;
790 : : }
791 : :
792 : : // Getter for direct access to the elem_type unique_ptr
793 : 0 : std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
794 : :
795 : : protected:
796 : : /* Use covariance to implement clone function as returning this object
797 : : * rather than base */
798 : 361 : SliceType *clone_type_no_bounds_impl () const override
799 : : {
800 : 361 : return new SliceType (*this);
801 : : }
802 : 0 : SliceType *reconstruct_impl () const override
803 : : {
804 : 0 : return new SliceType (elem_type->reconstruct (), locus);
805 : : }
806 : : };
807 : :
808 : : /* Type used in generic arguments to explicitly request type inference (wildcard
809 : : * pattern) */
810 : 136 : class InferredType : public TypeNoBounds
811 : : {
812 : : location_t locus;
813 : :
814 : : // e.g. Vec<_> = whatever
815 : : protected:
816 : : /* Use covariance to implement clone function as returning this object
817 : : * rather than base */
818 : 136 : InferredType *clone_type_no_bounds_impl () const override
819 : : {
820 : : // This goes through the copy constructor
821 : 136 : return new InferredType (*this);
822 : : }
823 : :
824 : 0 : InferredType *reconstruct_impl () const override
825 : : {
826 : : // This goes through the base constructor which calls the base
827 : : // TypeNoBounds constructor, which allocates a new NodeId
828 : 0 : return new InferredType (locus);
829 : : }
830 : :
831 : : public:
832 : 208 : InferredType (location_t locus) : locus (locus) {}
833 : :
834 : : std::string as_string () const override;
835 : :
836 : 268 : location_t get_locus () const override final { return locus; }
837 : :
838 : : void accept_vis (ASTVisitor &vis) override;
839 : : };
840 : :
841 : : class QualifiedPathInType; // definition moved to "rust-path.h"
842 : :
843 : : // A possibly named param used in a BaseFunctionType
844 : : struct MaybeNamedParam
845 : : {
846 : : public:
847 : : enum ParamKind
848 : : {
849 : : UNNAMED,
850 : : IDENTIFIER,
851 : : WILDCARD
852 : : };
853 : :
854 : : private:
855 : : std::vector<Attribute> outer_attrs;
856 : :
857 : : std::unique_ptr<Type> param_type;
858 : :
859 : : ParamKind param_kind;
860 : : Identifier name; // technically, can be an identifier or '_'
861 : :
862 : : location_t locus;
863 : :
864 : : public:
865 : 46 : MaybeNamedParam (Identifier name, ParamKind param_kind,
866 : : std::unique_ptr<Type> param_type,
867 : : std::vector<Attribute> outer_attrs, location_t locus)
868 : 46 : : outer_attrs (std::move (outer_attrs)),
869 : 46 : param_type (std::move (param_type)), param_kind (param_kind),
870 : 46 : name (std::move (name)), locus (locus)
871 : 46 : {}
872 : :
873 : : // Copy constructor with clone
874 : 8 : MaybeNamedParam (MaybeNamedParam const &other)
875 : 8 : : outer_attrs (other.outer_attrs), param_kind (other.param_kind),
876 : 8 : name (other.name), locus (other.locus)
877 : : {
878 : : // guard to prevent null dereference
879 : 8 : if (other.param_type != nullptr)
880 : 8 : param_type = other.param_type->clone_type ();
881 : 8 : }
882 : :
883 : 59 : ~MaybeNamedParam () = default;
884 : :
885 : : // Overloaded assignment operator with clone
886 : : MaybeNamedParam &operator= (MaybeNamedParam const &other)
887 : : {
888 : : outer_attrs = other.outer_attrs;
889 : : name = other.name;
890 : : param_kind = other.param_kind;
891 : : locus = other.locus;
892 : :
893 : : // guard to prevent null dereference
894 : : if (other.param_type != nullptr)
895 : : param_type = other.param_type->clone_type ();
896 : : else
897 : : param_type = nullptr;
898 : :
899 : : return *this;
900 : : }
901 : :
902 : : // move constructors
903 : 51 : MaybeNamedParam (MaybeNamedParam &&other) = default;
904 : 0 : MaybeNamedParam &operator= (MaybeNamedParam &&other) = default;
905 : :
906 : : std::string as_string () const;
907 : :
908 : : // Returns whether the param is in an error state.
909 : 46 : bool is_error () const { return param_type == nullptr; }
910 : :
911 : : // Creates an error state param.
912 : 0 : static MaybeNamedParam create_error ()
913 : : {
914 : 0 : return MaybeNamedParam ({""}, UNNAMED, nullptr, {}, UNDEF_LOCATION);
915 : : }
916 : :
917 : 44 : location_t get_locus () const { return locus; }
918 : :
919 : : // TODO: this mutable getter seems really dodgy. Think up better way.
920 : 874 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
921 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
922 : :
923 : : // TODO: would a "vis_type" be better?
924 : 918 : Type &get_type ()
925 : : {
926 : 918 : rust_assert (param_type != nullptr);
927 : 918 : return *param_type;
928 : : }
929 : :
930 : 92 : std::unique_ptr<Type> &get_type_ptr ()
931 : : {
932 : 92 : rust_assert (param_type != nullptr);
933 : 92 : return param_type;
934 : : }
935 : :
936 : 44 : ParamKind get_param_kind () const { return param_kind; }
937 : :
938 : 44 : Identifier get_name () const { return name; }
939 : : };
940 : :
941 : : /* A function pointer type - can be created via coercion from function items and
942 : : * non-capturing closures. */
943 : : class BareFunctionType : public TypeNoBounds
944 : : {
945 : : // bool has_for_lifetimes;
946 : : // ForLifetimes for_lifetimes;
947 : : std::vector<LifetimeParam> for_lifetimes; // inlined version
948 : :
949 : : FunctionQualifiers function_qualifiers;
950 : : std::vector<MaybeNamedParam> params;
951 : : bool _is_variadic;
952 : : std::vector<Attribute> variadic_attrs;
953 : :
954 : : // bool has_return_type;
955 : : // BareFunctionReturnType return_type;
956 : : std::unique_ptr<TypeNoBounds> return_type; // inlined version
957 : :
958 : : location_t locus;
959 : :
960 : : public:
961 : : // Whether a return type is defined with the function.
962 : 1020 : bool has_return_type () const { return return_type != nullptr; }
963 : :
964 : : // Whether the function has ForLifetimes.
965 : 2 : bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
966 : :
967 : 732 : std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
968 : :
969 : 688 : bool is_variadic () const { return _is_variadic; }
970 : :
971 : 0 : std::vector<Attribute> &get_variadic_attr () { return variadic_attrs; };
972 : : const std::vector<Attribute> &get_variadic_attr () const
973 : : {
974 : : return variadic_attrs;
975 : : };
976 : :
977 : 47 : BareFunctionType (std::vector<LifetimeParam> lifetime_params,
978 : : FunctionQualifiers qualifiers,
979 : : std::vector<MaybeNamedParam> named_params, bool is_variadic,
980 : : std::vector<Attribute> variadic_attrs,
981 : : std::unique_ptr<TypeNoBounds> type, location_t locus)
982 : 94 : : for_lifetimes (std::move (lifetime_params)),
983 : 47 : function_qualifiers (std::move (qualifiers)),
984 : 47 : params (std::move (named_params)), _is_variadic (is_variadic),
985 : 47 : variadic_attrs (std::move (variadic_attrs)),
986 : 47 : return_type (std::move (type)), locus (locus)
987 : : {
988 : 47 : if (!variadic_attrs.empty ())
989 : 47 : is_variadic = true;
990 : 47 : }
991 : :
992 : : // Copy constructor with clone
993 : 10 : BareFunctionType (BareFunctionType const &other)
994 : 20 : : for_lifetimes (other.for_lifetimes),
995 : 10 : function_qualifiers (other.function_qualifiers), params (other.params),
996 : 10 : _is_variadic (other._is_variadic), variadic_attrs (other.variadic_attrs),
997 : 20 : locus (other.locus)
998 : : {
999 : : // guard to prevent null dereference
1000 : 10 : if (other.return_type != nullptr)
1001 : 5 : return_type = other.return_type->clone_type_no_bounds ();
1002 : 10 : }
1003 : :
1004 : : // Overload assignment operator to deep copy
1005 : : BareFunctionType &operator= (BareFunctionType const &other)
1006 : : {
1007 : : for_lifetimes = other.for_lifetimes;
1008 : : function_qualifiers = other.function_qualifiers;
1009 : : params = other.params;
1010 : : _is_variadic = other._is_variadic;
1011 : : variadic_attrs = other.variadic_attrs;
1012 : : locus = other.locus;
1013 : :
1014 : : // guard to prevent null dereference
1015 : : if (other.return_type != nullptr)
1016 : : return_type = other.return_type->clone_type_no_bounds ();
1017 : : else
1018 : : return_type = nullptr;
1019 : :
1020 : : return *this;
1021 : : }
1022 : :
1023 : : // move constructors
1024 : : BareFunctionType (BareFunctionType &&other) = default;
1025 : : BareFunctionType &operator= (BareFunctionType &&other) = default;
1026 : :
1027 : : std::string as_string () const override;
1028 : :
1029 : 48 : location_t get_locus () const override final { return locus; }
1030 : :
1031 : : void accept_vis (ASTVisitor &vis) override;
1032 : :
1033 : : // TODO: this mutable getter seems kinda dodgy
1034 : 1020 : std::vector<MaybeNamedParam> &get_function_params () { return params; }
1035 : : const std::vector<MaybeNamedParam> &get_function_params () const
1036 : : {
1037 : : return params;
1038 : : }
1039 : :
1040 : : // TODO: would a "vis_type" be better?
1041 : 776 : TypeNoBounds &get_return_type ()
1042 : : {
1043 : 776 : rust_assert (has_return_type ());
1044 : 776 : return *return_type;
1045 : : }
1046 : :
1047 : 734 : FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
1048 : :
1049 : 0 : BareFunctionType *reconstruct_impl () const override
1050 : : {
1051 : 0 : return new BareFunctionType (
1052 : 0 : for_lifetimes, function_qualifiers, params,
1053 : : /* FIXME: Should params be reconstruct() as well? */
1054 : 0 : _is_variadic, variadic_attrs, return_type->reconstruct (), locus);
1055 : : }
1056 : :
1057 : : protected:
1058 : : /* Use covariance to implement clone function as returning this object
1059 : : * rather than base */
1060 : 10 : BareFunctionType *clone_type_no_bounds_impl () const override
1061 : : {
1062 : 10 : return new BareFunctionType (*this);
1063 : : }
1064 : : };
1065 : :
1066 : : // Forward decl - defined in rust-macro.h
1067 : : class MacroInvocation;
1068 : :
1069 : : /* TODO: possible types
1070 : : * struct type?
1071 : : * "enum" (tagged union) type?
1072 : : * C-like union type?
1073 : : * function item type?
1074 : : * closure expression types?
1075 : : * primitive types (bool, int, float, char, str (the slice))
1076 : : * Although supposedly TypePaths are used to reference these types
1077 : : * (including primitives) */
1078 : :
1079 : : /* FIXME: Incomplete spec references:
1080 : : * anonymous type parameters, aka "impl Trait in argument position" - impl
1081 : : * then trait bounds abstract return types, aka "impl Trait in return
1082 : : * position" - impl then trait bounds */
1083 : : } // namespace AST
1084 : : } // namespace Rust
1085 : :
1086 : : #endif
|