Line data Source code
1 : // Copyright (C) 2020-2026 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 726424 : 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 145293 : PathIdentSegment (std::string segment_name, location_t locus)
43 145851 : : segment_name (std::move (segment_name)), locus (locus)
44 : {}
45 :
46 : // Creates an error PathIdentSegment.
47 8 : static PathIdentSegment create_error ()
48 : {
49 8 : return PathIdentSegment ("", UNDEF_LOCATION);
50 : }
51 :
52 : // Returns whether PathIdentSegment is in an error state.
53 86896 : bool is_error () const { return segment_name.empty (); }
54 :
55 542835 : std::string as_string () const { return segment_name; }
56 :
57 6168 : location_t get_locus () const { return locus; }
58 :
59 31900 : bool is_super_path_seg () const
60 : {
61 63800 : return as_string ().compare ("super") == 0;
62 : }
63 47138 : bool is_crate_path_seg () const
64 : {
65 94276 : return as_string ().compare ("crate") == 0;
66 : }
67 196508 : bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
68 108052 : 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 73 : bool is_error () const
82 : {
83 73 : 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 73 : GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
95 : location_t locus = UNDEF_LOCATION)
96 73 : : 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 86 : GenericArgsBinding (GenericArgsBinding const &other)
101 86 : : identifier (other.identifier), locus (other.locus)
102 : {
103 : // guard to protect from null pointer dereference
104 86 : if (other.type != nullptr)
105 86 : type = other.type->clone_type ();
106 86 : }
107 :
108 : // default destructor
109 160 : ~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 74 : 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 1225 : Type &get_type ()
134 : {
135 1225 : rust_assert (type != nullptr);
136 1225 : return *type;
137 : }
138 :
139 278 : std::unique_ptr<Type> &get_type_ptr ()
140 : {
141 278 : rust_assert (type != nullptr);
142 278 : return type;
143 : }
144 :
145 104 : location_t get_locus () const { return locus; }
146 :
147 104 : 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 3764 : static GenericArg create_type (std::unique_ptr<Type> type)
183 : {
184 3764 : auto locus = type->get_locus ();
185 11292 : return GenericArg (nullptr, std::move (type), {""}, Kind::Type, locus);
186 : }
187 :
188 2453 : static GenericArg create_ambiguous (Identifier path, location_t locus)
189 : {
190 4906 : return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
191 : }
192 :
193 8679 : GenericArg (const GenericArg &other)
194 8679 : : path (other.path), kind (other.kind), locus (other.locus)
195 : {
196 8679 : if (other.expression)
197 129 : expression = other.expression->clone_expr ();
198 8679 : if (other.type)
199 4919 : type = other.type->clone_type ();
200 8679 : }
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 7994 : GenericArg (GenericArg &&other) = default;
217 2347 : GenericArg &operator= (GenericArg &&other) = default;
218 :
219 82034 : Kind get_kind () const { return kind; }
220 0 : location_t get_locus () const { return locus; }
221 :
222 44560 : void accept_vis (AST::ASTVisitor &visitor)
223 : {
224 44560 : switch (get_kind ())
225 : {
226 1201 : case Kind::Const:
227 1201 : get_expression ().accept_vis (visitor);
228 1201 : break;
229 18674 : case Kind::Type:
230 18674 : get_type ().accept_vis (visitor);
231 18674 : break;
232 : case Kind::Either:
233 : break;
234 : }
235 44560 : }
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 32217 : Type &get_type ()
252 : {
253 32217 : rust_assert (kind == Kind::Type);
254 :
255 32217 : return *type;
256 : }
257 :
258 3842 : std::unique_ptr<Type> &get_type_ptr ()
259 : {
260 3842 : rust_assert (kind == Kind::Type);
261 :
262 3842 : return type;
263 : }
264 :
265 4692 : const std::string get_path () const
266 : {
267 4692 : rust_assert (kind == Kind::Either);
268 :
269 4692 : 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 6358 : GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
301 : Identifier path, Kind kind, location_t locus)
302 4838 : : expression (std::move (expression)), type (std::move (type)),
303 6358 : 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 101 : ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
353 : tl::optional<GenericArg> default_value,
354 : AST::AttrVec outer_attrs, location_t locus)
355 101 : : name (name), type (std::move (type)),
356 101 : default_value (std::move (default_value)), outer_attrs (outer_attrs),
357 101 : locus (locus)
358 101 : {}
359 :
360 97 : ConstGenericParam (const ConstGenericParam &other)
361 97 : : GenericParam (), name (other.name), type (other.type->clone_type ()),
362 97 : default_value (other.default_value), outer_attrs (other.outer_attrs),
363 97 : locus (other.locus)
364 97 : {}
365 :
366 1338 : bool has_type () const { return type != nullptr; }
367 1439 : bool has_default_value () const { return default_value.has_value (); }
368 :
369 291 : const Identifier &get_name () const { return name; }
370 :
371 1349 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
372 :
373 1241 : AST::Type &get_type ()
374 : {
375 1241 : rust_assert (has_type ());
376 :
377 1241 : return *type;
378 : }
379 :
380 97 : std::unique_ptr<AST::Type> &get_type_ptr ()
381 : {
382 97 : rust_assert (has_type ());
383 :
384 97 : 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 0 : 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 465 : location_t get_locus () const override final { return locus; }
413 :
414 303 : 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 97 : ConstGenericParam *clone_generic_param_impl () const override
420 : {
421 97 : 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 908060 : bool has_generic_args () const
436 : {
437 907410 : return !(lifetime_args.empty () && generic_args.empty ()
438 815878 : && binding_args.empty ());
439 : }
440 :
441 89641 : 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 89641 : : lifetime_args (std::move (lifetime_args)),
446 89641 : generic_args (std::move (generic_args)),
447 89641 : binding_args (std::move (binding_args)), locus (locus)
448 89641 : {}
449 :
450 : // copy constructor with vector clone
451 75066 : GenericArgs (GenericArgs const &other)
452 75066 : : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
453 75066 : locus (other.locus)
454 : {
455 75066 : generic_args.clear ();
456 75066 : generic_args.reserve (other.generic_args.size ());
457 83499 : for (const auto &arg : other.generic_args)
458 8433 : generic_args.emplace_back (arg);
459 75066 : }
460 :
461 318384 : ~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 191682 : GenericArgs (GenericArgs &&other) = default;
480 : GenericArgs &operator= (GenericArgs &&other) = default;
481 :
482 : // Creates an empty GenericArgs (no arguments)
483 85400 : static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
484 :
485 : std::string as_string () const;
486 :
487 76149 : std::vector<GenericArg> &get_generic_args () { return generic_args; }
488 :
489 76160 : 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 42576 : 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 3701 : 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 212325 : 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 1304532 : bool has_generic_args () const { return generic_args.has_generic_args (); }
519 :
520 : // Constructor for segment (from IdentSegment and GenericArgs)
521 86306 : PathExprSegment (PathIdentSegment segment_name, location_t locus,
522 : GenericArgs generic_args = GenericArgs::create_empty ())
523 86306 : : segment_name (std::move (segment_name)),
524 86306 : generic_args (std::move (generic_args)), locus (locus),
525 86306 : node_id (Analysis::Mappings::get ().get_next_node_id ())
526 86306 : {}
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 86841 : bool is_error () const { return segment_name.is_error (); }
543 :
544 : // Creates an error-state path expression segment.
545 8 : static PathExprSegment create_error ()
546 : {
547 8 : return PathExprSegment (PathIdentSegment::create_error (), UNDEF_LOCATION);
548 : }
549 :
550 : std::string as_string () const;
551 :
552 38687 : location_t get_locus () const { return locus; }
553 :
554 : // TODO: is this better? Or is a "vis_pattern" better?
555 20212 : GenericArgs &get_generic_args ()
556 : {
557 20212 : rust_assert (has_generic_args ());
558 20212 : return generic_args;
559 : }
560 :
561 484444 : PathIdentSegment &get_ident_segment () { return segment_name; }
562 96409 : const PathIdentSegment &get_ident_segment () const { return segment_name; }
563 :
564 72870 : 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 42273 : bool is_lower_self_seg () const
577 : {
578 84275 : 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 74132 : Path (std::vector<PathExprSegment> segments)
594 74132 : : segments (std::move (segments)), lang_item (tl::nullopt),
595 74132 : kind (Kind::Regular)
596 : {}
597 :
598 144 : Path (LangItem::Kind lang_item)
599 144 : : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
600 144 : {}
601 :
602 : // Returns whether path has segments.
603 8485 : bool has_segments () const
604 : {
605 8485 : rust_assert (kind == Kind::Regular);
606 8485 : 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 96797 : bool is_single_segment () const
616 : {
617 96797 : rust_assert (kind == Kind::Regular);
618 96797 : return segments.size () == 1;
619 : }
620 :
621 : std::string as_string () const override;
622 :
623 530660 : bool is_lang_item () const { return kind == Kind::LangItem; }
624 :
625 : // TODO: this seems kinda dodgy
626 576216 : std::vector<PathExprSegment> &get_segments ()
627 : {
628 576216 : rust_assert (kind == Kind::Regular);
629 576216 : return segments;
630 : }
631 24182 : const std::vector<PathExprSegment> &get_segments () const
632 : {
633 24182 : rust_assert (kind == Kind::Regular);
634 24182 : 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 74018 : PathInExpression (std::vector<PathExprSegment> path_segments,
669 : std::vector<Attribute> outer_attrs, location_t locus,
670 : bool has_opening_scope_resolution = false)
671 148036 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
672 74018 : has_opening_scope_resolution (has_opening_scope_resolution),
673 74018 : locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
674 74018 : marked_for_strip (false)
675 74018 : {}
676 :
677 144 : PathInExpression (LangItem::Kind lang_item,
678 : std::vector<Attribute> outer_attrs, location_t locus)
679 288 : : Path (lang_item), outer_attrs (std::move (outer_attrs)),
680 144 : has_opening_scope_resolution (false), locus (locus),
681 144 : _node_id (Analysis::Mappings::get ().get_next_node_id ()),
682 144 : marked_for_strip (false)
683 144 : {}
684 :
685 : // Creates an error state path in expression.
686 8 : static PathInExpression create_error ()
687 : {
688 8 : return PathInExpression (std::vector<PathExprSegment> (), {},
689 16 : UNDEF_LOCATION);
690 : }
691 :
692 : // Returns whether path in expression is in an error state.
693 6025 : 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 2460 : 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 2460 : return convert_to_simple_path (has_opening_scope_resolution);
706 : }
707 :
708 62201 : 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 143386 : bool is_marked_for_strip () const override { return marked_for_strip; }
714 :
715 49345 : bool opening_scope_resolution () const
716 : {
717 49345 : return has_opening_scope_resolution;
718 : }
719 :
720 74106 : NodeId get_node_id () const override { return _node_id; }
721 :
722 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
723 586201 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
724 :
725 9851 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
726 : {
727 9851 : 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 20621 : Expr::Kind get_expr_kind () const override
737 : {
738 20621 : return Expr::Kind::PathInExpression;
739 : }
740 :
741 : protected:
742 : /* Use covariance to implement clone function as returning this object
743 : * rather than base */
744 1153 : PathInExpression *clone_pattern_impl () const final override
745 : {
746 1153 : 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 39514 : /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
757 : {
758 39514 : 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 102648 : virtual TypePathSegment *clone_type_path_segment_impl () const
789 : {
790 102648 : return new TypePathSegment (*this);
791 : }
792 93 : virtual TypePathSegment *reconstruct_impl () const
793 : {
794 186 : return new TypePathSegment (lang_item, ident_segment,
795 93 : has_separating_scope_resolution, locus);
796 : }
797 :
798 : public:
799 212301 : virtual ~TypePathSegment () {}
800 :
801 75 : virtual SegmentType get_type () const { return SegmentType::REG; }
802 :
803 : // Unique pointer custom clone function
804 106644 : std::unique_ptr<TypePathSegment> clone_type_path_segment () const
805 : {
806 106644 : 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 54923 : TypePathSegment (PathIdentSegment ident_segment,
815 : bool has_separating_scope_resolution, location_t locus)
816 109846 : : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
817 54923 : locus (locus),
818 54923 : has_separating_scope_resolution (has_separating_scope_resolution),
819 54923 : node_id (Analysis::Mappings::get ().get_next_node_id ())
820 54923 : {}
821 :
822 390 : TypePathSegment (LangItem::Kind lang_item, location_t locus)
823 390 : : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
824 390 : has_separating_scope_resolution (false),
825 390 : node_id (Analysis::Mappings::get ().get_next_node_id ())
826 390 : {}
827 :
828 4066 : TypePathSegment (std::string segment_name,
829 : bool has_separating_scope_resolution, location_t locus)
830 4066 : : lang_item (tl::nullopt),
831 4066 : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
832 4066 : locus (locus),
833 4066 : has_separating_scope_resolution (has_separating_scope_resolution),
834 8132 : node_id (Analysis::Mappings::get ().get_next_node_id ())
835 4066 : {}
836 :
837 : // General constructor
838 93 : TypePathSegment (tl::optional<LangItem::Kind> lang_item,
839 : tl::optional<PathIdentSegment> ident_segment,
840 : bool has_separating_scope_resolution, location_t locus)
841 186 : : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
842 93 : has_separating_scope_resolution (has_separating_scope_resolution),
843 93 : node_id (Analysis::Mappings::get ().get_next_node_id ())
844 93 : {}
845 :
846 107441 : TypePathSegment (TypePathSegment const &other)
847 214882 : : lang_item (other.lang_item), ident_segment (other.ident_segment),
848 107441 : locus (other.locus),
849 107441 : has_separating_scope_resolution (other.has_separating_scope_resolution),
850 107441 : node_id (other.node_id)
851 107441 : {}
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 318 : virtual std::string as_string () const
868 : {
869 318 : if (lang_item.has_value ())
870 0 : return LangItem::PrettyString (*lang_item);
871 :
872 318 : 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 55 : bool is_error () const
878 : {
879 55 : rust_assert (ident_segment);
880 55 : 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 30 : virtual bool is_ident_only () const { return true; }
886 :
887 281966 : bool is_lang_item () const { return lang_item.has_value (); }
888 :
889 3135 : 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 55155 : bool get_separating_scope_resolution () const
895 : {
896 55155 : return has_separating_scope_resolution;
897 : }
898 :
899 172974 : PathIdentSegment &get_ident_segment ()
900 : {
901 172974 : rust_assert (!is_lang_item ());
902 172974 : return *ident_segment;
903 : };
904 :
905 2 : const PathIdentSegment &get_ident_segment () const
906 : {
907 2 : rust_assert (!is_lang_item ());
908 2 : 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 111666 : 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 105101 : 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 2857 : TypePathSegmentGeneric (PathIdentSegment ident_segment,
951 : bool has_separating_scope_resolution,
952 : GenericArgs generic_args, location_t locus)
953 2857 : : TypePathSegment (std::move (ident_segment),
954 : has_separating_scope_resolution, locus),
955 2857 : generic_args (std::move (generic_args))
956 2857 : {}
957 :
958 49 : TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
959 : location_t locus)
960 49 : : TypePathSegment (lang_item, locus),
961 49 : generic_args (std::move (generic_args))
962 49 : {}
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 4763 : TypePathSegmentGeneric (TypePathSegmentGeneric const &other)
980 4763 : : TypePathSegment (other), generic_args (other.generic_args)
981 4763 : {}
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 55614 : GenericArgs &get_generic_args () { return generic_args; }
1001 :
1002 : // Use covariance to override base class method
1003 4763 : TypePathSegmentGeneric *clone_type_path_segment_impl () const override
1004 : {
1005 4763 : 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 552 : 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 582 : 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 30 : TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus,
1051 : std::unique_ptr<Type> type = nullptr)
1052 30 : : inputs (std::move (inputs)), return_type (std::move (type)),
1053 30 : is_invalid (false), locus (locus)
1054 : {}
1055 :
1056 : // Copy constructor with clone
1057 30 : TypePathFunction (TypePathFunction const &other)
1058 30 : : is_invalid (other.is_invalid)
1059 : {
1060 : // guard to protect from null pointer dereference
1061 30 : if (other.return_type != nullptr)
1062 28 : return_type = other.return_type->clone_type ();
1063 :
1064 30 : inputs.reserve (other.inputs.size ());
1065 62 : for (const auto &e : other.inputs)
1066 32 : inputs.push_back (e->clone_type ());
1067 30 : }
1068 :
1069 30 : ~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 30 : 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 552 : std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
1101 :
1102 : // TODO: is this better? Or is a "vis_pattern" better?
1103 434 : Type &get_return_type ()
1104 : {
1105 434 : rust_assert (has_return_type ());
1106 434 : return *return_type;
1107 : }
1108 :
1109 84 : std::unique_ptr<Type> &get_return_type_ptr ()
1110 : {
1111 84 : rust_assert (has_return_type ());
1112 84 : 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 7 : SegmentType get_type () const override { return SegmentType::FUNCTION; }
1125 :
1126 : // Constructor with PathIdentSegment and TypePathFn
1127 30 : TypePathSegmentFunction (PathIdentSegment ident_segment,
1128 : bool has_separating_scope_resolution,
1129 : TypePathFunction function_path, location_t locus)
1130 30 : : TypePathSegment (std::move (ident_segment),
1131 : has_separating_scope_resolution, locus),
1132 30 : function_path (std::move (function_path))
1133 30 : {}
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 552 : TypePathFunction &get_type_path_function ()
1152 : {
1153 552 : rust_assert (!function_path.is_error ());
1154 552 : return function_path;
1155 : }
1156 :
1157 : // Use covariance to override base class method
1158 30 : TypePathSegmentFunction *clone_type_path_segment_impl () const override
1159 : {
1160 30 : return new TypePathSegmentFunction (*this);
1161 : }
1162 : };
1163 :
1164 65898 : 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 83405 : TypePath *clone_type_no_bounds_impl () const override
1174 : {
1175 83405 : return new TypePath (*this);
1176 : }
1177 93 : TypePath *reconstruct_impl () const override
1178 : {
1179 465 : return new TypePath (reconstruct_vec (segments), locus,
1180 186 : 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 111427 : bool has_opening_scope_resolution_op () const
1187 : {
1188 111427 : return has_opening_scope_resolution;
1189 : }
1190 :
1191 : // Returns whether the TypePath is in an invalid state.
1192 72549 : bool is_error () const { return segments.empty (); }
1193 :
1194 : // Creates an error state TypePath.
1195 631 : static TypePath create_error ()
1196 : {
1197 631 : return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
1198 631 : UNDEF_LOCATION);
1199 : }
1200 :
1201 : // Constructor
1202 57920 : TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
1203 : location_t locus, bool has_opening_scope_resolution = false)
1204 3280 : : TypeNoBounds (),
1205 57920 : has_opening_scope_resolution (has_opening_scope_resolution),
1206 57920 : 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 104124 : TypePath (TypePath const &other)
1219 104124 : : TypeNoBounds (other),
1220 104124 : has_opening_scope_resolution (other.has_opening_scope_resolution),
1221 104124 : locus (other.locus)
1222 : {
1223 104124 : segments.reserve (other.segments.size ());
1224 210768 : for (const auto &e : other.segments)
1225 106644 : segments.push_back (e->clone_type_path_segment ());
1226 104124 : }
1227 :
1228 : // Overloaded assignment operator with clone
1229 : TypePath &operator= (TypePath const &other)
1230 : {
1231 : TypeNoBounds::operator= (other);
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 55499 : TypePath (TypePath &&other) = default;
1244 431 : 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 99244 : location_t get_locus () const override final { return locus; }
1258 297171 : NodeId get_node_id () const override { return node_id; }
1259 :
1260 0 : void mark_for_strip () override {}
1261 248148 : 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 3648 : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1267 : {
1268 1179203 : return segments;
1269 : }
1270 54287 : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1271 : {
1272 54289 : return segments;
1273 : }
1274 :
1275 : size_t get_num_segments () const { return segments.size (); }
1276 :
1277 258 : Type::Kind get_type_kind () const override { return Type::Kind::TypePath; }
1278 : };
1279 :
1280 : struct QualifiedPathType
1281 : {
1282 : private:
1283 : std::unique_ptr<Type> type_to_invoke_on;
1284 : TypePath trait_path;
1285 : location_t locus;
1286 : NodeId node_id;
1287 :
1288 : public:
1289 : // Constructor
1290 445 : QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
1291 : location_t locus = UNDEF_LOCATION,
1292 : TypePath trait_path = TypePath::create_error ())
1293 445 : : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
1294 445 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1295 445 : {}
1296 :
1297 : // Copy constructor uses custom deep copy for Type to preserve polymorphism
1298 983 : QualifiedPathType (QualifiedPathType const &other)
1299 983 : : trait_path (other.trait_path), locus (other.locus)
1300 : {
1301 983 : node_id = other.node_id;
1302 : // guard to prevent null dereference
1303 983 : if (other.type_to_invoke_on != nullptr)
1304 983 : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1305 983 : }
1306 :
1307 : // default destructor
1308 2334 : ~QualifiedPathType () = default;
1309 :
1310 : // overload assignment operator to use custom clone method
1311 : QualifiedPathType &operator= (QualifiedPathType const &other)
1312 : {
1313 : node_id = other.node_id;
1314 : trait_path = other.trait_path;
1315 : locus = other.locus;
1316 :
1317 : // guard to prevent null dereference
1318 : if (other.type_to_invoke_on != nullptr)
1319 : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1320 : else
1321 : type_to_invoke_on = nullptr;
1322 :
1323 : return *this;
1324 : }
1325 :
1326 : // move constructor
1327 1301 : QualifiedPathType (QualifiedPathType &&other) = default;
1328 0 : QualifiedPathType &operator= (QualifiedPathType &&other) = default;
1329 :
1330 : // Returns whether the qualified path type has a rebind as clause.
1331 9563 : bool has_as_clause () const { return !trait_path.is_error (); }
1332 :
1333 : // Returns whether the qualified path type is in an error state.
1334 10517 : bool is_error () const { return type_to_invoke_on == nullptr; }
1335 :
1336 : // Creates an error state qualified path type.
1337 0 : static QualifiedPathType create_error ()
1338 : {
1339 0 : return QualifiedPathType (nullptr);
1340 : }
1341 :
1342 : std::string as_string () const;
1343 :
1344 532 : location_t get_locus () const { return locus; }
1345 :
1346 : // TODO: is this better? Or is a "vis_pattern" better?
1347 8142 : Type &get_type ()
1348 : {
1349 8142 : rust_assert (type_to_invoke_on != nullptr);
1350 8142 : return *type_to_invoke_on;
1351 : }
1352 :
1353 1421 : std::unique_ptr<Type> &get_type_ptr ()
1354 : {
1355 1421 : rust_assert (type_to_invoke_on != nullptr);
1356 1421 : return type_to_invoke_on;
1357 : }
1358 :
1359 : // TODO: is this better? Or is a "vis_pattern" better?
1360 8647 : TypePath &get_as_type_path ()
1361 : {
1362 8647 : rust_assert (has_as_clause ());
1363 8647 : return trait_path;
1364 : }
1365 :
1366 356 : NodeId get_node_id () const { return node_id; }
1367 : };
1368 :
1369 : /* AST node representing a qualified path-in-expression pattern (path that
1370 : * allows specifying trait functions) */
1371 : class QualifiedPathInExpression : public Path, public ExprWithoutBlock
1372 : {
1373 : std::vector<Attribute> outer_attrs;
1374 : QualifiedPathType path_type;
1375 : location_t locus;
1376 : NodeId _node_id;
1377 :
1378 : public:
1379 : std::string as_string () const override;
1380 :
1381 114 : QualifiedPathInExpression (QualifiedPathType qual_path_type,
1382 : std::vector<PathExprSegment> path_segments,
1383 : std::vector<Attribute> outer_attrs,
1384 : location_t locus)
1385 228 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
1386 114 : path_type (std::move (qual_path_type)), locus (locus),
1387 114 : _node_id (Analysis::Mappings::get ().get_next_node_id ())
1388 114 : {}
1389 :
1390 : /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1391 : * elements as params */
1392 :
1393 : // Returns whether qualified path in expression is in an error state.
1394 526 : bool is_error () const { return path_type.is_error (); }
1395 :
1396 : // Creates an error qualified path in expression.
1397 0 : static QualifiedPathInExpression create_error ()
1398 : {
1399 0 : return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
1400 0 : {}, UNDEF_LOCATION);
1401 : }
1402 :
1403 310 : location_t get_locus () const override final { return locus; }
1404 :
1405 : void accept_vis (ASTVisitor &vis) override;
1406 :
1407 : // Invalid if path_type is error, so base stripping on that.
1408 0 : void mark_for_strip () override
1409 : {
1410 0 : path_type = QualifiedPathType::create_error ();
1411 0 : }
1412 526 : bool is_marked_for_strip () const override { return is_error (); }
1413 :
1414 : // TODO: is this better? Or is a "vis_pattern" better?
1415 2647 : QualifiedPathType &get_qualified_path_type ()
1416 : {
1417 2647 : rust_assert (!path_type.is_error ());
1418 2647 : return path_type;
1419 : }
1420 :
1421 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1422 2881 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1423 :
1424 97 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
1425 : {
1426 97 : outer_attrs = std::move (new_attrs);
1427 0 : }
1428 :
1429 144 : NodeId get_node_id () const override { return _node_id; }
1430 :
1431 114 : Expr::Kind get_expr_kind () const override
1432 : {
1433 114 : return Expr::Kind::QualifiedPathInExpression;
1434 : }
1435 :
1436 : protected:
1437 : /* Use covariance to implement clone function as returning this object
1438 : * rather than base */
1439 0 : QualifiedPathInExpression *clone_pattern_impl () const final override
1440 : {
1441 0 : return clone_qual_path_in_expression_impl ();
1442 : }
1443 :
1444 : /* Use covariance to implement clone function as returning this object
1445 : * rather than base */
1446 : QualifiedPathInExpression *
1447 0 : clone_expr_without_block_impl () const final override
1448 : {
1449 0 : return clone_qual_path_in_expression_impl ();
1450 : }
1451 :
1452 : /*virtual*/ QualifiedPathInExpression *
1453 169 : clone_qual_path_in_expression_impl () const
1454 : {
1455 169 : return new QualifiedPathInExpression (*this);
1456 : }
1457 : };
1458 :
1459 : /* Represents a qualified path in a type; used for disambiguating trait
1460 : * function calls */
1461 : class QualifiedPathInType : public TypeNoBounds
1462 : {
1463 : QualifiedPathType path_type;
1464 : std::unique_ptr<TypePathSegment> associated_segment;
1465 : std::vector<std::unique_ptr<TypePathSegment>> segments;
1466 : location_t locus;
1467 :
1468 : protected:
1469 : /* Use covariance to implement clone function as returning this object
1470 : * rather than base */
1471 797 : QualifiedPathInType *clone_type_no_bounds_impl () const override
1472 : {
1473 797 : return new QualifiedPathInType (*this);
1474 : }
1475 0 : QualifiedPathInType *reconstruct_impl () const override
1476 : {
1477 0 : return new QualifiedPathInType (path_type,
1478 0 : associated_segment->reconstruct (),
1479 0 : reconstruct_vec (segments), locus);
1480 : }
1481 :
1482 : public:
1483 331 : QualifiedPathInType (
1484 : QualifiedPathType qual_path_type,
1485 : std::unique_ptr<TypePathSegment> associated_segment,
1486 : std::vector<std::unique_ptr<TypePathSegment>> path_segments,
1487 : location_t locus)
1488 662 : : path_type (std::move (qual_path_type)),
1489 331 : associated_segment (std::move (associated_segment)),
1490 331 : segments (std::move (path_segments)), locus (locus)
1491 331 : {}
1492 :
1493 : // Copy constructor with vector clone
1494 797 : QualifiedPathInType (QualifiedPathInType const &other)
1495 797 : : path_type (other.path_type), locus (other.locus)
1496 : {
1497 797 : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1498 797 : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1499 :
1500 797 : segments.reserve (other.segments.size ());
1501 797 : for (const auto &e : other.segments)
1502 0 : segments.push_back (e->clone_type_path_segment ());
1503 797 : }
1504 :
1505 : // Overloaded assignment operator with vector clone
1506 : QualifiedPathInType &operator= (QualifiedPathInType const &other)
1507 : {
1508 : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1509 : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1510 :
1511 : path_type = other.path_type;
1512 : locus = other.locus;
1513 :
1514 : segments.reserve (other.segments.size ());
1515 : for (const auto &e : other.segments)
1516 : segments.push_back (e->clone_type_path_segment ());
1517 :
1518 : return *this;
1519 : }
1520 :
1521 : // move constructors
1522 331 : QualifiedPathInType (QualifiedPathInType &&other) = default;
1523 : QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
1524 :
1525 : // Returns whether qualified path in type is in an error state.
1526 331 : bool is_error () const { return path_type.is_error (); }
1527 :
1528 : // Creates an error state qualified path in type.
1529 0 : static QualifiedPathInType create_error ()
1530 : {
1531 0 : return QualifiedPathInType (
1532 0 : QualifiedPathType::create_error (), nullptr,
1533 0 : std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
1534 : }
1535 :
1536 : std::string as_string () const override;
1537 :
1538 : void accept_vis (ASTVisitor &vis) override;
1539 :
1540 : // TODO: is this better? Or is a "vis_pattern" better?
1541 7642 : QualifiedPathType &get_qualified_path_type ()
1542 : {
1543 7642 : rust_assert (!path_type.is_error ());
1544 7642 : return path_type;
1545 : }
1546 :
1547 : std::unique_ptr<TypePathSegment> &get_associated_segment ()
1548 : {
1549 4954 : return associated_segment;
1550 : }
1551 :
1552 : // TODO: this seems kinda dodgy
1553 : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1554 : {
1555 5663 : return segments;
1556 : }
1557 : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1558 : {
1559 : return segments;
1560 : }
1561 :
1562 248 : location_t get_locus () const override final { return locus; }
1563 :
1564 0 : Type::Kind get_type_kind () const override
1565 : {
1566 0 : return Type::Kind::QualifiedPathInType;
1567 : }
1568 : };
1569 : } // namespace AST
1570 : } // namespace Rust
1571 :
1572 : #endif
|