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