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