Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #ifndef RUST_AST_PATH_H
20 : : #define RUST_AST_PATH_H
21 : : /* "Path" (identifier within namespaces, essentially) handling. Required include
22 : : * for virtually all AST-related functionality. */
23 : :
24 : : #include "optional.h"
25 : : #include "rust-ast.h"
26 : : #include "rust-hir-map.h"
27 : : #include "rust-mapping-common.h"
28 : : #include "rust-system.h"
29 : : #include "system.h"
30 : :
31 : : namespace Rust {
32 : : namespace AST {
33 : :
34 : : // The "identifier" (not generic args) aspect of each path expression segment
35 : 1723316 : class PathIdentSegment
36 : : {
37 : : std::string segment_name;
38 : : location_t locus;
39 : :
40 : : // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
41 : : public:
42 : 639621 : PathIdentSegment (std::string segment_name, location_t locus)
43 : 635279 : : segment_name (std::move (segment_name)), locus (locus)
44 : : {}
45 : :
46 : : // Creates an error PathIdentSegment.
47 : 215 : static PathIdentSegment create_error ()
48 : : {
49 : 215 : return PathIdentSegment ("", UNDEF_LOCATION);
50 : : }
51 : :
52 : : // Returns whether PathIdentSegment is in an error state.
53 : 597882 : bool is_error () const { return segment_name.empty (); }
54 : :
55 : 772132 : std::string as_string () const { return segment_name; }
56 : :
57 : 5200 : location_t get_locus () const { return locus; }
58 : :
59 : 31850 : bool is_super_path_seg () const
60 : : {
61 : 63700 : return as_string ().compare ("super") == 0;
62 : : }
63 : 47079 : bool is_crate_path_seg () const
64 : : {
65 : 94158 : return as_string ().compare ("crate") == 0;
66 : : }
67 : 707584 : bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
68 : 110156 : bool is_big_self_seg () const { return as_string ().compare ("Self") == 0; }
69 : : };
70 : :
71 : : // A binding of an identifier to a type used in generic arguments in paths
72 : : struct GenericArgsBinding
73 : : {
74 : : private:
75 : : Identifier identifier;
76 : : std::unique_ptr<Type> type;
77 : : location_t locus;
78 : :
79 : : public:
80 : : // Returns whether binding is in an error state.
81 : 331 : bool is_error () const
82 : : {
83 : 331 : return type == nullptr;
84 : : // and also identifier is empty, but cheaper computation
85 : : }
86 : :
87 : : // Creates an error state generic args binding.
88 : 0 : static GenericArgsBinding create_error ()
89 : : {
90 : 0 : return GenericArgsBinding ({""}, nullptr);
91 : : }
92 : :
93 : : // Pointer type for type in constructor to enable polymorphism
94 : 331 : GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
95 : : location_t locus = UNDEF_LOCATION)
96 : 331 : : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
97 : : {}
98 : :
99 : : // Copy constructor has to deep copy the type as it is a unique pointer
100 : 445 : GenericArgsBinding (GenericArgsBinding const &other)
101 : 445 : : identifier (other.identifier), locus (other.locus)
102 : : {
103 : : // guard to protect from null pointer dereference
104 : 445 : if (other.type != nullptr)
105 : 445 : type = other.type->clone_type ();
106 : 445 : }
107 : :
108 : : // default destructor
109 : 784 : ~GenericArgsBinding () = default;
110 : :
111 : : // Overload assignment operator to deep copy the pointed-to type
112 : : GenericArgsBinding &operator= (GenericArgsBinding const &other)
113 : : {
114 : : identifier = other.identifier;
115 : : locus = other.locus;
116 : :
117 : : // guard to protect from null pointer dereference
118 : : if (other.type != nullptr)
119 : : type = other.type->clone_type ();
120 : : else
121 : : type = nullptr;
122 : :
123 : : return *this;
124 : : }
125 : :
126 : : // move constructors
127 : 339 : GenericArgsBinding (GenericArgsBinding &&other) = default;
128 : : GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
129 : :
130 : : std::string as_string () const;
131 : :
132 : : // TODO: is this better? Or is a "vis_pattern" better?
133 : 35540 : Type &get_type ()
134 : : {
135 : 35540 : rust_assert (type != nullptr);
136 : 35540 : return *type;
137 : : }
138 : :
139 : 9363 : std::unique_ptr<Type> &get_type_ptr ()
140 : : {
141 : 9363 : rust_assert (type != nullptr);
142 : 9363 : return type;
143 : : }
144 : :
145 : 79 : location_t get_locus () const { return locus; }
146 : :
147 : 79 : Identifier get_identifier () const { return identifier; }
148 : : };
149 : :
150 : : /* Class representing a const generic application */
151 : : class GenericArg
152 : : {
153 : : public:
154 : : /**
155 : : * const generic arguments cannot always be differentiated with generic type
156 : : * arguments during parsing, e.g:
157 : : * ```rust
158 : : * let a: Foo<N>;
159 : : * ```
160 : : *
161 : : * Is N a type? A constant defined elsewhere? The parser cannot know, and must
162 : : * not draw any conclusions. We must wait until later passes of the compiler
163 : : * to decide whether this refers to a constant item or a type.
164 : : *
165 : : * On the other hand, simple expressions like literals or block expressions
166 : : * will always be constant expressions: There is no ambiguity at all.
167 : : */
168 : : enum class Kind
169 : : {
170 : : Const, // A const value
171 : : Type, // A type argument (not discernable during parsing)
172 : : Either, // Either a type or a const value, cleared up during resolving
173 : : };
174 : :
175 : 141 : static GenericArg create_const (std::unique_ptr<Expr> expression)
176 : : {
177 : 141 : auto locus = expression->get_locus ();
178 : 141 : return GenericArg (std::move (expression), nullptr, {""}, Kind::Const,
179 : 282 : locus);
180 : : }
181 : :
182 : 8334 : static GenericArg create_type (std::unique_ptr<Type> type)
183 : : {
184 : 8334 : auto locus = type->get_locus ();
185 : 25002 : return GenericArg (nullptr, std::move (type), {""}, Kind::Type, locus);
186 : : }
187 : :
188 : 13557 : static GenericArg create_ambiguous (Identifier path, location_t locus)
189 : : {
190 : 27114 : return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
191 : : }
192 : :
193 : 59162 : GenericArg (const GenericArg &other)
194 : 59162 : : path (other.path), kind (other.kind), locus (other.locus)
195 : : {
196 : 59162 : if (other.expression)
197 : 19 : expression = other.expression->clone_expr ();
198 : 59162 : if (other.type)
199 : 21242 : type = other.type->clone_type ();
200 : 59162 : }
201 : :
202 : : GenericArg operator= (const GenericArg &other)
203 : : {
204 : : kind = other.kind;
205 : : path = other.path;
206 : : locus = other.locus;
207 : :
208 : : if (other.expression)
209 : : expression = other.expression->clone_expr ();
210 : : if (other.type)
211 : : type = other.type->clone_type ();
212 : :
213 : : return *this;
214 : : }
215 : :
216 : 39760 : GenericArg (GenericArg &&other) = default;
217 : 2340 : GenericArg &operator= (GenericArg &&other) = default;
218 : :
219 : 2797413 : Kind get_kind () const { return kind; }
220 : 0 : location_t get_locus () const { return locus; }
221 : :
222 : 1055084 : void accept_vis (AST::ASTVisitor &visitor)
223 : : {
224 : 1055084 : switch (get_kind ())
225 : : {
226 : 1201 : case Kind::Const:
227 : 1201 : get_expression ().accept_vis (visitor);
228 : 1201 : break;
229 : 337309 : case Kind::Type:
230 : 337309 : get_type ().accept_vis (visitor);
231 : 337309 : break;
232 : : case Kind::Either:
233 : : break;
234 : : }
235 : 1055084 : }
236 : :
237 : 1726 : Expr &get_expression ()
238 : : {
239 : 1726 : rust_assert (kind == Kind::Const);
240 : :
241 : 1726 : return *expression;
242 : : }
243 : :
244 : 138 : std::unique_ptr<Expr> &get_expression_ptr ()
245 : : {
246 : 138 : rust_assert (kind == Kind::Const);
247 : :
248 : 138 : return expression;
249 : : }
250 : :
251 : 694142 : Type &get_type ()
252 : : {
253 : 694142 : rust_assert (kind == Kind::Type);
254 : :
255 : 694142 : return *type;
256 : : }
257 : :
258 : 153841 : std::unique_ptr<Type> &get_type_ptr ()
259 : : {
260 : 153841 : rust_assert (kind == Kind::Type);
261 : :
262 : 153841 : return type;
263 : : }
264 : :
265 : 4678 : const std::string get_path () const
266 : : {
267 : 4678 : rust_assert (kind == Kind::Either);
268 : :
269 : 4678 : return path.as_string ();
270 : : }
271 : :
272 : 0 : std::string as_string () const
273 : : {
274 : 0 : switch (get_kind ())
275 : : {
276 : 0 : case Kind::Either:
277 : 0 : return "Ambiguous: " + path.as_string ();
278 : 0 : case Kind::Const:
279 : 0 : return "Const: { " + expression->as_string () + " }";
280 : 0 : case Kind::Type:
281 : 0 : return "Type: " + type->as_string ();
282 : : }
283 : :
284 : 0 : return "";
285 : : }
286 : :
287 : : /**
288 : : * Disambiguate an ambiguous generic argument to a const generic argument,
289 : : * unequivocally
290 : : */
291 : : GenericArg disambiguate_to_const () const;
292 : :
293 : : /**
294 : : * Disambiguate an ambiguous generic argument to a type argument,
295 : : * unequivocally
296 : : */
297 : : GenericArg disambiguate_to_type () const;
298 : :
299 : : private:
300 : 22032 : GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
301 : : Identifier path, Kind kind, location_t locus)
302 : 15960 : : expression (std::move (expression)), type (std::move (type)),
303 : 22032 : path (std::move (path)), kind (kind), locus (locus)
304 : : {}
305 : :
306 : : /**
307 : : * Expression associated with a `Clear` const generic application
308 : : * A null pointer here is allowed in the case that the const argument is
309 : : * ambiguous.
310 : : */
311 : : std::unique_ptr<Expr> expression;
312 : :
313 : : /**
314 : : * If the argument ends up being a type argument instead. A null pointer will
315 : : * be present here until the resolving phase.
316 : : */
317 : : std::unique_ptr<Type> type;
318 : :
319 : : /**
320 : : * Optional path which cannot be differentiated between a constant item and
321 : : * a type. Only used for ambiguous const generic arguments, otherwise
322 : : * empty.
323 : : */
324 : : Identifier path;
325 : :
326 : : /* Which kind of const generic application are we dealing with */
327 : : Kind kind;
328 : :
329 : : location_t locus;
330 : : };
331 : :
332 : : /**
333 : : * Representation of const generic parameters
334 : : */
335 : : class ConstGenericParam : public GenericParam
336 : : {
337 : : /* Name of the parameter */
338 : : Identifier name;
339 : :
340 : : /* Mandatory type of the const parameter - a null pointer is an error */
341 : : std::unique_ptr<AST::Type> type;
342 : :
343 : : /**
344 : : * Default value for the const generic parameter
345 : : */
346 : : tl::optional<GenericArg> default_value;
347 : :
348 : : AST::AttrVec outer_attrs;
349 : : location_t locus;
350 : :
351 : : public:
352 : 176 : ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
353 : : tl::optional<GenericArg> default_value,
354 : : AST::AttrVec outer_attrs, location_t locus)
355 : 176 : : name (name), type (std::move (type)),
356 : 176 : default_value (std::move (default_value)), outer_attrs (outer_attrs),
357 : 176 : locus (locus)
358 : 176 : {}
359 : :
360 : 0 : ConstGenericParam (const ConstGenericParam &other)
361 : 0 : : GenericParam (), name (other.name), type (other.type->clone_type ()),
362 : 0 : default_value (other.default_value), outer_attrs (other.outer_attrs),
363 : 0 : locus (other.locus)
364 : 0 : {}
365 : :
366 : 9907 : bool has_type () const { return type != nullptr; }
367 : 10073 : bool has_default_value () const { return default_value.has_value (); }
368 : :
369 : 2991 : const Identifier &get_name () const { return name; }
370 : :
371 : 9918 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
372 : :
373 : 9735 : AST::Type &get_type ()
374 : : {
375 : 9735 : rust_assert (has_type ());
376 : :
377 : 9735 : return *type;
378 : : }
379 : :
380 : 172 : std::unique_ptr<AST::Type> &get_type_ptr ()
381 : : {
382 : 172 : rust_assert (has_type ());
383 : :
384 : 172 : return type;
385 : : }
386 : :
387 : 248 : GenericArg &get_default_value_unchecked ()
388 : : {
389 : 248 : rust_assert (has_default_value ());
390 : :
391 : 248 : return default_value.value ();
392 : : }
393 : :
394 : 0 : const GenericArg &get_default_value_unchecked () const
395 : : {
396 : 0 : rust_assert (has_default_value ());
397 : :
398 : 0 : return default_value.value ();
399 : : }
400 : :
401 : 5 : tl::optional<GenericArg> &get_default_value () { return default_value; }
402 : :
403 : : const tl::optional<GenericArg> &get_default_value () const
404 : : {
405 : : return default_value;
406 : : }
407 : :
408 : : std::string as_string () const override;
409 : :
410 : : void accept_vis (ASTVisitor &vis) override;
411 : :
412 : 3165 : location_t get_locus () const override final { return locus; }
413 : :
414 : 518 : Kind get_kind () const override final { return Kind::Const; }
415 : :
416 : : protected:
417 : : /* Use covariance to implement clone function as returning this object rather
418 : : * than base */
419 : 0 : ConstGenericParam *clone_generic_param_impl () const override
420 : : {
421 : 0 : return new ConstGenericParam (*this);
422 : : }
423 : : };
424 : :
425 : : // Generic arguments allowed in each path expression segment - inline?
426 : : struct GenericArgs
427 : : {
428 : : std::vector<Lifetime> lifetime_args;
429 : : std::vector<GenericArg> generic_args;
430 : : std::vector<GenericArgsBinding> binding_args;
431 : : location_t locus;
432 : :
433 : : public:
434 : : // Returns true if there are any generic arguments
435 : 29477299 : bool has_generic_args () const
436 : : {
437 : 29211601 : return !(lifetime_args.empty () && generic_args.empty ()
438 : 26536947 : && binding_args.empty ());
439 : : }
440 : :
441 : 436584 : GenericArgs (std::vector<Lifetime> lifetime_args,
442 : : std::vector<GenericArg> generic_args,
443 : : std::vector<GenericArgsBinding> binding_args,
444 : : location_t locus = UNDEF_LOCATION)
445 : 436584 : : lifetime_args (std::move (lifetime_args)),
446 : 436584 : generic_args (std::move (generic_args)),
447 : 436584 : binding_args (std::move (binding_args)), locus (locus)
448 : 436584 : {}
449 : :
450 : : // copy constructor with vector clone
451 : 540874 : GenericArgs (GenericArgs const &other)
452 : 540874 : : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
453 : 540874 : locus (other.locus)
454 : : {
455 : 540874 : generic_args.clear ();
456 : 540874 : generic_args.reserve (other.generic_args.size ());
457 : 599388 : for (const auto &arg : other.generic_args)
458 : 58514 : generic_args.emplace_back (arg);
459 : 540874 : }
460 : :
461 : 1737600 : ~GenericArgs () = default;
462 : :
463 : : // overloaded assignment operator to vector clone
464 : : GenericArgs &operator= (GenericArgs const &other)
465 : : {
466 : : lifetime_args = other.lifetime_args;
467 : : binding_args = other.binding_args;
468 : : locus = other.locus;
469 : :
470 : : generic_args.clear ();
471 : : generic_args.reserve (other.generic_args.size ());
472 : : for (const auto &arg : other.generic_args)
473 : : generic_args.emplace_back (arg);
474 : :
475 : : return *this;
476 : : }
477 : :
478 : : // move constructors
479 : 921992 : GenericArgs (GenericArgs &&other) = default;
480 : : GenericArgs &operator= (GenericArgs &&other) = default;
481 : :
482 : : // Creates an empty GenericArgs (no arguments)
483 : 415740 : static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
484 : :
485 : : std::string as_string () const;
486 : :
487 : 2880740 : std::vector<GenericArg> &get_generic_args () { return generic_args; }
488 : :
489 : 2880751 : std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
490 : :
491 : : const std::vector<GenericArgsBinding> &get_binding_args () const
492 : : {
493 : : return binding_args;
494 : : }
495 : :
496 : 1057664 : std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
497 : :
498 : : const std::vector<Lifetime> &get_lifetime_args () const
499 : : {
500 : : return lifetime_args;
501 : : };
502 : :
503 : 3662 : location_t get_locus () const { return locus; }
504 : : };
505 : :
506 : : /* A segment of a path in expression, including an identifier aspect and maybe
507 : : * generic args */
508 : 1113497 : class PathExprSegment
509 : : { // or should this extend PathIdentSegment?
510 : : private:
511 : : PathIdentSegment segment_name;
512 : : GenericArgs generic_args;
513 : : location_t locus;
514 : : NodeId node_id;
515 : :
516 : : public:
517 : : // Returns true if there are any generic arguments
518 : 41275641 : bool has_generic_args () const { return generic_args.has_generic_args (); }
519 : :
520 : : // Constructor for segment (from IdentSegment and GenericArgs)
521 : 417121 : PathExprSegment (PathIdentSegment segment_name, location_t locus,
522 : : GenericArgs generic_args = GenericArgs::create_empty ())
523 : 417121 : : segment_name (std::move (segment_name)),
524 : 417121 : generic_args (std::move (generic_args)), locus (locus),
525 : 417121 : node_id (Analysis::Mappings::get ().get_next_node_id ())
526 : 417121 : {}
527 : :
528 : : /* Constructor for segment with generic arguments (from segment name and all
529 : : * args) */
530 : : PathExprSegment (std::string segment_name, location_t locus,
531 : : std::vector<Lifetime> lifetime_args = {},
532 : : std::vector<GenericArg> generic_args = {},
533 : : std::vector<GenericArgsBinding> binding_args = {})
534 : : : segment_name (PathIdentSegment (std::move (segment_name), locus)),
535 : : generic_args (GenericArgs (std::move (lifetime_args),
536 : : std::move (generic_args),
537 : : std::move (binding_args))),
538 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
539 : : {}
540 : :
541 : : // Returns whether path expression segment is in an error state.
542 : 464313 : bool is_error () const { return segment_name.is_error (); }
543 : :
544 : : // Creates an error-state path expression segment.
545 : 2 : static PathExprSegment create_error ()
546 : : {
547 : 2 : return PathExprSegment (PathIdentSegment::create_error (), UNDEF_LOCATION);
548 : : }
549 : :
550 : : std::string as_string () const;
551 : :
552 : 88933 : location_t get_locus () const { return locus; }
553 : :
554 : : // TODO: is this better? Or is a "vis_pattern" better?
555 : 105171 : GenericArgs &get_generic_args ()
556 : : {
557 : 105171 : rust_assert (has_generic_args ());
558 : 105171 : return generic_args;
559 : : }
560 : :
561 : 12465033 : PathIdentSegment &get_ident_segment () { return segment_name; }
562 : 351931 : const PathIdentSegment &get_ident_segment () const { return segment_name; }
563 : :
564 : 72732 : NodeId get_node_id () const { return node_id; }
565 : :
566 : : bool is_super_path_seg () const
567 : : {
568 : : return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
569 : : }
570 : :
571 : : bool is_crate_path_seg () const
572 : : {
573 : : return !has_generic_args () && get_ident_segment ().is_crate_path_seg ();
574 : : }
575 : :
576 : 298112 : bool is_lower_self_seg () const
577 : : {
578 : 595718 : return !has_generic_args () && get_ident_segment ().is_lower_self_seg ();
579 : : }
580 : : };
581 : :
582 : : // AST node representing a pattern that involves a "path" - abstract base
583 : : // class
584 : : class Path : public Pattern
585 : : {
586 : : public:
587 : : enum class Kind
588 : : {
589 : : LangItem,
590 : : Regular,
591 : : };
592 : :
593 : 367613 : Path (std::vector<PathExprSegment> segments)
594 : 367613 : : segments (std::move (segments)), lang_item (tl::nullopt),
595 : 367613 : kind (Kind::Regular)
596 : : {}
597 : :
598 : 1728 : Path (LangItem::Kind lang_item)
599 : 1728 : : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
600 : 1728 : {}
601 : :
602 : : // Returns whether path has segments.
603 : 98023 : bool has_segments () const
604 : : {
605 : 98023 : rust_assert (kind == Kind::Regular);
606 : 98023 : return !segments.empty ();
607 : : }
608 : :
609 : : /* Converts path segments to their equivalent SimplePath segments if
610 : : * possible, and creates a SimplePath from them. */
611 : : SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
612 : :
613 : : /* Returns whether the path is a single segment (excluding qualified path
614 : : * initial as segment). */
615 : 518846 : bool is_single_segment () const
616 : : {
617 : 518846 : rust_assert (kind == Kind::Regular);
618 : 518846 : return segments.size () == 1;
619 : : }
620 : :
621 : : std::string as_string () const override;
622 : :
623 : 13959603 : bool is_lang_item () const { return kind == Kind::LangItem; }
624 : :
625 : : // TODO: this seems kinda dodgy
626 : 14392485 : std::vector<PathExprSegment> &get_segments ()
627 : : {
628 : 14392485 : rust_assert (kind == Kind::Regular);
629 : 14392485 : return segments;
630 : : }
631 : 24118 : const std::vector<PathExprSegment> &get_segments () const
632 : : {
633 : 24118 : rust_assert (kind == Kind::Regular);
634 : 24118 : return segments;
635 : : }
636 : :
637 : 352 : LangItem::Kind get_lang_item () const
638 : : {
639 : 352 : rust_assert (kind == Kind::LangItem);
640 : 352 : return *lang_item;
641 : : }
642 : :
643 : 0 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
644 : : Path::Kind get_path_kind () { return kind; }
645 : :
646 : : protected:
647 : : std::vector<PathExprSegment> segments;
648 : : tl::optional<LangItem::Kind> lang_item;
649 : :
650 : : Path::Kind kind;
651 : : };
652 : :
653 : : /* AST node representing a path-in-expression pattern (path that allows
654 : : * generic arguments) */
655 : : class PathInExpression : public Path, public ExprWithoutBlock
656 : : {
657 : : std::vector<Attribute> outer_attrs;
658 : : bool has_opening_scope_resolution;
659 : : location_t locus;
660 : : NodeId _node_id;
661 : :
662 : : bool marked_for_strip;
663 : :
664 : : public:
665 : : std::string as_string () const override;
666 : :
667 : : // Constructor
668 : 367399 : PathInExpression (std::vector<PathExprSegment> path_segments,
669 : : std::vector<Attribute> outer_attrs, location_t locus,
670 : : bool has_opening_scope_resolution = false)
671 : 734798 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
672 : 367399 : has_opening_scope_resolution (has_opening_scope_resolution),
673 : 367399 : locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
674 : 367399 : marked_for_strip (false)
675 : 367399 : {}
676 : :
677 : 1728 : PathInExpression (LangItem::Kind lang_item,
678 : : std::vector<Attribute> outer_attrs, location_t locus)
679 : 3456 : : Path (lang_item), outer_attrs (std::move (outer_attrs)),
680 : 1728 : has_opening_scope_resolution (false), locus (locus),
681 : 1728 : _node_id (Analysis::Mappings::get ().get_next_node_id ()),
682 : 1728 : marked_for_strip (false)
683 : 1728 : {}
684 : :
685 : : // Creates an error state path in expression.
686 : 2 : static PathInExpression create_error ()
687 : : {
688 : 2 : return PathInExpression (std::vector<PathExprSegment> (), {},
689 : 4 : UNDEF_LOCATION);
690 : : }
691 : :
692 : : // Returns whether path in expression is in an error state.
693 : 45478 : bool is_error () const { return !has_segments (); }
694 : :
695 : : /* Converts PathInExpression to SimplePath if possible (i.e. no generic
696 : : * arguments). Otherwise returns an empty SimplePath. */
697 : 52545 : SimplePath as_simple_path () const
698 : : {
699 : : /* delegate to parent class as can't access segments. however,
700 : : * QualifiedPathInExpression conversion to simple path wouldn't make
701 : : * sense, so the method in the parent class should be protected, not
702 : : * public. Have to pass in opening scope resolution as parent class has no
703 : : * access to it.
704 : : */
705 : 52545 : return convert_to_simple_path (has_opening_scope_resolution);
706 : : }
707 : :
708 : 271208 : location_t get_locus () const override final { return locus; }
709 : :
710 : : void accept_vis (ASTVisitor &vis) override;
711 : :
712 : 0 : void mark_for_strip () override { marked_for_strip = true; }
713 : 5743868 : bool is_marked_for_strip () const override { return marked_for_strip; }
714 : :
715 : 49338 : bool opening_scope_resolution () const
716 : : {
717 : 49338 : return has_opening_scope_resolution;
718 : : }
719 : :
720 : 465611 : NodeId get_node_id () const override { return _node_id; }
721 : :
722 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
723 : 17538059 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
724 : :
725 : 25388 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
726 : : {
727 : 25388 : outer_attrs = std::move (new_attrs);
728 : 0 : }
729 : :
730 : : PathExprSegment &get_final_segment () { return get_segments ().back (); }
731 : : const PathExprSegment &get_final_segment () const
732 : : {
733 : : return get_segments ().back ();
734 : : }
735 : :
736 : 93778 : Expr::Kind get_expr_kind () const override
737 : : {
738 : 93778 : return Expr::Kind::PathInExpression;
739 : : }
740 : :
741 : : protected:
742 : : /* Use covariance to implement clone function as returning this object
743 : : * rather than base */
744 : 439 : PathInExpression *clone_pattern_impl () const final override
745 : : {
746 : 439 : return clone_path_in_expression_impl ();
747 : : }
748 : :
749 : : /* Use covariance to implement clone function as returning this object
750 : : * rather than base */
751 : 0 : PathInExpression *clone_expr_without_block_impl () const final override
752 : : {
753 : 0 : return clone_path_in_expression_impl ();
754 : : }
755 : :
756 : 325153 : /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
757 : : {
758 : 325153 : return new PathInExpression (*this);
759 : : }
760 : : };
761 : :
762 : : /* Base class for segments used in type paths - not abstract (represents an
763 : : * ident-only segment) */
764 : : class TypePathSegment
765 : : {
766 : : public:
767 : : enum SegmentType
768 : : {
769 : : REG,
770 : : GENERIC,
771 : : FUNCTION
772 : : };
773 : :
774 : : private:
775 : : tl::optional<LangItem::Kind> lang_item;
776 : : tl::optional<PathIdentSegment> ident_segment;
777 : : location_t locus;
778 : :
779 : : protected:
780 : : /* This is protected because it is only really used by derived classes, not
781 : : * the base. */
782 : : bool has_separating_scope_resolution;
783 : : NodeId node_id;
784 : :
785 : : public:
786 : : // Clone function implementation - not pure virtual as overrided by
787 : : // subclasses
788 : 217553 : virtual TypePathSegment *clone_type_path_segment_impl () const
789 : : {
790 : 217553 : return new TypePathSegment (*this);
791 : : }
792 : 171 : virtual TypePathSegment *reconstruct_impl () const
793 : : {
794 : 342 : return new TypePathSegment (lang_item, ident_segment,
795 : 171 : has_separating_scope_resolution, locus);
796 : : }
797 : :
798 : : public:
799 : 458561 : virtual ~TypePathSegment () {}
800 : :
801 : 91 : virtual SegmentType get_type () const { return SegmentType::REG; }
802 : :
803 : : // Unique pointer custom clone function
804 : 258479 : std::unique_ptr<TypePathSegment> clone_type_path_segment () const
805 : : {
806 : 258479 : return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
807 : : }
808 : : // Unique pointer custom reconstruct function
809 : 0 : std::unique_ptr<TypePathSegment> reconstruct () const
810 : : {
811 : 0 : return reconstruct_base (this);
812 : : }
813 : :
814 : 213560 : TypePathSegment (PathIdentSegment ident_segment,
815 : : bool has_separating_scope_resolution, location_t locus)
816 : 427120 : : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
817 : 213560 : locus (locus),
818 : 213560 : has_separating_scope_resolution (has_separating_scope_resolution),
819 : 213560 : node_id (Analysis::Mappings::get ().get_next_node_id ())
820 : 213560 : {}
821 : :
822 : 1475 : TypePathSegment (LangItem::Kind lang_item, location_t locus)
823 : 1475 : : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
824 : 1475 : has_separating_scope_resolution (false),
825 : 1475 : node_id (Analysis::Mappings::get ().get_next_node_id ())
826 : 1475 : {}
827 : :
828 : 8745 : TypePathSegment (std::string segment_name,
829 : : bool has_separating_scope_resolution, location_t locus)
830 : 8745 : : lang_item (tl::nullopt),
831 : 8745 : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
832 : 8745 : locus (locus),
833 : 8745 : has_separating_scope_resolution (has_separating_scope_resolution),
834 : 17490 : node_id (Analysis::Mappings::get ().get_next_node_id ())
835 : 8745 : {}
836 : :
837 : : // General constructor
838 : 171 : TypePathSegment (tl::optional<LangItem::Kind> lang_item,
839 : : tl::optional<PathIdentSegment> ident_segment,
840 : : bool has_separating_scope_resolution, location_t locus)
841 : 342 : : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
842 : 171 : has_separating_scope_resolution (has_separating_scope_resolution),
843 : 171 : node_id (Analysis::Mappings::get ().get_next_node_id ())
844 : 171 : {}
845 : :
846 : 271872 : TypePathSegment (TypePathSegment const &other)
847 : 543744 : : lang_item (other.lang_item), ident_segment (other.ident_segment),
848 : 271872 : locus (other.locus),
849 : 271872 : has_separating_scope_resolution (other.has_separating_scope_resolution),
850 : 271872 : node_id (other.node_id)
851 : 271872 : {}
852 : :
853 : : TypePathSegment &operator= (TypePathSegment const &other)
854 : : {
855 : : ident_segment = other.ident_segment;
856 : : lang_item = other.lang_item;
857 : : locus = other.locus;
858 : : has_separating_scope_resolution = other.has_separating_scope_resolution;
859 : : node_id = other.node_id;
860 : :
861 : : return *this;
862 : : }
863 : :
864 : : TypePathSegment (TypePathSegment &&other) = default;
865 : : TypePathSegment &operator= (TypePathSegment &&other) = default;
866 : :
867 : 994 : virtual std::string as_string () const
868 : : {
869 : 994 : if (lang_item.has_value ())
870 : 0 : return LangItem::PrettyString (*lang_item);
871 : :
872 : 994 : return ident_segment->as_string ();
873 : : }
874 : :
875 : : /* Returns whether the type path segment is in an error state. May be
876 : : * virtual in future. */
877 : 520 : bool is_error () const
878 : : {
879 : 520 : rust_assert (ident_segment);
880 : 520 : return ident_segment->is_error ();
881 : : }
882 : :
883 : : /* Returns whether segment is identifier only (as opposed to generic args or
884 : : * function). Overridden in derived classes with other segments. */
885 : 497 : virtual bool is_ident_only () const { return true; }
886 : :
887 : 358395 : bool is_lang_item () const { return lang_item.has_value (); }
888 : :
889 : 3563 : location_t get_locus () const { return locus; }
890 : :
891 : : // not pure virtual as class not abstract
892 : : virtual void accept_vis (ASTVisitor &vis);
893 : :
894 : 55192 : bool get_separating_scope_resolution () const
895 : : {
896 : 55192 : return has_separating_scope_resolution;
897 : : }
898 : :
899 : 249339 : PathIdentSegment &get_ident_segment ()
900 : : {
901 : 249339 : rust_assert (!is_lang_item ());
902 : 249339 : return *ident_segment;
903 : : };
904 : :
905 : 18 : const PathIdentSegment &get_ident_segment () const
906 : : {
907 : 18 : rust_assert (!is_lang_item ());
908 : 18 : return *ident_segment;
909 : : };
910 : :
911 : 1168 : LangItem::Kind get_lang_item () const
912 : : {
913 : 1168 : rust_assert (is_lang_item ());
914 : 1168 : return *lang_item;
915 : : }
916 : :
917 : 111294 : NodeId get_node_id () const { return node_id; }
918 : :
919 : : bool is_crate_path_seg () const
920 : : {
921 : : return get_ident_segment ().is_crate_path_seg ();
922 : : }
923 : : bool is_super_path_seg () const
924 : : {
925 : : return get_ident_segment ().is_super_path_seg ();
926 : : }
927 : : bool is_big_self_seg () const
928 : : {
929 : : return get_ident_segment ().is_big_self_seg ();
930 : : }
931 : : bool is_lower_self_seg () const
932 : : {
933 : : return get_ident_segment ().is_lower_self_seg ();
934 : : }
935 : : };
936 : :
937 : : // Segment used in type path with generic args
938 : : class TypePathSegmentGeneric : public TypePathSegment
939 : : {
940 : : GenericArgs generic_args;
941 : :
942 : : public:
943 : 11 : SegmentType get_type () const override { return SegmentType::GENERIC; }
944 : :
945 : 5279567 : bool has_generic_args () const { return generic_args.has_generic_args (); }
946 : :
947 : 0 : bool is_ident_only () const override { return false; }
948 : :
949 : : // Constructor with PathIdentSegment and GenericArgs
950 : 18264 : TypePathSegmentGeneric (PathIdentSegment ident_segment,
951 : : bool has_separating_scope_resolution,
952 : : GenericArgs generic_args, location_t locus)
953 : 18264 : : TypePathSegment (std::move (ident_segment),
954 : : has_separating_scope_resolution, locus),
955 : 18264 : generic_args (std::move (generic_args))
956 : 18264 : {}
957 : :
958 : 107 : TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
959 : : location_t locus)
960 : 107 : : TypePathSegment (lang_item, locus),
961 : 107 : generic_args (std::move (generic_args))
962 : 107 : {}
963 : :
964 : : // Constructor from segment name and all args
965 : : TypePathSegmentGeneric (std::string segment_name,
966 : : bool has_separating_scope_resolution,
967 : : std::vector<Lifetime> lifetime_args,
968 : : std::vector<GenericArg> generic_args,
969 : : std::vector<GenericArgsBinding> binding_args,
970 : : location_t locus)
971 : : : TypePathSegment (std::move (segment_name),
972 : : has_separating_scope_resolution, locus),
973 : : generic_args (GenericArgs (std::move (lifetime_args),
974 : : std::move (generic_args),
975 : : std::move (binding_args)))
976 : : {}
977 : :
978 : : // Copy constructor with vector clone
979 : 54203 : TypePathSegmentGeneric (TypePathSegmentGeneric const &other)
980 : 54203 : : TypePathSegment (other), generic_args (other.generic_args)
981 : 54203 : {}
982 : :
983 : : // Overloaded assignment operator with vector clone
984 : : TypePathSegmentGeneric &operator= (TypePathSegmentGeneric const &other)
985 : : {
986 : : generic_args = other.generic_args;
987 : :
988 : : return *this;
989 : : }
990 : :
991 : : // move constructors
992 : : TypePathSegmentGeneric (TypePathSegmentGeneric &&other) = default;
993 : : TypePathSegmentGeneric &operator= (TypePathSegmentGeneric &&other) = default;
994 : :
995 : : std::string as_string () const override;
996 : :
997 : : void accept_vis (ASTVisitor &vis) override;
998 : :
999 : : // TODO: is this better? Or is a "vis_pattern" better?
1000 : 2775332 : GenericArgs &get_generic_args () { return generic_args; }
1001 : :
1002 : : // Use covariance to override base class method
1003 : 54203 : TypePathSegmentGeneric *clone_type_path_segment_impl () const override
1004 : : {
1005 : 54203 : return new TypePathSegmentGeneric (*this);
1006 : : }
1007 : : };
1008 : :
1009 : : // A function as represented in a type path
1010 : : struct TypePathFunction
1011 : : {
1012 : : private:
1013 : : // TODO: remove
1014 : : /*bool has_inputs;
1015 : : TypePathFnInputs inputs;*/
1016 : : // inlined from TypePathFnInputs
1017 : : std::vector<std::unique_ptr<Type>> inputs;
1018 : :
1019 : : // bool has_type;
1020 : : std::unique_ptr<Type> return_type;
1021 : :
1022 : : // FIXME: think of better way to mark as invalid than taking up storage
1023 : : bool is_invalid;
1024 : :
1025 : : location_t locus;
1026 : :
1027 : : protected:
1028 : : // Constructor only used to create invalid type path functions.
1029 : 0 : TypePathFunction (bool is_invalid, location_t locus)
1030 : 0 : : is_invalid (is_invalid), locus (locus)
1031 : : {}
1032 : :
1033 : : public:
1034 : : // Returns whether the return type of the function has been specified.
1035 : 138152 : bool has_return_type () const { return return_type != nullptr; }
1036 : :
1037 : : // Returns whether the function has inputs.
1038 : 5 : bool has_inputs () const { return !inputs.empty (); }
1039 : :
1040 : : // Returns whether function is in an error state.
1041 : 138688 : bool is_error () const { return is_invalid; }
1042 : :
1043 : : // Creates an error state function.
1044 : 0 : static TypePathFunction create_error ()
1045 : : {
1046 : 0 : return TypePathFunction (true, UNDEF_LOCATION);
1047 : : }
1048 : :
1049 : : // Constructor
1050 : 536 : TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus,
1051 : : std::unique_ptr<Type> type = nullptr)
1052 : 536 : : inputs (std::move (inputs)), return_type (std::move (type)),
1053 : 536 : is_invalid (false), locus (locus)
1054 : : {}
1055 : :
1056 : : // Copy constructor with clone
1057 : 116 : TypePathFunction (TypePathFunction const &other)
1058 : 116 : : is_invalid (other.is_invalid)
1059 : : {
1060 : : // guard to protect from null pointer dereference
1061 : 116 : if (other.return_type != nullptr)
1062 : 108 : return_type = other.return_type->clone_type ();
1063 : :
1064 : 116 : inputs.reserve (other.inputs.size ());
1065 : 260 : for (const auto &e : other.inputs)
1066 : 144 : inputs.push_back (e->clone_type ());
1067 : 116 : }
1068 : :
1069 : 536 : ~TypePathFunction () = default;
1070 : :
1071 : : // Overloaded assignment operator to clone type
1072 : : TypePathFunction &operator= (TypePathFunction const &other)
1073 : : {
1074 : : is_invalid = other.is_invalid;
1075 : :
1076 : : // guard to protect from null pointer dereference
1077 : : if (other.return_type != nullptr)
1078 : : return_type = other.return_type->clone_type ();
1079 : : else
1080 : : return_type = nullptr;
1081 : :
1082 : : inputs.reserve (other.inputs.size ());
1083 : : for (const auto &e : other.inputs)
1084 : : inputs.push_back (e->clone_type ());
1085 : :
1086 : : return *this;
1087 : : }
1088 : :
1089 : : // move constructors
1090 : 536 : TypePathFunction (TypePathFunction &&other) = default;
1091 : : TypePathFunction &operator= (TypePathFunction &&other) = default;
1092 : :
1093 : : std::string as_string () const;
1094 : :
1095 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1096 : : const std::vector<std::unique_ptr<Type>> &get_params () const
1097 : : {
1098 : : return inputs;
1099 : : }
1100 : 138152 : std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
1101 : :
1102 : : // TODO: is this better? Or is a "vis_pattern" better?
1103 : 115970 : Type &get_return_type ()
1104 : : {
1105 : 115970 : rust_assert (has_return_type ());
1106 : 115970 : return *return_type;
1107 : : }
1108 : :
1109 : 17589 : std::unique_ptr<Type> &get_return_type_ptr ()
1110 : : {
1111 : 17589 : rust_assert (has_return_type ());
1112 : 17589 : return return_type;
1113 : : }
1114 : :
1115 : 5 : location_t get_locus () const { return locus; }
1116 : : };
1117 : :
1118 : : // Segment used in type path with a function argument
1119 : : class TypePathSegmentFunction : public TypePathSegment
1120 : : {
1121 : : TypePathFunction function_path;
1122 : :
1123 : : public:
1124 : 27 : SegmentType get_type () const override { return SegmentType::FUNCTION; }
1125 : :
1126 : : // Constructor with PathIdentSegment and TypePathFn
1127 : 536 : TypePathSegmentFunction (PathIdentSegment ident_segment,
1128 : : bool has_separating_scope_resolution,
1129 : : TypePathFunction function_path, location_t locus)
1130 : 536 : : TypePathSegment (std::move (ident_segment),
1131 : : has_separating_scope_resolution, locus),
1132 : 536 : function_path (std::move (function_path))
1133 : 536 : {}
1134 : :
1135 : : // Constructor with segment name and TypePathFn
1136 : : TypePathSegmentFunction (std::string segment_name,
1137 : : bool has_separating_scope_resolution,
1138 : : TypePathFunction function_path, location_t locus)
1139 : : : TypePathSegment (std::move (segment_name),
1140 : : has_separating_scope_resolution, locus),
1141 : : function_path (std::move (function_path))
1142 : : {}
1143 : :
1144 : : std::string as_string () const override;
1145 : :
1146 : 5 : bool is_ident_only () const override { return false; }
1147 : :
1148 : : void accept_vis (ASTVisitor &vis) override;
1149 : :
1150 : : // TODO: is this better? Or is a "vis_pattern" better?
1151 : 138152 : TypePathFunction &get_type_path_function ()
1152 : : {
1153 : 138152 : rust_assert (!function_path.is_error ());
1154 : 138152 : return function_path;
1155 : : }
1156 : :
1157 : : // Use covariance to override base class method
1158 : 116 : TypePathSegmentFunction *clone_type_path_segment_impl () const override
1159 : : {
1160 : 116 : return new TypePathSegmentFunction (*this);
1161 : : }
1162 : : };
1163 : :
1164 : 181741 : class TypePath : public TypeNoBounds
1165 : : {
1166 : : bool has_opening_scope_resolution;
1167 : : std::vector<std::unique_ptr<TypePathSegment>> segments;
1168 : : location_t locus;
1169 : :
1170 : : protected:
1171 : : /* Use covariance to implement clone function as returning this object
1172 : : * rather than base */
1173 : 176128 : TypePath *clone_type_no_bounds_impl () const override
1174 : : {
1175 : 176128 : return new TypePath (*this);
1176 : : }
1177 : 171 : TypePath *reconstruct_impl () const override
1178 : : {
1179 : 855 : return new TypePath (reconstruct_vec (segments), locus,
1180 : 342 : has_opening_scope_resolution);
1181 : : }
1182 : :
1183 : : public:
1184 : : /* Returns whether the TypePath has an opening scope resolution operator
1185 : : * (i.e. is global path or crate-relative path, not module-relative) */
1186 : 110522 : bool has_opening_scope_resolution_op () const
1187 : : {
1188 : 110522 : return has_opening_scope_resolution;
1189 : : }
1190 : :
1191 : : // Returns whether the TypePath is in an invalid state.
1192 : 1634772 : bool is_error () const { return segments.empty (); }
1193 : :
1194 : : // Creates an error state TypePath.
1195 : 3951 : static TypePath create_error ()
1196 : : {
1197 : 3951 : return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
1198 : 3951 : UNDEF_LOCATION);
1199 : : }
1200 : :
1201 : : // Constructor
1202 : 217583 : TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
1203 : : location_t locus, bool has_opening_scope_resolution = false)
1204 : 85134 : : TypeNoBounds (),
1205 : 217583 : has_opening_scope_resolution (has_opening_scope_resolution),
1206 : 217583 : segments (std::move (segments)), locus (locus)
1207 : : {}
1208 : :
1209 : 0 : TypePath (LangItem::Kind lang_item,
1210 : : std::vector<std::unique_ptr<TypePathSegment>> segments,
1211 : : location_t locus, bool has_opening_scope_resolution = false)
1212 : 0 : : TypeNoBounds (),
1213 : 0 : has_opening_scope_resolution (has_opening_scope_resolution),
1214 : 0 : segments (std::move (segments)), locus (locus)
1215 : : {}
1216 : :
1217 : : // Copy constructor with vector clone
1218 : 245225 : TypePath (TypePath const &other)
1219 : 490450 : : has_opening_scope_resolution (other.has_opening_scope_resolution),
1220 : 245225 : locus (other.locus)
1221 : : {
1222 : 245225 : node_id = other.node_id;
1223 : 245225 : segments.reserve (other.segments.size ());
1224 : 503704 : for (const auto &e : other.segments)
1225 : 258479 : segments.push_back (e->clone_type_path_segment ());
1226 : 245225 : }
1227 : :
1228 : : // Overloaded assignment operator with clone
1229 : : TypePath &operator= (TypePath const &other)
1230 : : {
1231 : : node_id = other.node_id;
1232 : : has_opening_scope_resolution = other.has_opening_scope_resolution;
1233 : : locus = other.locus;
1234 : :
1235 : : segments.reserve (other.segments.size ());
1236 : : for (const auto &e : other.segments)
1237 : : segments.push_back (e->clone_type_path_segment ());
1238 : :
1239 : : return *this;
1240 : : }
1241 : :
1242 : : // move constructors
1243 : 130086 : TypePath (TypePath &&other) = default;
1244 : 3692 : TypePath &operator= (TypePath &&other) = default;
1245 : :
1246 : : std::string as_string () const override;
1247 : :
1248 : : std::string make_debug_string () const;
1249 : :
1250 : : /* Converts TypePath to SimplePath if possible (i.e. no generic or function
1251 : : * arguments). Otherwise returns an empty SimplePath. */
1252 : : SimplePath as_simple_path () const;
1253 : :
1254 : : // Creates a trait bound with a clone of this type path as its only element.
1255 : : TraitBound *to_trait_bound (bool in_parens) const override;
1256 : :
1257 : 158679 : location_t get_locus () const override final { return locus; }
1258 : 2590622 : NodeId get_node_id () const override { return node_id; }
1259 : :
1260 : 0 : void mark_for_strip () override {}
1261 : 4230147 : bool is_marked_for_strip () const override { return false; }
1262 : :
1263 : : void accept_vis (ASTVisitor &vis) override;
1264 : :
1265 : : // TODO: this seems kinda dodgy
1266 : 3065 : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1267 : : {
1268 : 13669629 : return segments;
1269 : : }
1270 : 54144 : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1271 : : {
1272 : 54162 : return segments;
1273 : : }
1274 : :
1275 : : size_t get_num_segments () const { return segments.size (); }
1276 : : };
1277 : :
1278 : : struct QualifiedPathType
1279 : : {
1280 : : private:
1281 : : std::unique_ptr<Type> type_to_invoke_on;
1282 : : TypePath trait_path;
1283 : : location_t locus;
1284 : : NodeId node_id;
1285 : :
1286 : : public:
1287 : : // Constructor
1288 : 3767 : QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
1289 : : location_t locus = UNDEF_LOCATION,
1290 : : TypePath trait_path = TypePath::create_error ())
1291 : 3767 : : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
1292 : 3767 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1293 : 3767 : {}
1294 : :
1295 : : // Copy constructor uses custom deep copy for Type to preserve polymorphism
1296 : 13840 : QualifiedPathType (QualifiedPathType const &other)
1297 : 13840 : : trait_path (other.trait_path), locus (other.locus)
1298 : : {
1299 : 13840 : node_id = other.node_id;
1300 : : // guard to prevent null dereference
1301 : 13840 : if (other.type_to_invoke_on != nullptr)
1302 : 13840 : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1303 : 13840 : }
1304 : :
1305 : : // default destructor
1306 : 25137 : ~QualifiedPathType () = default;
1307 : :
1308 : : // overload assignment operator to use custom clone method
1309 : : QualifiedPathType &operator= (QualifiedPathType const &other)
1310 : : {
1311 : : node_id = other.node_id;
1312 : : trait_path = other.trait_path;
1313 : : locus = other.locus;
1314 : :
1315 : : // guard to prevent null dereference
1316 : : if (other.type_to_invoke_on != nullptr)
1317 : : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1318 : : else
1319 : : type_to_invoke_on = nullptr;
1320 : :
1321 : : return *this;
1322 : : }
1323 : :
1324 : : // move constructor
1325 : 11247 : QualifiedPathType (QualifiedPathType &&other) = default;
1326 : 0 : QualifiedPathType &operator= (QualifiedPathType &&other) = default;
1327 : :
1328 : : // Returns whether the qualified path type has a rebind as clause.
1329 : 770462 : bool has_as_clause () const { return !trait_path.is_error (); }
1330 : :
1331 : : // Returns whether the qualified path type is in an error state.
1332 : 784600 : bool is_error () const { return type_to_invoke_on == nullptr; }
1333 : :
1334 : : // Creates an error state qualified path type.
1335 : 0 : static QualifiedPathType create_error ()
1336 : : {
1337 : 0 : return QualifiedPathType (nullptr);
1338 : : }
1339 : :
1340 : : std::string as_string () const;
1341 : :
1342 : 593 : location_t get_locus () const { return locus; }
1343 : :
1344 : : // TODO: is this better? Or is a "vis_pattern" better?
1345 : 660027 : Type &get_type ()
1346 : : {
1347 : 660027 : rust_assert (type_to_invoke_on != nullptr);
1348 : 660027 : return *type_to_invoke_on;
1349 : : }
1350 : :
1351 : 110435 : std::unique_ptr<Type> &get_type_ptr ()
1352 : : {
1353 : 110435 : rust_assert (type_to_invoke_on != nullptr);
1354 : 110435 : return type_to_invoke_on;
1355 : : }
1356 : :
1357 : : // TODO: is this better? Or is a "vis_pattern" better?
1358 : 742615 : TypePath &get_as_type_path ()
1359 : : {
1360 : 742615 : rust_assert (has_as_clause ());
1361 : 742615 : return trait_path;
1362 : : }
1363 : :
1364 : 349 : NodeId get_node_id () const { return node_id; }
1365 : : };
1366 : :
1367 : : /* AST node representing a qualified path-in-expression pattern (path that
1368 : : * allows specifying trait functions) */
1369 : : class QualifiedPathInExpression : public Path, public ExprWithoutBlock
1370 : : {
1371 : : std::vector<Attribute> outer_attrs;
1372 : : QualifiedPathType path_type;
1373 : : location_t locus;
1374 : : NodeId _node_id;
1375 : :
1376 : : public:
1377 : : std::string as_string () const override;
1378 : :
1379 : 214 : QualifiedPathInExpression (QualifiedPathType qual_path_type,
1380 : : std::vector<PathExprSegment> path_segments,
1381 : : std::vector<Attribute> outer_attrs,
1382 : : location_t locus)
1383 : 428 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
1384 : 214 : path_type (std::move (qual_path_type)), locus (locus),
1385 : 214 : _node_id (Analysis::Mappings::get ().get_next_node_id ())
1386 : 214 : {}
1387 : :
1388 : : /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1389 : : * elements as params */
1390 : :
1391 : : // Returns whether qualified path in expression is in an error state.
1392 : 10398 : bool is_error () const { return path_type.is_error (); }
1393 : :
1394 : : // Creates an error qualified path in expression.
1395 : 0 : static QualifiedPathInExpression create_error ()
1396 : : {
1397 : 0 : return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
1398 : 0 : {}, UNDEF_LOCATION);
1399 : : }
1400 : :
1401 : 363 : location_t get_locus () const override final { return locus; }
1402 : :
1403 : : void accept_vis (ASTVisitor &vis) override;
1404 : :
1405 : : // Invalid if path_type is error, so base stripping on that.
1406 : 0 : void mark_for_strip () override
1407 : : {
1408 : 0 : path_type = QualifiedPathType::create_error ();
1409 : 0 : }
1410 : 10398 : bool is_marked_for_strip () const override { return is_error (); }
1411 : :
1412 : : // TODO: is this better? Or is a "vis_pattern" better?
1413 : 35982 : QualifiedPathType &get_qualified_path_type ()
1414 : : {
1415 : 35982 : rust_assert (!path_type.is_error ());
1416 : 35982 : return path_type;
1417 : : }
1418 : :
1419 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1420 : 44301 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1421 : :
1422 : 187 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
1423 : : {
1424 : 187 : outer_attrs = std::move (new_attrs);
1425 : 0 : }
1426 : :
1427 : 2058 : NodeId get_node_id () const override { return _node_id; }
1428 : :
1429 : 214 : Expr::Kind get_expr_kind () const override
1430 : : {
1431 : 214 : return Expr::Kind::QualifiedPathInExpression;
1432 : : }
1433 : :
1434 : : protected:
1435 : : /* Use covariance to implement clone function as returning this object
1436 : : * rather than base */
1437 : 0 : QualifiedPathInExpression *clone_pattern_impl () const final override
1438 : : {
1439 : 0 : return clone_qual_path_in_expression_impl ();
1440 : : }
1441 : :
1442 : : /* Use covariance to implement clone function as returning this object
1443 : : * rather than base */
1444 : : QualifiedPathInExpression *
1445 : 0 : clone_expr_without_block_impl () const final override
1446 : : {
1447 : 0 : return clone_qual_path_in_expression_impl ();
1448 : : }
1449 : :
1450 : : /*virtual*/ QualifiedPathInExpression *
1451 : 420 : clone_qual_path_in_expression_impl () const
1452 : : {
1453 : 420 : return new QualifiedPathInExpression (*this);
1454 : : }
1455 : : };
1456 : :
1457 : : /* Represents a qualified path in a type; used for disambiguating trait
1458 : : * function calls */
1459 : : class QualifiedPathInType : public TypeNoBounds
1460 : : {
1461 : : QualifiedPathType path_type;
1462 : : std::unique_ptr<TypePathSegment> associated_segment;
1463 : : std::vector<std::unique_ptr<TypePathSegment>> segments;
1464 : : location_t locus;
1465 : :
1466 : : protected:
1467 : : /* Use covariance to implement clone function as returning this object
1468 : : * rather than base */
1469 : 13393 : QualifiedPathInType *clone_type_no_bounds_impl () const override
1470 : : {
1471 : 13393 : return new QualifiedPathInType (*this);
1472 : : }
1473 : 0 : QualifiedPathInType *reconstruct_impl () const override
1474 : : {
1475 : 0 : return new QualifiedPathInType (path_type,
1476 : 0 : associated_segment->reconstruct (),
1477 : 0 : reconstruct_vec (segments), locus);
1478 : : }
1479 : :
1480 : : public:
1481 : 3553 : QualifiedPathInType (
1482 : : QualifiedPathType qual_path_type,
1483 : : std::unique_ptr<TypePathSegment> associated_segment,
1484 : : std::vector<std::unique_ptr<TypePathSegment>> path_segments,
1485 : : location_t locus)
1486 : 7106 : : path_type (std::move (qual_path_type)),
1487 : 3553 : associated_segment (std::move (associated_segment)),
1488 : 3553 : segments (std::move (path_segments)), locus (locus)
1489 : 3553 : {}
1490 : :
1491 : : // Copy constructor with vector clone
1492 : 13393 : QualifiedPathInType (QualifiedPathInType const &other)
1493 : 13393 : : path_type (other.path_type), locus (other.locus)
1494 : : {
1495 : 13393 : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1496 : 13393 : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1497 : :
1498 : 13393 : segments.reserve (other.segments.size ());
1499 : 13393 : for (const auto &e : other.segments)
1500 : 0 : segments.push_back (e->clone_type_path_segment ());
1501 : 13393 : }
1502 : :
1503 : : // Overloaded assignment operator with vector clone
1504 : : QualifiedPathInType &operator= (QualifiedPathInType const &other)
1505 : : {
1506 : : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1507 : : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1508 : :
1509 : : path_type = other.path_type;
1510 : : locus = other.locus;
1511 : :
1512 : : segments.reserve (other.segments.size ());
1513 : : for (const auto &e : other.segments)
1514 : : segments.push_back (e->clone_type_path_segment ());
1515 : :
1516 : : return *this;
1517 : : }
1518 : :
1519 : : // move constructors
1520 : 3553 : QualifiedPathInType (QualifiedPathInType &&other) = default;
1521 : : QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
1522 : :
1523 : : // Returns whether qualified path in type is in an error state.
1524 : 3553 : bool is_error () const { return path_type.is_error (); }
1525 : :
1526 : : // Creates an error state qualified path in type.
1527 : 0 : static QualifiedPathInType create_error ()
1528 : : {
1529 : 0 : return QualifiedPathInType (
1530 : 0 : QualifiedPathType::create_error (), nullptr,
1531 : 0 : std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
1532 : : }
1533 : :
1534 : : std::string as_string () const override;
1535 : :
1536 : : void accept_vis (ASTVisitor &vis) override;
1537 : :
1538 : : // TODO: is this better? Or is a "vis_pattern" better?
1539 : 735185 : QualifiedPathType &get_qualified_path_type ()
1540 : : {
1541 : 735185 : rust_assert (!path_type.is_error ());
1542 : 735185 : return path_type;
1543 : : }
1544 : :
1545 : : std::unique_ptr<TypePathSegment> &get_associated_segment ()
1546 : : {
1547 : 425506 : return associated_segment;
1548 : : }
1549 : :
1550 : : // TODO: this seems kinda dodgy
1551 : : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1552 : : {
1553 : 528536 : return segments;
1554 : : }
1555 : : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1556 : : {
1557 : : return segments;
1558 : : }
1559 : :
1560 : 257 : location_t get_locus () const override final { return locus; }
1561 : : };
1562 : : } // namespace AST
1563 : : } // namespace Rust
1564 : :
1565 : : #endif
|