]>
Commit | Line | Data |
---|---|---|
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 locus; | |
44 | ||
45 | public: | |
46 | // Returns whether trait bound has "for" lifetimes | |
47 | bool has_for_lifetimes () const { return !for_lifetimes.empty (); } | |
48 | ||
49 | std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; } | |
50 | ||
51 | TraitBound (TypePath type_path, Location locus, bool in_parens = false, | |
52 | bool opening_question_mark = false, | |
53 | std::vector<LifetimeParam> for_lifetimes | |
54 | = std::vector<LifetimeParam> ()) | |
55 | : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()), | |
56 | in_parens (in_parens), opening_question_mark (opening_question_mark), | |
57 | for_lifetimes (std::move (for_lifetimes)), | |
58 | type_path (std::move (type_path)), locus (locus) | |
59 | {} | |
60 | ||
61 | TraitBound (NodeId id, TypePath type_path, Location locus, | |
62 | bool in_parens = false, bool opening_question_mark = false, | |
63 | std::vector<LifetimeParam> for_lifetimes | |
64 | = std::vector<LifetimeParam> ()) | |
65 | : TypeParamBound (id), in_parens (in_parens), | |
66 | opening_question_mark (opening_question_mark), | |
67 | for_lifetimes (std::move (for_lifetimes)), | |
68 | type_path (std::move (type_path)), locus (locus) | |
69 | {} | |
70 | ||
71 | std::string as_string () const override; | |
72 | ||
73 | Location 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 | TypePath &get_type_path () { return type_path; } | |
79 | const TypePath &get_type_path () const { return type_path; } | |
80 | ||
81 | bool is_in_parens () const { return in_parens; } | |
82 | 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 | TraitBound *clone_type_param_bound_impl () const override | |
88 | { | |
89 | return new TraitBound (node_id, type_path, locus, in_parens, | |
90 | 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 locus; | |
105 | ||
106 | protected: | |
107 | /* Use covariance to implement clone function as returning this object rather | |
108 | * than base */ | |
109 | ImplTraitType *clone_type_impl () const override | |
110 | { | |
111 | return new ImplTraitType (*this); | |
112 | } | |
113 | ||
114 | public: | |
115 | ImplTraitType ( | |
116 | std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, | |
117 | Location locus) | |
118 | : type_param_bounds (std::move (type_param_bounds)), locus (locus) | |
119 | {} | |
120 | ||
121 | // copy constructor with vector clone | |
122 | ImplTraitType (ImplTraitType const &other) : locus (other.locus) | |
123 | { | |
124 | type_param_bounds.reserve (other.type_param_bounds.size ()); | |
125 | for (const auto &e : other.type_param_bounds) | |
126 | type_param_bounds.push_back (e->clone_type_param_bound ()); | |
127 | } | |
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 | Location get_locus () const override final { return locus; } | |
148 | ||
149 | void accept_vis (ASTVisitor &vis) override; | |
150 | ||
151 | // TODO: mutable getter seems kinda dodgy | |
152 | std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () | |
153 | { | |
154 | 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 locus; | |
169 | ||
170 | protected: | |
171 | /* Use covariance to implement clone function as returning this object rather | |
172 | * than base */ | |
173 | TraitObjectType *clone_type_impl () const override | |
174 | { | |
175 | return new TraitObjectType (*this); | |
176 | } | |
177 | ||
178 | public: | |
179 | TraitObjectType ( | |
180 | std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, | |
181 | Location locus, bool is_dyn_dispatch) | |
182 | : has_dyn (is_dyn_dispatch), | |
183 | type_param_bounds (std::move (type_param_bounds)), locus (locus) | |
184 | {} | |
185 | ||
186 | // copy constructor with vector clone | |
187 | TraitObjectType (TraitObjectType const &other) | |
188 | : has_dyn (other.has_dyn), locus (other.locus) | |
189 | { | |
190 | type_param_bounds.reserve (other.type_param_bounds.size ()); | |
191 | for (const auto &e : other.type_param_bounds) | |
192 | type_param_bounds.push_back (e->clone_type_param_bound ()); | |
193 | } | |
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 | Location get_locus () const override final { return locus; } | |
214 | ||
215 | void accept_vis (ASTVisitor &vis) override; | |
216 | ||
217 | bool is_dyn () const { return has_dyn; } | |
218 | ||
219 | // TODO: mutable getter seems kinda dodgy | |
220 | std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () | |
221 | { | |
222 | 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 locus; | |
236 | ||
237 | protected: | |
238 | /* Use covariance to implement clone function as returning this object rather | |
239 | * than base */ | |
240 | ParenthesisedType *clone_type_no_bounds_impl () const override | |
241 | { | |
242 | return new ParenthesisedType (*this); | |
243 | } | |
244 | ||
245 | public: | |
246 | // Constructor uses Type pointer for polymorphism | |
247 | ParenthesisedType (std::unique_ptr<Type> type_inside_parens, Location locus) | |
248 | : 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 | ParenthesisedType (ParenthesisedType const &other) | |
254 | : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) | |
255 | {} | |
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 | std::string as_string () const override | |
270 | { | |
271 | return "(" + type_in_parens->as_string () + ")"; | |
272 | } | |
273 | ||
274 | // Creates a trait bound (clone of this one's trait bound) - HACK | |
275 | 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 | return type_in_parens->to_trait_bound (true); | |
281 | } | |
282 | ||
283 | Location 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 | std::unique_ptr<Type> &get_type_in_parens () | |
289 | { | |
290 | rust_assert (type_in_parens != nullptr); | |
291 | return type_in_parens; | |
292 | } | |
293 | }; | |
294 | ||
295 | // Impl trait with a single bound? Poor reference material here. | |
296 | class ImplTraitTypeOneBound : public TypeNoBounds | |
297 | { | |
298 | TraitBound trait_bound; | |
299 | Location locus; | |
300 | ||
301 | protected: | |
302 | /* Use covariance to implement clone function as returning this object rather | |
303 | * than base */ | |
304 | ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override | |
305 | { | |
306 | return new ImplTraitTypeOneBound (*this); | |
307 | } | |
308 | ||
309 | public: | |
310 | ImplTraitTypeOneBound (TraitBound trait_bound, Location locus) | |
311 | : trait_bound (std::move (trait_bound)), locus (locus) | |
312 | {} | |
313 | ||
314 | std::string as_string () const override; | |
315 | ||
316 | Location 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 | TraitBound &get_trait_bound () | |
322 | { | |
323 | // TODO: check to ensure invariants are met? | |
324 | 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 locus; | |
335 | ||
336 | protected: | |
337 | /* Use covariance to implement clone function as returning this object rather | |
338 | * than base */ | |
339 | TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override | |
340 | { | |
341 | return new TraitObjectTypeOneBound (*this); | |
342 | } | |
343 | ||
344 | public: | |
345 | TraitObjectTypeOneBound (TraitBound trait_bound, Location locus, | |
346 | bool is_dyn_dispatch = false) | |
347 | : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)), | |
348 | 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 | 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 | return new TraitBound (trait_bound); | |
359 | } | |
360 | ||
361 | Location 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 | TraitBound &get_trait_bound () | |
367 | { | |
368 | // TODO: check to ensure invariants are met? | |
369 | return trait_bound; | |
370 | } | |
371 | ||
372 | 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 locus; | |
383 | ||
384 | public: | |
385 | // Returns whether the tuple type is the unit type, i.e. has no elements. | |
386 | bool is_unit_type () const { return elems.empty (); } | |
387 | ||
388 | TupleType (std::vector<std::unique_ptr<Type> > elems, Location locus) | |
389 | : elems (std::move (elems)), locus (locus) | |
390 | {} | |
391 | ||
392 | // copy constructor with vector clone | |
393 | TupleType (TupleType const &other) : locus (other.locus) | |
394 | { | |
395 | elems.reserve (other.elems.size ()); | |
396 | for (const auto &e : other.elems) | |
397 | elems.push_back (e->clone_type ()); | |
398 | } | |
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 | Location get_locus () const override final { return locus; } | |
419 | ||
420 | void accept_vis (ASTVisitor &vis) override; | |
421 | ||
422 | // TODO: mutable getter seems kinda dodgy | |
423 | 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 | TupleType *clone_type_no_bounds_impl () const override | |
433 | { | |
434 | 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 | class NeverType : public TypeNoBounds | |
442 | { | |
443 | Location locus; | |
444 | ||
445 | protected: | |
446 | /* Use covariance to implement clone function as returning this object rather | |
447 | * than base */ | |
448 | NeverType *clone_type_no_bounds_impl () const override | |
449 | { | |
450 | return new NeverType (*this); | |
451 | } | |
452 | ||
453 | public: | |
454 | NeverType (Location locus) : locus (locus) {} | |
455 | ||
456 | std::string as_string () const override { return "! (never type)"; } | |
457 | ||
458 | Location 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 locus; | |
477 | ||
478 | public: | |
479 | // Returns whether the pointer is mutable or constant. | |
480 | PointerType get_pointer_type () const { return pointer_type; } | |
481 | ||
482 | // Constructor requires pointer for polymorphism reasons | |
483 | RawPointerType (PointerType pointer_type, | |
484 | std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus) | |
485 | : pointer_type (pointer_type), type (std::move (type_no_bounds)), | |
486 | locus (locus) | |
487 | {} | |
488 | ||
489 | // Copy constructor calls custom polymorphic clone function | |
490 | RawPointerType (RawPointerType const &other) | |
491 | : pointer_type (other.pointer_type), | |
492 | type (other.type->clone_type_no_bounds ()), locus (other.locus) | |
493 | {} | |
494 | ||
495 | // overload assignment operator to use custom clone method | |
496 | RawPointerType &operator= (RawPointerType const &other) | |
497 | { | |
498 | pointer_type = other.pointer_type; | |
499 | type = other.type->clone_type_no_bounds (); | |
500 | locus = other.locus; | |
501 | return *this; | |
502 | } | |
503 | ||
504 | // default move semantics | |
505 | RawPointerType (RawPointerType &&other) = default; | |
506 | RawPointerType &operator= (RawPointerType &&other) = default; | |
507 | ||
508 | std::string as_string () const override; | |
509 | ||
510 | Location get_locus () const override final { return locus; } | |
511 | ||
512 | void accept_vis (ASTVisitor &vis) override; | |
513 | ||
514 | // TODO: would a "vis_type" be better? | |
515 | std::unique_ptr<TypeNoBounds> &get_type_pointed_to () | |
516 | { | |
517 | rust_assert (type != nullptr); | |
518 | return type; | |
519 | } | |
520 | ||
521 | protected: | |
522 | /* Use covariance to implement clone function as returning this object rather | |
523 | * than base */ | |
524 | RawPointerType *clone_type_no_bounds_impl () const override | |
525 | { | |
526 | return new RawPointerType (*this); | |
527 | } | |
528 | }; | |
529 | ||
530 | // A type pointing to memory owned by another value | |
531 | class ReferenceType : public TypeNoBounds | |
532 | { | |
533 | // bool has_lifetime; // TODO: handle in lifetime or something? | |
534 | Lifetime lifetime; | |
535 | ||
536 | bool has_mut; | |
537 | std::unique_ptr<TypeNoBounds> type; | |
538 | Location locus; | |
539 | ||
540 | public: | |
541 | // Returns whether the reference is mutable or immutable. | |
542 | bool is_mut () const { return has_mut; } | |
543 | ||
544 | // Returns whether the reference has a lifetime. | |
545 | bool has_lifetime () const { return !lifetime.is_error (); } | |
546 | ||
547 | // Constructor | |
548 | ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds, | |
549 | Location locus, Lifetime lifetime = Lifetime::error ()) | |
550 | : lifetime (std::move (lifetime)), has_mut (is_mut), | |
551 | type (std::move (type_no_bounds)), locus (locus) | |
552 | {} | |
553 | ||
554 | // Copy constructor with custom clone method | |
555 | ReferenceType (ReferenceType const &other) | |
556 | : lifetime (other.lifetime), has_mut (other.has_mut), | |
557 | type (other.type->clone_type_no_bounds ()), locus (other.locus) | |
558 | {} | |
559 | ||
560 | // Operator overload assignment operator to custom clone the unique pointer | |
561 | ReferenceType &operator= (ReferenceType const &other) | |
562 | { | |
563 | lifetime = other.lifetime; | |
564 | has_mut = other.has_mut; | |
565 | type = other.type->clone_type_no_bounds (); | |
566 | locus = other.locus; | |
567 | ||
568 | return *this; | |
569 | } | |
570 | ||
571 | // move constructors | |
572 | ReferenceType (ReferenceType &&other) = default; | |
573 | ReferenceType &operator= (ReferenceType &&other) = default; | |
574 | ||
575 | std::string as_string () const override; | |
576 | ||
577 | Location get_locus () const override final { return locus; } | |
578 | ||
579 | void accept_vis (ASTVisitor &vis) override; | |
580 | ||
581 | // TODO: would a "vis_type" be better? | |
582 | std::unique_ptr<TypeNoBounds> &get_type_referenced () | |
583 | { | |
584 | rust_assert (type != nullptr); | |
585 | return type; | |
586 | } | |
587 | ||
588 | bool get_has_mut () const { return has_mut; } | |
589 | ||
590 | Lifetime &get_lifetime () { return lifetime; } | |
591 | ||
592 | std::unique_ptr<TypeNoBounds> &get_base_type () { return type; } | |
593 | ||
594 | protected: | |
595 | /* Use covariance to implement clone function as returning this object rather | |
596 | * than base */ | |
597 | ReferenceType *clone_type_no_bounds_impl () const override | |
598 | { | |
599 | return new ReferenceType (*this); | |
600 | } | |
601 | }; | |
602 | ||
603 | // A fixed-size sequence of elements of a specified type | |
604 | class ArrayType : public TypeNoBounds | |
605 | { | |
606 | std::unique_ptr<Type> elem_type; | |
607 | std::unique_ptr<Expr> size; | |
608 | Location locus; | |
609 | ||
610 | public: | |
611 | // Constructor requires pointers for polymorphism | |
612 | ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size, | |
613 | Location locus) | |
614 | : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) | |
615 | {} | |
616 | ||
617 | // Copy constructor requires deep copies of both unique pointers | |
618 | ArrayType (ArrayType const &other) | |
619 | : elem_type (other.elem_type->clone_type ()), | |
620 | size (other.size->clone_expr ()), locus (other.locus) | |
621 | {} | |
622 | ||
623 | // Overload assignment operator to deep copy pointers | |
624 | ArrayType &operator= (ArrayType const &other) | |
625 | { | |
626 | elem_type = other.elem_type->clone_type (); | |
627 | size = other.size->clone_expr (); | |
628 | locus = other.locus; | |
629 | return *this; | |
630 | } | |
631 | ||
632 | // move constructors | |
633 | ArrayType (ArrayType &&other) = default; | |
634 | ArrayType &operator= (ArrayType &&other) = default; | |
635 | ||
636 | std::string as_string () const override; | |
637 | ||
638 | Location 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 | std::unique_ptr<Type> &get_elem_type () | |
644 | { | |
645 | rust_assert (elem_type != nullptr); | |
646 | return elem_type; | |
647 | } | |
648 | ||
649 | // TODO: would a "vis_expr" be better? | |
650 | std::unique_ptr<Expr> &get_size_expr () | |
651 | { | |
652 | rust_assert (size != nullptr); | |
653 | return size; | |
654 | } | |
655 | ||
656 | protected: | |
657 | /* Use covariance to implement clone function as returning this object rather | |
658 | * than base */ | |
659 | ArrayType *clone_type_no_bounds_impl () const override | |
660 | { | |
661 | return new ArrayType (*this); | |
662 | } | |
663 | }; | |
664 | ||
665 | /* A dynamically-sized type representing a "view" into a sequence of elements of | |
666 | * a type */ | |
667 | class SliceType : public TypeNoBounds | |
668 | { | |
669 | std::unique_ptr<Type> elem_type; | |
670 | Location locus; | |
671 | ||
672 | public: | |
673 | // Constructor requires pointer for polymorphism | |
674 | SliceType (std::unique_ptr<Type> type, Location locus) | |
675 | : elem_type (std::move (type)), locus (locus) | |
676 | {} | |
677 | ||
678 | // Copy constructor requires deep copy of Type smart pointer | |
679 | SliceType (SliceType const &other) | |
680 | : elem_type (other.elem_type->clone_type ()), locus (other.locus) | |
681 | {} | |
682 | ||
683 | // Overload assignment operator to deep copy | |
684 | SliceType &operator= (SliceType const &other) | |
685 | { | |
686 | elem_type = other.elem_type->clone_type (); | |
687 | locus = other.locus; | |
688 | ||
689 | return *this; | |
690 | } | |
691 | ||
692 | // move constructors | |
693 | SliceType (SliceType &&other) = default; | |
694 | SliceType &operator= (SliceType &&other) = default; | |
695 | ||
696 | std::string as_string () const override; | |
697 | ||
698 | Location get_locus () const override final { return locus; } | |
699 | ||
700 | void accept_vis (ASTVisitor &vis) override; | |
701 | ||
702 | // TODO: would a "vis_type" be better? | |
703 | std::unique_ptr<Type> &get_elem_type () | |
704 | { | |
705 | rust_assert (elem_type != nullptr); | |
706 | return elem_type; | |
707 | } | |
708 | ||
709 | protected: | |
710 | /* Use covariance to implement clone function as returning this object rather | |
711 | * than base */ | |
712 | SliceType *clone_type_no_bounds_impl () const override | |
713 | { | |
714 | return new SliceType (*this); | |
715 | } | |
716 | }; | |
717 | ||
718 | /* Type used in generic arguments to explicitly request type inference (wildcard | |
719 | * pattern) */ | |
720 | class InferredType : public TypeNoBounds | |
721 | { | |
722 | Location locus; | |
723 | ||
724 | // e.g. Vec<_> = whatever | |
725 | protected: | |
726 | /* Use covariance to implement clone function as returning this object rather | |
727 | * than base */ | |
728 | InferredType *clone_type_no_bounds_impl () const override | |
729 | { | |
730 | return new InferredType (*this); | |
731 | } | |
732 | ||
733 | public: | |
734 | InferredType (Location locus) : locus (locus) {} | |
735 | ||
736 | std::string as_string () const override; | |
737 | ||
738 | Location get_locus () const override final { return locus; } | |
739 | ||
740 | void accept_vis (ASTVisitor &vis) override; | |
741 | }; | |
742 | ||
743 | class QualifiedPathInType; // definition moved to "rust-path.h" | |
744 | ||
745 | // A possibly named param used in a BaseFunctionType | |
746 | struct MaybeNamedParam | |
747 | { | |
748 | public: | |
749 | enum ParamKind | |
750 | { | |
751 | UNNAMED, | |
752 | IDENTIFIER, | |
753 | WILDCARD | |
754 | }; | |
755 | ||
756 | private: | |
757 | std::vector<Attribute> outer_attrs; | |
758 | ||
759 | std::unique_ptr<Type> param_type; | |
760 | ||
761 | ParamKind param_kind; | |
762 | Identifier name; // technically, can be an identifier or '_' | |
763 | ||
764 | Location locus; | |
765 | ||
766 | public: | |
767 | MaybeNamedParam (Identifier name, ParamKind param_kind, | |
768 | std::unique_ptr<Type> param_type, | |
769 | std::vector<Attribute> outer_attrs, Location locus) | |
770 | : outer_attrs (std::move (outer_attrs)), | |
771 | param_type (std::move (param_type)), param_kind (param_kind), | |
772 | name (std::move (name)), locus (locus) | |
773 | {} | |
774 | ||
775 | // Copy constructor with clone | |
776 | MaybeNamedParam (MaybeNamedParam const &other) | |
777 | : outer_attrs (other.outer_attrs), param_kind (other.param_kind), | |
778 | name (other.name), locus (other.locus) | |
779 | { | |
780 | // guard to prevent null dereference | |
781 | if (other.param_type != nullptr) | |
782 | param_type = other.param_type->clone_type (); | |
783 | } | |
784 | ||
785 | ~MaybeNamedParam () = default; | |
786 | ||
787 | // Overloaded assignment operator with clone | |
788 | MaybeNamedParam &operator= (MaybeNamedParam const &other) | |
789 | { | |
790 | outer_attrs = other.outer_attrs; | |
791 | name = other.name; | |
792 | param_kind = other.param_kind; | |
793 | locus = other.locus; | |
794 | ||
795 | // guard to prevent null dereference | |
796 | if (other.param_type != nullptr) | |
797 | param_type = other.param_type->clone_type (); | |
798 | else | |
799 | param_type = nullptr; | |
800 | ||
801 | return *this; | |
802 | } | |
803 | ||
804 | // move constructors | |
805 | MaybeNamedParam (MaybeNamedParam &&other) = default; | |
806 | MaybeNamedParam &operator= (MaybeNamedParam &&other) = default; | |
807 | ||
808 | std::string as_string () const; | |
809 | ||
810 | // Returns whether the param is in an error state. | |
811 | bool is_error () const { return param_type == nullptr; } | |
812 | ||
813 | // Creates an error state param. | |
814 | static MaybeNamedParam create_error () | |
815 | { | |
816 | return MaybeNamedParam ("", UNNAMED, nullptr, {}, Location ()); | |
817 | } | |
818 | ||
819 | Location get_locus () const { return locus; } | |
820 | ||
821 | // TODO: this mutable getter seems really dodgy. Think up better way. | |
822 | std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } | |
823 | const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } | |
824 | ||
825 | // TODO: would a "vis_type" be better? | |
826 | std::unique_ptr<Type> &get_type () | |
827 | { | |
828 | rust_assert (param_type != nullptr); | |
829 | return param_type; | |
830 | } | |
831 | ||
832 | ParamKind get_param_kind () const { return param_kind; } | |
833 | ||
834 | Identifier get_name () const { return name; } | |
835 | }; | |
836 | ||
837 | /* A function pointer type - can be created via coercion from function items and | |
838 | * non-capturing closures. */ | |
839 | class BareFunctionType : public TypeNoBounds | |
840 | { | |
841 | // bool has_for_lifetimes; | |
842 | // ForLifetimes for_lifetimes; | |
843 | std::vector<LifetimeParam> for_lifetimes; // inlined version | |
844 | ||
845 | FunctionQualifiers function_qualifiers; | |
846 | std::vector<MaybeNamedParam> params; | |
847 | bool _is_variadic; | |
848 | std::vector<Attribute> variadic_attrs; | |
849 | ||
850 | // bool has_return_type; | |
851 | // BareFunctionReturnType return_type; | |
852 | std::unique_ptr<TypeNoBounds> return_type; // inlined version | |
853 | ||
854 | Location locus; | |
855 | ||
856 | public: | |
857 | // Whether a return type is defined with the function. | |
858 | bool has_return_type () const { return return_type != nullptr; } | |
859 | ||
860 | // Whether the function has ForLifetimes. | |
861 | bool has_for_lifetimes () const { return !for_lifetimes.empty (); } | |
862 | ||
863 | std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; } | |
864 | ||
865 | bool is_variadic () const { return _is_variadic; } | |
866 | ||
867 | std::vector<Attribute> &get_variadic_attr () { return variadic_attrs; }; | |
868 | const std::vector<Attribute> &get_variadic_attr () const | |
869 | { | |
870 | return variadic_attrs; | |
871 | }; | |
872 | ||
873 | BareFunctionType (std::vector<LifetimeParam> lifetime_params, | |
874 | FunctionQualifiers qualifiers, | |
875 | std::vector<MaybeNamedParam> named_params, bool is_variadic, | |
876 | std::vector<Attribute> variadic_attrs, | |
877 | std::unique_ptr<TypeNoBounds> type, Location locus) | |
878 | : for_lifetimes (std::move (lifetime_params)), | |
879 | function_qualifiers (std::move (qualifiers)), | |
880 | params (std::move (named_params)), _is_variadic (is_variadic), | |
881 | variadic_attrs (std::move (variadic_attrs)), | |
882 | return_type (std::move (type)), locus (locus) | |
883 | { | |
884 | if (!variadic_attrs.empty ()) | |
885 | is_variadic = true; | |
886 | } | |
887 | ||
888 | // Copy constructor with clone | |
889 | BareFunctionType (BareFunctionType const &other) | |
890 | : for_lifetimes (other.for_lifetimes), | |
891 | function_qualifiers (other.function_qualifiers), params (other.params), | |
892 | _is_variadic (other._is_variadic), variadic_attrs (other.variadic_attrs), | |
893 | locus (other.locus) | |
894 | { | |
895 | // guard to prevent null dereference | |
896 | if (other.return_type != nullptr) | |
897 | return_type = other.return_type->clone_type_no_bounds (); | |
898 | } | |
899 | ||
900 | // Overload assignment operator to deep copy | |
901 | BareFunctionType &operator= (BareFunctionType const &other) | |
902 | { | |
903 | for_lifetimes = other.for_lifetimes; | |
904 | function_qualifiers = other.function_qualifiers; | |
905 | params = other.params; | |
906 | _is_variadic = other._is_variadic; | |
907 | variadic_attrs = other.variadic_attrs; | |
908 | locus = other.locus; | |
909 | ||
910 | // guard to prevent null dereference | |
911 | if (other.return_type != nullptr) | |
912 | return_type = other.return_type->clone_type_no_bounds (); | |
913 | else | |
914 | return_type = nullptr; | |
915 | ||
916 | return *this; | |
917 | } | |
918 | ||
919 | // move constructors | |
920 | BareFunctionType (BareFunctionType &&other) = default; | |
921 | BareFunctionType &operator= (BareFunctionType &&other) = default; | |
922 | ||
923 | std::string as_string () const override; | |
924 | ||
925 | Location get_locus () const override final { return locus; } | |
926 | ||
927 | void accept_vis (ASTVisitor &vis) override; | |
928 | ||
929 | // TODO: this mutable getter seems kinda dodgy | |
930 | std::vector<MaybeNamedParam> &get_function_params () { return params; } | |
931 | const std::vector<MaybeNamedParam> &get_function_params () const | |
932 | { | |
933 | return params; | |
934 | } | |
935 | ||
936 | // TODO: would a "vis_type" be better? | |
937 | std::unique_ptr<TypeNoBounds> &get_return_type () | |
938 | { | |
939 | rust_assert (has_return_type ()); | |
940 | return return_type; | |
941 | } | |
942 | ||
943 | FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; } | |
944 | ||
945 | protected: | |
946 | /* Use covariance to implement clone function as returning this object rather | |
947 | * than base */ | |
948 | BareFunctionType *clone_type_no_bounds_impl () const override | |
949 | { | |
950 | return new BareFunctionType (*this); | |
951 | } | |
952 | }; | |
953 | ||
954 | // Forward decl - defined in rust-macro.h | |
955 | class MacroInvocation; | |
956 | ||
957 | /* TODO: possible types | |
958 | * struct type? | |
959 | * "enum" (tagged union) type? | |
960 | * C-like union type? | |
961 | * function item type? | |
962 | * closure expression types? | |
963 | * primitive types (bool, int, float, char, str (the slice)) | |
964 | * Although supposedly TypePaths are used to reference these types (including | |
965 | * primitives) */ | |
966 | ||
967 | /* FIXME: Incomplete spec references: | |
968 | * anonymous type parameters, aka "impl Trait in argument position" - impl then | |
969 | * trait bounds abstract return types, aka "impl Trait in return position" - | |
970 | * impl then trait bounds */ | |
971 | } // namespace AST | |
972 | } // namespace Rust | |
973 | ||
974 | #endif |