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 : 575029 : 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 : 220981 : PathIdentSegment (std::string segment_name, location_t locus)
43 : 188189 : : segment_name (std::move (segment_name)), locus (locus)
44 : : {}
45 : :
46 : : // Creates an error PathIdentSegment.
47 : 205 : static PathIdentSegment create_error ()
48 : : {
49 : 205 : return PathIdentSegment ("", UNDEF_LOCATION);
50 : : }
51 : :
52 : : // Returns whether PathIdentSegment is in an error state.
53 : 106601 : bool is_error () const { return segment_name.empty (); }
54 : :
55 : 485938 : std::string as_string () const { return segment_name; }
56 : :
57 : 5182 : location_t get_locus () const { return locus; }
58 : :
59 : 31647 : bool is_super_path_seg () const
60 : : {
61 : 63294 : return as_string ().compare ("super") == 0;
62 : : }
63 : 46787 : bool is_crate_path_seg () const
64 : : {
65 : 93574 : return as_string ().compare ("crate") == 0;
66 : : }
67 : 189540 : bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
68 : 105974 : 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 : 14 : GenericArgsBinding (GenericArgsBinding const &other)
101 : 14 : : identifier (other.identifier), locus (other.locus)
102 : : {
103 : : // guard to protect from null pointer dereference
104 : 14 : if (other.type != nullptr)
105 : 14 : type = other.type->clone_type ();
106 : 14 : }
107 : :
108 : : // default destructor
109 : 88 : ~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 : 1273 : Type &get_type ()
134 : : {
135 : 1273 : rust_assert (type != nullptr);
136 : 1273 : return *type;
137 : : }
138 : :
139 : 205 : std::unique_ptr<Type> &get_type_ptr ()
140 : : {
141 : 205 : rust_assert (type != nullptr);
142 : 205 : 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 : 87 : static GenericArg create_const (std::unique_ptr<Expr> expression)
176 : : {
177 : 87 : auto locus = expression->get_locus ();
178 : 87 : return GenericArg (std::move (expression), nullptr, {""}, Kind::Const,
179 : 174 : locus);
180 : : }
181 : :
182 : 3725 : static GenericArg create_type (std::unique_ptr<Type> type)
183 : : {
184 : 3725 : auto locus = type->get_locus ();
185 : 11175 : return GenericArg (nullptr, std::move (type), {""}, Kind::Type, locus);
186 : : }
187 : :
188 : 2399 : static GenericArg create_ambiguous (Identifier path, location_t locus)
189 : : {
190 : 4798 : return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
191 : : }
192 : :
193 : 5614 : GenericArg (const GenericArg &other)
194 : 5614 : : path (other.path), kind (other.kind), locus (other.locus)
195 : : {
196 : 5614 : if (other.expression)
197 : 18 : expression = other.expression->clone_expr ();
198 : 5614 : if (other.type)
199 : 4184 : type = other.type->clone_type ();
200 : 5614 : }
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 : 13201 : GenericArg (GenericArg &&other) = default;
217 : 2295 : GenericArg &operator= (GenericArg &&other) = default;
218 : :
219 : 79389 : Kind get_kind () const { return kind; }
220 : 0 : location_t get_locus () const { return locus; }
221 : :
222 : 42628 : void accept_vis (AST::ASTVisitor &visitor)
223 : : {
224 : 42628 : switch (get_kind ())
225 : : {
226 : 859 : case Kind::Const:
227 : 859 : get_expression ().accept_vis (visitor);
228 : 859 : break;
229 : 17865 : case Kind::Type:
230 : 17865 : get_type ().accept_vis (visitor);
231 : 17865 : break;
232 : : case Kind::Either:
233 : : break;
234 : : }
235 : 42628 : }
236 : :
237 : 1201 : Expr &get_expression ()
238 : : {
239 : 1201 : rust_assert (kind == Kind::Const);
240 : :
241 : 1201 : return *expression;
242 : : }
243 : :
244 : 92 : std::unique_ptr<Expr> &get_expression_ptr ()
245 : : {
246 : 92 : rust_assert (kind == Kind::Const);
247 : :
248 : 92 : return expression;
249 : : }
250 : :
251 : 31226 : Type &get_type ()
252 : : {
253 : 31226 : rust_assert (kind == Kind::Type);
254 : :
255 : 31226 : return *type;
256 : : }
257 : :
258 : 3819 : std::unique_ptr<Type> &get_type_ptr ()
259 : : {
260 : 3819 : rust_assert (kind == Kind::Type);
261 : :
262 : 3819 : return type;
263 : : }
264 : :
265 : 4588 : const std::string get_path () const
266 : : {
267 : 4588 : rust_assert (kind == Kind::Either);
268 : :
269 : 4588 : 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 : 6211 : GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
301 : : Identifier path, Kind kind, location_t locus)
302 : 4732 : : expression (std::move (expression)), type (std::move (type)),
303 : 6211 : 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 : 46 : ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
353 : : tl::optional<GenericArg> default_value,
354 : : AST::AttrVec outer_attrs, location_t locus)
355 : 46 : : name (name), type (std::move (type)),
356 : 46 : default_value (std::move (default_value)), outer_attrs (outer_attrs),
357 : 46 : locus (locus)
358 : 46 : {}
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 : 631 : bool has_type () const { return type != nullptr; }
367 : 631 : bool has_default_value () const { return default_value.has_value (); }
368 : :
369 : 138 : const Identifier &get_name () const { return name; }
370 : :
371 : 642 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
372 : :
373 : 631 : AST::Type &get_type ()
374 : : {
375 : 631 : rust_assert (has_type ());
376 : :
377 : 631 : return *type;
378 : : }
379 : :
380 : 248 : GenericArg &get_default_value_unchecked ()
381 : : {
382 : 248 : rust_assert (has_default_value ());
383 : :
384 : 248 : return default_value.value ();
385 : : }
386 : :
387 : 0 : const GenericArg &get_default_value_unchecked () const
388 : : {
389 : 0 : rust_assert (has_default_value ());
390 : :
391 : 0 : return default_value.value ();
392 : : }
393 : :
394 : 0 : tl::optional<GenericArg> &get_default_value () { return default_value; }
395 : :
396 : : const tl::optional<GenericArg> &get_default_value () const
397 : : {
398 : : return default_value;
399 : : }
400 : :
401 : : std::string as_string () const override;
402 : :
403 : : void accept_vis (ASTVisitor &vis) override;
404 : :
405 : 208 : location_t get_locus () const override final { return locus; }
406 : :
407 : 92 : Kind get_kind () const override final { return Kind::Const; }
408 : :
409 : : protected:
410 : : /* Use covariance to implement clone function as returning this object rather
411 : : * than base */
412 : 0 : ConstGenericParam *clone_generic_param_impl () const override
413 : : {
414 : 0 : return new ConstGenericParam (*this);
415 : : }
416 : : };
417 : :
418 : : // Generic arguments allowed in each path expression segment - inline?
419 : : struct GenericArgs
420 : : {
421 : : std::vector<Lifetime> lifetime_args;
422 : : std::vector<GenericArg> generic_args;
423 : : std::vector<GenericArgsBinding> binding_args;
424 : : location_t locus;
425 : :
426 : : public:
427 : : // Returns true if there are any generic arguments
428 : 882347 : bool has_generic_args () const
429 : : {
430 : 881810 : return !(lifetime_args.empty () && generic_args.empty ()
431 : 793828 : && binding_args.empty ());
432 : : }
433 : :
434 : 88489 : GenericArgs (std::vector<Lifetime> lifetime_args,
435 : : std::vector<GenericArg> generic_args,
436 : : std::vector<GenericArgsBinding> binding_args,
437 : : location_t locus = UNDEF_LOCATION)
438 : 88489 : : lifetime_args (std::move (lifetime_args)),
439 : 88489 : generic_args (std::move (generic_args)),
440 : 88489 : binding_args (std::move (binding_args)), locus (locus)
441 : 88489 : {}
442 : :
443 : : // copy constructor with vector clone
444 : 46279 : GenericArgs (GenericArgs const &other)
445 : 46279 : : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
446 : 46279 : locus (other.locus)
447 : : {
448 : 46279 : generic_args.clear ();
449 : 46279 : generic_args.reserve (other.generic_args.size ());
450 : 51670 : for (const auto &arg : other.generic_args)
451 : : {
452 : 5391 : generic_args.push_back (GenericArg (arg));
453 : : }
454 : 46279 : }
455 : :
456 : 253417 : ~GenericArgs () = default;
457 : :
458 : : // overloaded assignment operator to vector clone
459 : : GenericArgs &operator= (GenericArgs const &other)
460 : : {
461 : : lifetime_args = other.lifetime_args;
462 : : binding_args = other.binding_args;
463 : : locus = other.locus;
464 : :
465 : : generic_args.clear ();
466 : : generic_args.reserve (other.generic_args.size ());
467 : : for (const auto &arg : other.generic_args)
468 : : {
469 : : generic_args.push_back (GenericArg (arg));
470 : : }
471 : :
472 : : return *this;
473 : : }
474 : :
475 : : // move constructors
476 : 156190 : GenericArgs (GenericArgs &&other) = default;
477 : 308 : GenericArgs &operator= (GenericArgs &&other) = default;
478 : :
479 : : // Creates an empty GenericArgs (no arguments)
480 : 51565 : static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
481 : :
482 : : std::string as_string () const;
483 : :
484 : 73452 : std::vector<GenericArg> &get_generic_args () { return generic_args; }
485 : :
486 : 73463 : std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
487 : :
488 : : const std::vector<GenericArgsBinding> &get_binding_args () const
489 : : {
490 : : return binding_args;
491 : : }
492 : :
493 : 44232 : std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
494 : :
495 : : const std::vector<Lifetime> &get_lifetime_args () const
496 : : {
497 : : return lifetime_args;
498 : : };
499 : :
500 : 3577 : location_t get_locus () const { return locus; }
501 : : };
502 : :
503 : : /* A segment of a path in expression, including an identifier aspect and maybe
504 : : * generic args */
505 : 185758 : class PathExprSegment
506 : : { // or should this extend PathIdentSegment?
507 : : private:
508 : : PathIdentSegment segment_name;
509 : : GenericArgs generic_args;
510 : : location_t locus;
511 : : NodeId node_id;
512 : :
513 : : public:
514 : : // Returns true if there are any generic arguments
515 : 1277345 : bool has_generic_args () const { return generic_args.has_generic_args (); }
516 : :
517 : : // Constructor for segment (from IdentSegment and GenericArgs)
518 : 52427 : PathExprSegment (PathIdentSegment segment_name, location_t locus,
519 : : GenericArgs generic_args = GenericArgs::create_empty ())
520 : 52427 : : segment_name (std::move (segment_name)),
521 : 52427 : generic_args (std::move (generic_args)), locus (locus),
522 : 52427 : node_id (Analysis::Mappings::get ().get_next_node_id ())
523 : 52427 : {}
524 : :
525 : : /* Constructor for segment with generic arguments (from segment name and all
526 : : * args) */
527 : 32788 : PathExprSegment (std::string segment_name, location_t locus,
528 : : std::vector<Lifetime> lifetime_args = {},
529 : : std::vector<GenericArg> generic_args = {},
530 : : std::vector<GenericArgsBinding> binding_args = {})
531 : 32788 : : segment_name (PathIdentSegment (std::move (segment_name), locus)),
532 : 32788 : generic_args (GenericArgs (std::move (lifetime_args),
533 : : std::move (generic_args),
534 : 32788 : std::move (binding_args))),
535 : 32788 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
536 : 32788 : {}
537 : :
538 : : // Returns whether path expression segment is in an error state.
539 : 85406 : bool is_error () const { return segment_name.is_error (); }
540 : :
541 : : // Creates an error-state path expression segment.
542 : 2 : static PathExprSegment create_error ()
543 : : {
544 : 2 : return PathExprSegment (PathIdentSegment::create_error (), UNDEF_LOCATION);
545 : : }
546 : :
547 : : std::string as_string () const;
548 : :
549 : 38222 : location_t get_locus () const { return locus; }
550 : :
551 : : // TODO: is this better? Or is a "vis_pattern" better?
552 : 19089 : GenericArgs &get_generic_args ()
553 : : {
554 : 19089 : rust_assert (has_generic_args ());
555 : 19089 : return generic_args;
556 : : }
557 : :
558 : 462509 : PathIdentSegment &get_ident_segment () { return segment_name; }
559 : 92741 : const PathIdentSegment &get_ident_segment () const { return segment_name; }
560 : :
561 : 71974 : NodeId get_node_id () const { return node_id; }
562 : :
563 : 0 : bool is_super_path_seg () const
564 : : {
565 : 0 : return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
566 : : }
567 : :
568 : 0 : bool is_crate_path_seg () const
569 : : {
570 : 0 : return !has_generic_args () && get_ident_segment ().is_crate_path_seg ();
571 : : }
572 : :
573 : 41496 : bool is_lower_self_seg () const
574 : : {
575 : 82730 : return !has_generic_args () && get_ident_segment ().is_lower_self_seg ();
576 : : }
577 : : };
578 : :
579 : : // AST node representing a pattern that involves a "path" - abstract base
580 : : // class
581 : : class Path : public Pattern
582 : : {
583 : : public:
584 : : enum class Kind
585 : : {
586 : : LangItem,
587 : : Regular,
588 : : };
589 : :
590 : 72811 : Path (std::vector<PathExprSegment> segments)
591 : 72811 : : segments (std::move (segments)), lang_item (tl::nullopt),
592 : 72811 : kind (Kind::Regular)
593 : : {}
594 : :
595 : 144 : Path (LangItem::Kind lang_item)
596 : 144 : : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
597 : 144 : {}
598 : :
599 : : // Returns whether path has segments.
600 : 8373 : bool has_segments () const
601 : : {
602 : 8373 : rust_assert (kind == Kind::Regular);
603 : 8373 : return !segments.empty ();
604 : : }
605 : :
606 : : /* Converts path segments to their equivalent SimplePath segments if
607 : : * possible, and creates a SimplePath from them. */
608 : : SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
609 : :
610 : : /* Returns whether the path is a single segment (excluding qualified path
611 : : * initial as segment). */
612 : 95062 : bool is_single_segment () const
613 : : {
614 : 95062 : rust_assert (kind == Kind::Regular);
615 : 95062 : return segments.size () == 1;
616 : : }
617 : :
618 : : std::string as_string () const override;
619 : :
620 : 517391 : bool is_lang_item () const { return kind == Kind::LangItem; }
621 : :
622 : : // TODO: this seems kinda dodgy
623 : 564254 : std::vector<PathExprSegment> &get_segments ()
624 : : {
625 : 564254 : rust_assert (kind == Kind::Regular);
626 : 564254 : return segments;
627 : : }
628 : 23802 : const std::vector<PathExprSegment> &get_segments () const
629 : : {
630 : 23802 : rust_assert (kind == Kind::Regular);
631 : 23802 : return segments;
632 : : }
633 : :
634 : 352 : LangItem::Kind get_lang_item () const
635 : : {
636 : 352 : rust_assert (kind == Kind::LangItem);
637 : 352 : return *lang_item;
638 : : }
639 : :
640 : 0 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
641 : : Path::Kind get_path_kind () { return kind; }
642 : :
643 : : protected:
644 : : std::vector<PathExprSegment> segments;
645 : : tl::optional<LangItem::Kind> lang_item;
646 : :
647 : : Path::Kind kind;
648 : : };
649 : :
650 : : /* AST node representing a path-in-expression pattern (path that allows
651 : : * generic arguments) */
652 : : class PathInExpression : public Path, public ExprWithoutBlock
653 : : {
654 : : std::vector<Attribute> outer_attrs;
655 : : bool has_opening_scope_resolution;
656 : : location_t locus;
657 : : NodeId _node_id;
658 : :
659 : : bool marked_for_strip;
660 : :
661 : : public:
662 : : std::string as_string () const override;
663 : :
664 : : // Constructor
665 : 72697 : PathInExpression (std::vector<PathExprSegment> path_segments,
666 : : std::vector<Attribute> outer_attrs, location_t locus,
667 : : bool has_opening_scope_resolution = false)
668 : 145394 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
669 : 72697 : has_opening_scope_resolution (has_opening_scope_resolution),
670 : 72697 : locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
671 : 72697 : marked_for_strip (false)
672 : 72697 : {}
673 : :
674 : 144 : PathInExpression (LangItem::Kind lang_item,
675 : : std::vector<Attribute> outer_attrs, location_t locus)
676 : 288 : : Path (lang_item), outer_attrs (std::move (outer_attrs)),
677 : 144 : has_opening_scope_resolution (false), locus (locus),
678 : 144 : _node_id (Analysis::Mappings::get ().get_next_node_id ()),
679 : 144 : marked_for_strip (false)
680 : 144 : {}
681 : :
682 : : // Creates an error state path in expression.
683 : 2 : static PathInExpression create_error ()
684 : : {
685 : 2 : return PathInExpression (std::vector<PathExprSegment> (), {},
686 : 4 : UNDEF_LOCATION);
687 : : }
688 : :
689 : : // Returns whether path in expression is in an error state.
690 : 5961 : bool is_error () const { return !has_segments (); }
691 : :
692 : : /* Converts PathInExpression to SimplePath if possible (i.e. no generic
693 : : * arguments). Otherwise returns an empty SimplePath. */
694 : 2412 : SimplePath as_simple_path () const
695 : : {
696 : : /* delegate to parent class as can't access segments. however,
697 : : * QualifiedPathInExpression conversion to simple path wouldn't make
698 : : * sense, so the method in the parent class should be protected, not
699 : : * public. Have to pass in opening scope resolution as parent class has no
700 : : * access to it.
701 : : */
702 : 2412 : return convert_to_simple_path (has_opening_scope_resolution);
703 : : }
704 : :
705 : 61211 : location_t get_locus () const override final { return locus; }
706 : :
707 : : void accept_vis (ASTVisitor &vis) override;
708 : :
709 : 0 : void mark_for_strip () override { marked_for_strip = true; }
710 : 141663 : bool is_marked_for_strip () const override { return marked_for_strip; }
711 : :
712 : 48580 : bool opening_scope_resolution () const
713 : : {
714 : 48580 : return has_opening_scope_resolution;
715 : : }
716 : :
717 : 44108 : NodeId get_node_id () const override { return _node_id; }
718 : :
719 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
720 : 572705 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
721 : :
722 : 9716 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
723 : : {
724 : 9716 : outer_attrs = std::move (new_attrs);
725 : 0 : }
726 : :
727 : : PathExprSegment &get_final_segment () { return get_segments ().back (); }
728 : : const PathExprSegment &get_final_segment () const
729 : : {
730 : : return get_segments ().back ();
731 : : }
732 : :
733 : 13153 : Expr::Kind get_expr_kind () const override
734 : : {
735 : 13153 : return Expr::Kind::PathInExpression;
736 : : }
737 : :
738 : : protected:
739 : : /* Use covariance to implement clone function as returning this object
740 : : * rather than base */
741 : 174 : PathInExpression *clone_pattern_impl () const final override
742 : : {
743 : 174 : return clone_path_in_expression_impl ();
744 : : }
745 : :
746 : : /* Use covariance to implement clone function as returning this object
747 : : * rather than base */
748 : 0 : PathInExpression *clone_expr_without_block_impl () const final override
749 : : {
750 : 0 : return clone_path_in_expression_impl ();
751 : : }
752 : :
753 : 23221 : /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
754 : : {
755 : 23221 : return new PathInExpression (*this);
756 : : }
757 : : };
758 : :
759 : : /* Base class for segments used in type paths - not abstract (represents an
760 : : * ident-only segment) */
761 : : class TypePathSegment
762 : : {
763 : : public:
764 : : enum SegmentType
765 : : {
766 : : REG,
767 : : GENERIC,
768 : : FUNCTION
769 : : };
770 : :
771 : : private:
772 : : tl::optional<LangItem::Kind> lang_item;
773 : : tl::optional<PathIdentSegment> ident_segment;
774 : : location_t locus;
775 : :
776 : : protected:
777 : : /* This is protected because it is only really used by derived classes, not
778 : : * the base. */
779 : : bool has_separating_scope_resolution;
780 : : NodeId node_id;
781 : :
782 : : public:
783 : : // Clone function implementation - not pure virtual as overrided by
784 : : // subclasses
785 : 68811 : virtual TypePathSegment *clone_type_path_segment_impl () const
786 : : {
787 : 68811 : return new TypePathSegment (*this);
788 : : }
789 : 93 : virtual TypePathSegment *reconstruct_impl () const
790 : : {
791 : 186 : return new TypePathSegment (lang_item, ident_segment,
792 : 93 : has_separating_scope_resolution, locus);
793 : : }
794 : :
795 : : public:
796 : 144575 : virtual ~TypePathSegment () {}
797 : :
798 : 75 : virtual SegmentType get_type () const { return SegmentType::REG; }
799 : :
800 : : // Unique pointer custom clone function
801 : 70658 : std::unique_ptr<TypePathSegment> clone_type_path_segment () const
802 : : {
803 : 70658 : return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
804 : : }
805 : : // Unique pointer custom reconstruct function
806 : 0 : std::unique_ptr<TypePathSegment> reconstruct () const
807 : : {
808 : 0 : return reconstruct_base (this);
809 : : }
810 : :
811 : 131196 : TypePathSegment (PathIdentSegment ident_segment,
812 : : bool has_separating_scope_resolution, location_t locus)
813 : 262392 : : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
814 : 131196 : locus (locus),
815 : 131196 : has_separating_scope_resolution (has_separating_scope_resolution),
816 : 131196 : node_id (Analysis::Mappings::get ().get_next_node_id ())
817 : 131196 : {}
818 : :
819 : 431 : TypePathSegment (LangItem::Kind lang_item, location_t locus)
820 : 431 : : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
821 : 431 : has_separating_scope_resolution (false),
822 : 431 : node_id (Analysis::Mappings::get ().get_next_node_id ())
823 : 431 : {}
824 : :
825 : 4369 : TypePathSegment (std::string segment_name,
826 : : bool has_separating_scope_resolution, location_t locus)
827 : 4369 : : lang_item (tl::nullopt),
828 : 4369 : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
829 : 4369 : locus (locus),
830 : 4369 : has_separating_scope_resolution (has_separating_scope_resolution),
831 : 8738 : node_id (Analysis::Mappings::get ().get_next_node_id ())
832 : 4369 : {}
833 : :
834 : : // General constructor
835 : 93 : TypePathSegment (tl::optional<LangItem::Kind> lang_item,
836 : : tl::optional<PathIdentSegment> ident_segment,
837 : : bool has_separating_scope_resolution, location_t locus)
838 : 186 : : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
839 : 93 : has_separating_scope_resolution (has_separating_scope_resolution),
840 : 93 : node_id (Analysis::Mappings::get ().get_next_node_id ())
841 : 93 : {}
842 : :
843 : 71283 : TypePathSegment (TypePathSegment const &other)
844 : 142566 : : lang_item (other.lang_item), ident_segment (other.ident_segment),
845 : 71283 : locus (other.locus),
846 : 71283 : has_separating_scope_resolution (other.has_separating_scope_resolution),
847 : 71283 : node_id (other.node_id)
848 : 71283 : {}
849 : :
850 : : TypePathSegment &operator= (TypePathSegment const &other)
851 : : {
852 : : ident_segment = other.ident_segment;
853 : : lang_item = other.lang_item;
854 : : locus = other.locus;
855 : : has_separating_scope_resolution = other.has_separating_scope_resolution;
856 : : node_id = other.node_id;
857 : :
858 : : return *this;
859 : : }
860 : :
861 : : TypePathSegment (TypePathSegment &&other) = default;
862 : : TypePathSegment &operator= (TypePathSegment &&other) = default;
863 : :
864 : 58 : virtual std::string as_string () const
865 : : {
866 : 58 : if (lang_item.has_value ())
867 : 0 : return LangItem::PrettyString (*lang_item);
868 : :
869 : 58 : return ident_segment->as_string ();
870 : : }
871 : :
872 : : /* Returns whether the type path segment is in an error state. May be
873 : : * virtual in future. */
874 : 50 : bool is_error () const
875 : : {
876 : 50 : rust_assert (ident_segment);
877 : 50 : return ident_segment->is_error ();
878 : : }
879 : :
880 : : /* Returns whether segment is identifier only (as opposed to generic args or
881 : : * function). Overridden in derived classes with other segments. */
882 : 29 : virtual bool is_ident_only () const { return true; }
883 : :
884 : 169172 : bool is_lang_item () const { return lang_item.has_value (); }
885 : :
886 : 3046 : location_t get_locus () const { return locus; }
887 : :
888 : : // not pure virtual as class not abstract
889 : : virtual void accept_vis (ASTVisitor &vis);
890 : :
891 : 54384 : bool get_separating_scope_resolution () const
892 : : {
893 : 54384 : return has_separating_scope_resolution;
894 : : }
895 : :
896 : 116964 : PathIdentSegment &get_ident_segment ()
897 : : {
898 : 116964 : rust_assert (!is_lang_item ());
899 : 116964 : return *ident_segment;
900 : : };
901 : :
902 : 51528 : const PathIdentSegment &get_ident_segment () const
903 : : {
904 : 51528 : rust_assert (!is_lang_item ());
905 : 51528 : return *ident_segment;
906 : : };
907 : :
908 : 758 : LangItem::Kind get_lang_item () const
909 : : {
910 : 758 : rust_assert (is_lang_item ());
911 : 758 : return *lang_item;
912 : : }
913 : :
914 : 109670 : NodeId get_node_id () const { return node_id; }
915 : :
916 : 0 : bool is_crate_path_seg () const
917 : : {
918 : 0 : return get_ident_segment ().is_crate_path_seg ();
919 : : }
920 : 0 : bool is_super_path_seg () const
921 : : {
922 : 0 : return get_ident_segment ().is_super_path_seg ();
923 : : }
924 : 51526 : bool is_big_self_seg () const
925 : : {
926 : 51526 : return get_ident_segment ().is_big_self_seg ();
927 : : }
928 : 0 : bool is_lower_self_seg () const
929 : : {
930 : 0 : return get_ident_segment ().is_lower_self_seg ();
931 : : }
932 : : };
933 : :
934 : : // Segment used in type path with generic args
935 : : class TypePathSegmentGeneric : public TypePathSegment
936 : : {
937 : : GenericArgs generic_args;
938 : :
939 : : public:
940 : 11 : SegmentType get_type () const override { return SegmentType::GENERIC; }
941 : :
942 : 102398 : bool has_generic_args () const { return generic_args.has_generic_args (); }
943 : :
944 : 0 : bool is_ident_only () const override { return false; }
945 : :
946 : : // Constructor with PathIdentSegment and GenericArgs
947 : 2806 : TypePathSegmentGeneric (PathIdentSegment ident_segment,
948 : : bool has_separating_scope_resolution,
949 : : GenericArgs generic_args, location_t locus)
950 : 2806 : : TypePathSegment (std::move (ident_segment),
951 : : has_separating_scope_resolution, locus),
952 : 2806 : generic_args (std::move (generic_args))
953 : 2806 : {}
954 : :
955 : 47 : TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
956 : : location_t locus)
957 : 47 : : TypePathSegment (lang_item, locus),
958 : 47 : generic_args (std::move (generic_args))
959 : 47 : {}
960 : :
961 : : // Constructor from segment name and all args
962 : : TypePathSegmentGeneric (std::string segment_name,
963 : : bool has_separating_scope_resolution,
964 : : std::vector<Lifetime> lifetime_args,
965 : : std::vector<GenericArg> generic_args,
966 : : std::vector<GenericArgsBinding> binding_args,
967 : : location_t locus)
968 : : : TypePathSegment (std::move (segment_name),
969 : : has_separating_scope_resolution, locus),
970 : : generic_args (GenericArgs (std::move (lifetime_args),
971 : : std::move (generic_args),
972 : : std::move (binding_args)))
973 : : {}
974 : :
975 : : // Copy constructor with vector clone
976 : 2472 : TypePathSegmentGeneric (TypePathSegmentGeneric const &other)
977 : 2472 : : TypePathSegment (other), generic_args (other.generic_args)
978 : 2472 : {}
979 : :
980 : : // Overloaded assignment operator with vector clone
981 : : TypePathSegmentGeneric &operator= (TypePathSegmentGeneric const &other)
982 : : {
983 : : generic_args = other.generic_args;
984 : :
985 : : return *this;
986 : : }
987 : :
988 : : // move constructors
989 : : TypePathSegmentGeneric (TypePathSegmentGeneric &&other) = default;
990 : : TypePathSegmentGeneric &operator= (TypePathSegmentGeneric &&other) = default;
991 : :
992 : : std::string as_string () const override;
993 : :
994 : : void accept_vis (ASTVisitor &vis) override;
995 : :
996 : : // TODO: is this better? Or is a "vis_pattern" better?
997 : 54126 : GenericArgs &get_generic_args () { return generic_args; }
998 : :
999 : : // Use covariance to override base class method
1000 : 2472 : TypePathSegmentGeneric *clone_type_path_segment_impl () const override
1001 : : {
1002 : 2472 : return new TypePathSegmentGeneric (*this);
1003 : : }
1004 : : };
1005 : :
1006 : : // A function as represented in a type path
1007 : : struct TypePathFunction
1008 : : {
1009 : : private:
1010 : : // TODO: remove
1011 : : /*bool has_inputs;
1012 : : TypePathFnInputs inputs;*/
1013 : : // inlined from TypePathFnInputs
1014 : : std::vector<std::unique_ptr<Type>> inputs;
1015 : :
1016 : : // bool has_type;
1017 : : std::unique_ptr<Type> return_type;
1018 : :
1019 : : // FIXME: think of better way to mark as invalid than taking up storage
1020 : : bool is_invalid;
1021 : :
1022 : : location_t locus;
1023 : :
1024 : : protected:
1025 : : // Constructor only used to create invalid type path functions.
1026 : 0 : TypePathFunction (bool is_invalid, location_t locus)
1027 : 0 : : is_invalid (is_invalid), locus (locus)
1028 : : {}
1029 : :
1030 : : public:
1031 : : // Returns whether the return type of the function has been specified.
1032 : 552 : bool has_return_type () const { return return_type != nullptr; }
1033 : :
1034 : : // Returns whether the function has inputs.
1035 : 5 : bool has_inputs () const { return !inputs.empty (); }
1036 : :
1037 : : // Returns whether function is in an error state.
1038 : 582 : bool is_error () const { return is_invalid; }
1039 : :
1040 : : // Creates an error state function.
1041 : 0 : static TypePathFunction create_error ()
1042 : : {
1043 : 0 : return TypePathFunction (true, UNDEF_LOCATION);
1044 : : }
1045 : :
1046 : : // Constructor
1047 : 30 : TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus,
1048 : : std::unique_ptr<Type> type = nullptr)
1049 : 30 : : inputs (std::move (inputs)), return_type (std::move (type)),
1050 : 30 : is_invalid (false), locus (locus)
1051 : : {}
1052 : :
1053 : : // Copy constructor with clone
1054 : 0 : TypePathFunction (TypePathFunction const &other)
1055 : 0 : : is_invalid (other.is_invalid)
1056 : : {
1057 : : // guard to protect from null pointer dereference
1058 : 0 : if (other.return_type != nullptr)
1059 : 0 : return_type = other.return_type->clone_type ();
1060 : :
1061 : 0 : inputs.reserve (other.inputs.size ());
1062 : 0 : for (const auto &e : other.inputs)
1063 : 0 : inputs.push_back (e->clone_type ());
1064 : 0 : }
1065 : :
1066 : 30 : ~TypePathFunction () = default;
1067 : :
1068 : : // Overloaded assignment operator to clone type
1069 : : TypePathFunction &operator= (TypePathFunction const &other)
1070 : : {
1071 : : is_invalid = other.is_invalid;
1072 : :
1073 : : // guard to protect from null pointer dereference
1074 : : if (other.return_type != nullptr)
1075 : : return_type = other.return_type->clone_type ();
1076 : : else
1077 : : return_type = nullptr;
1078 : :
1079 : : inputs.reserve (other.inputs.size ());
1080 : : for (const auto &e : other.inputs)
1081 : : inputs.push_back (e->clone_type ());
1082 : :
1083 : : return *this;
1084 : : }
1085 : :
1086 : : // move constructors
1087 : 30 : TypePathFunction (TypePathFunction &&other) = default;
1088 : : TypePathFunction &operator= (TypePathFunction &&other) = default;
1089 : :
1090 : : std::string as_string () const;
1091 : :
1092 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1093 : : const std::vector<std::unique_ptr<Type>> &get_params () const
1094 : : {
1095 : : return inputs;
1096 : : }
1097 : 552 : std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
1098 : :
1099 : : // TODO: is this better? Or is a "vis_pattern" better?
1100 : 462 : Type &get_return_type ()
1101 : : {
1102 : 462 : rust_assert (has_return_type ());
1103 : 462 : return *return_type;
1104 : : }
1105 : :
1106 : 56 : std::unique_ptr<Type> &get_return_type_ptr ()
1107 : : {
1108 : 56 : rust_assert (has_return_type ());
1109 : 56 : return return_type;
1110 : : }
1111 : :
1112 : 5 : location_t get_locus () const { return locus; }
1113 : : };
1114 : :
1115 : : // Segment used in type path with a function argument
1116 : : class TypePathSegmentFunction : public TypePathSegment
1117 : : {
1118 : : TypePathFunction function_path;
1119 : :
1120 : : public:
1121 : 7 : SegmentType get_type () const override { return SegmentType::FUNCTION; }
1122 : :
1123 : : // Constructor with PathIdentSegment and TypePathFn
1124 : 30 : TypePathSegmentFunction (PathIdentSegment ident_segment,
1125 : : bool has_separating_scope_resolution,
1126 : : TypePathFunction function_path, location_t locus)
1127 : 30 : : TypePathSegment (std::move (ident_segment),
1128 : : has_separating_scope_resolution, locus),
1129 : 30 : function_path (std::move (function_path))
1130 : 30 : {}
1131 : :
1132 : : // Constructor with segment name and TypePathFn
1133 : : TypePathSegmentFunction (std::string segment_name,
1134 : : bool has_separating_scope_resolution,
1135 : : TypePathFunction function_path, location_t locus)
1136 : : : TypePathSegment (std::move (segment_name),
1137 : : has_separating_scope_resolution, locus),
1138 : : function_path (std::move (function_path))
1139 : : {}
1140 : :
1141 : : std::string as_string () const override;
1142 : :
1143 : 5 : bool is_ident_only () const override { return false; }
1144 : :
1145 : : void accept_vis (ASTVisitor &vis) override;
1146 : :
1147 : : // TODO: is this better? Or is a "vis_pattern" better?
1148 : 552 : TypePathFunction &get_type_path_function ()
1149 : : {
1150 : 552 : rust_assert (!function_path.is_error ());
1151 : 552 : return function_path;
1152 : : }
1153 : :
1154 : : // Use covariance to override base class method
1155 : 0 : TypePathSegmentFunction *clone_type_path_segment_impl () const override
1156 : : {
1157 : 0 : return new TypePathSegmentFunction (*this);
1158 : : }
1159 : : };
1160 : :
1161 : 63343 : class TypePath : public TypeNoBounds
1162 : : {
1163 : : bool has_opening_scope_resolution;
1164 : : std::vector<std::unique_ptr<TypePathSegment>> segments;
1165 : : location_t locus;
1166 : :
1167 : : protected:
1168 : : /* Use covariance to implement clone function as returning this object
1169 : : * rather than base */
1170 : 50995 : TypePath *clone_type_no_bounds_impl () const override
1171 : : {
1172 : 50995 : return new TypePath (*this);
1173 : : }
1174 : 93 : TypePath *reconstruct_impl () const override
1175 : : {
1176 : 465 : return new TypePath (reconstruct_vec (segments), locus,
1177 : 186 : has_opening_scope_resolution);
1178 : : }
1179 : :
1180 : : public:
1181 : : /* Returns whether the TypePath has an opening scope resolution operator
1182 : : * (i.e. is global path or crate-relative path, not module-relative) */
1183 : 108894 : bool has_opening_scope_resolution_op () const
1184 : : {
1185 : 108894 : return has_opening_scope_resolution;
1186 : : }
1187 : :
1188 : : // Returns whether the TypePath is in an invalid state.
1189 : 69031 : bool is_error () const { return segments.empty (); }
1190 : :
1191 : : // Creates an error state TypePath.
1192 : 621 : static TypePath create_error ()
1193 : : {
1194 : 621 : return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
1195 : 621 : UNDEF_LOCATION);
1196 : : }
1197 : :
1198 : : // Constructor
1199 : 134309 : TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
1200 : : location_t locus, bool has_opening_scope_resolution = false)
1201 : 80453 : : TypeNoBounds (),
1202 : 134309 : has_opening_scope_resolution (has_opening_scope_resolution),
1203 : 134309 : segments (std::move (segments)), locus (locus)
1204 : : {}
1205 : :
1206 : 0 : TypePath (LangItem::Kind lang_item,
1207 : : std::vector<std::unique_ptr<TypePathSegment>> segments,
1208 : : location_t locus, bool has_opening_scope_resolution = false)
1209 : 0 : : TypeNoBounds (),
1210 : 0 : has_opening_scope_resolution (has_opening_scope_resolution),
1211 : 0 : segments (std::move (segments)), locus (locus)
1212 : : {}
1213 : :
1214 : : // Copy constructor with vector clone
1215 : 68414 : TypePath (TypePath const &other)
1216 : 136828 : : has_opening_scope_resolution (other.has_opening_scope_resolution),
1217 : 68414 : locus (other.locus)
1218 : : {
1219 : 68414 : node_id = other.node_id;
1220 : 68414 : segments.reserve (other.segments.size ());
1221 : 139072 : for (const auto &e : other.segments)
1222 : 70658 : segments.push_back (e->clone_type_path_segment ());
1223 : 68414 : }
1224 : :
1225 : : // Overloaded assignment operator with clone
1226 : : TypePath &operator= (TypePath const &other)
1227 : : {
1228 : : node_id = other.node_id;
1229 : : has_opening_scope_resolution = other.has_opening_scope_resolution;
1230 : : locus = other.locus;
1231 : :
1232 : : segments.reserve (other.segments.size ());
1233 : : for (const auto &e : other.segments)
1234 : : segments.push_back (e->clone_type_path_segment ());
1235 : :
1236 : : return *this;
1237 : : }
1238 : :
1239 : : // move constructors
1240 : 52398 : TypePath (TypePath &&other) = default;
1241 : 423 : TypePath &operator= (TypePath &&other) = default;
1242 : :
1243 : : std::string as_string () const override;
1244 : :
1245 : : std::string make_debug_string () const;
1246 : :
1247 : : /* Converts TypePath to SimplePath if possible (i.e. no generic or function
1248 : : * arguments). Otherwise returns an empty SimplePath. */
1249 : : SimplePath as_simple_path () const;
1250 : :
1251 : : // Creates a trait bound with a clone of this type path as its only element.
1252 : : TraitBound *to_trait_bound (bool in_parens) const override;
1253 : :
1254 : 97410 : location_t get_locus () const override final { return locus; }
1255 : 470675 : NodeId get_node_id () const { return node_id; }
1256 : :
1257 : 0 : void mark_for_strip () override {}
1258 : 244164 : bool is_marked_for_strip () const override { return false; }
1259 : :
1260 : : void accept_vis (ASTVisitor &vis) override;
1261 : :
1262 : : // TODO: this seems kinda dodgy
1263 : 3055 : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1264 : : {
1265 : 1094364 : return segments;
1266 : : }
1267 : 53334 : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1268 : : {
1269 : 53336 : return segments;
1270 : : }
1271 : :
1272 : : size_t get_num_segments () const { return segments.size (); }
1273 : : };
1274 : :
1275 : : struct QualifiedPathType
1276 : : {
1277 : : private:
1278 : : std::unique_ptr<Type> type_to_invoke_on;
1279 : : TypePath trait_path;
1280 : : location_t locus;
1281 : : NodeId node_id;
1282 : :
1283 : : public:
1284 : : // Constructor
1285 : 437 : QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
1286 : : location_t locus = UNDEF_LOCATION,
1287 : : TypePath trait_path = TypePath::create_error ())
1288 : 437 : : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
1289 : 437 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
1290 : 437 : {}
1291 : :
1292 : : // Copy constructor uses custom deep copy for Type to preserve polymorphism
1293 : 738 : QualifiedPathType (QualifiedPathType const &other)
1294 : 738 : : trait_path (other.trait_path), locus (other.locus)
1295 : : {
1296 : 738 : node_id = other.node_id;
1297 : : // guard to prevent null dereference
1298 : 738 : if (other.type_to_invoke_on != nullptr)
1299 : 738 : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1300 : 738 : }
1301 : :
1302 : : // default destructor
1303 : 2065 : ~QualifiedPathType () = default;
1304 : :
1305 : : // overload assignment operator to use custom clone method
1306 : : QualifiedPathType &operator= (QualifiedPathType const &other)
1307 : : {
1308 : : node_id = other.node_id;
1309 : : trait_path = other.trait_path;
1310 : : locus = other.locus;
1311 : :
1312 : : // guard to prevent null dereference
1313 : : if (other.type_to_invoke_on != nullptr)
1314 : : type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1315 : : else
1316 : : type_to_invoke_on = nullptr;
1317 : :
1318 : : return *this;
1319 : : }
1320 : :
1321 : : // move constructor
1322 : 1277 : QualifiedPathType (QualifiedPathType &&other) = default;
1323 : 0 : QualifiedPathType &operator= (QualifiedPathType &&other) = default;
1324 : :
1325 : : // Returns whether the qualified path type has a rebind as clause.
1326 : 9218 : bool has_as_clause () const { return !trait_path.is_error (); }
1327 : :
1328 : : // Returns whether the qualified path type is in an error state.
1329 : 10164 : bool is_error () const { return type_to_invoke_on == nullptr; }
1330 : :
1331 : : // Creates an error state qualified path type.
1332 : 0 : static QualifiedPathType create_error ()
1333 : : {
1334 : 0 : return QualifiedPathType (nullptr);
1335 : : }
1336 : :
1337 : : std::string as_string () const;
1338 : :
1339 : 503 : location_t get_locus () const { return locus; }
1340 : :
1341 : : // TODO: is this better? Or is a "vis_pattern" better?
1342 : 8254 : Type &get_type ()
1343 : : {
1344 : 8254 : rust_assert (type_to_invoke_on != nullptr);
1345 : 8254 : return *type_to_invoke_on;
1346 : : }
1347 : :
1348 : 964 : std::unique_ptr<Type> &get_type_ptr ()
1349 : : {
1350 : 964 : rust_assert (type_to_invoke_on != nullptr);
1351 : 964 : return type_to_invoke_on;
1352 : : }
1353 : :
1354 : : // TODO: is this better? Or is a "vis_pattern" better?
1355 : 8326 : TypePath &get_as_type_path ()
1356 : : {
1357 : 8326 : rust_assert (has_as_clause ());
1358 : 8326 : return trait_path;
1359 : : }
1360 : :
1361 : 349 : NodeId get_node_id () const { return node_id; }
1362 : : };
1363 : :
1364 : : /* AST node representing a qualified path-in-expression pattern (path that
1365 : : * allows specifying trait functions) */
1366 : : class QualifiedPathInExpression : public Path, public ExprWithoutBlock
1367 : : {
1368 : : std::vector<Attribute> outer_attrs;
1369 : : QualifiedPathType path_type;
1370 : : location_t locus;
1371 : : NodeId _node_id;
1372 : :
1373 : : public:
1374 : : std::string as_string () const override;
1375 : :
1376 : 114 : QualifiedPathInExpression (QualifiedPathType qual_path_type,
1377 : : std::vector<PathExprSegment> path_segments,
1378 : : std::vector<Attribute> outer_attrs,
1379 : : location_t locus)
1380 : 228 : : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
1381 : 114 : path_type (std::move (qual_path_type)), locus (locus),
1382 : 114 : _node_id (Analysis::Mappings::get ().get_next_node_id ())
1383 : 114 : {}
1384 : :
1385 : : /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1386 : : * elements as params */
1387 : :
1388 : : // Returns whether qualified path in expression is in an error state.
1389 : 526 : bool is_error () const { return path_type.is_error (); }
1390 : :
1391 : : // Creates an error qualified path in expression.
1392 : 0 : static QualifiedPathInExpression create_error ()
1393 : : {
1394 : 0 : return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
1395 : 0 : {}, UNDEF_LOCATION);
1396 : : }
1397 : :
1398 : 310 : location_t get_locus () const override final { return locus; }
1399 : :
1400 : : void accept_vis (ASTVisitor &vis) override;
1401 : :
1402 : : // Invalid if path_type is error, so base stripping on that.
1403 : 0 : void mark_for_strip () override
1404 : : {
1405 : 0 : path_type = QualifiedPathType::create_error ();
1406 : 0 : }
1407 : 526 : bool is_marked_for_strip () const override { return is_error (); }
1408 : :
1409 : : // TODO: is this better? Or is a "vis_pattern" better?
1410 : 2606 : QualifiedPathType &get_qualified_path_type ()
1411 : : {
1412 : 2606 : rust_assert (!path_type.is_error ());
1413 : 2606 : return path_type;
1414 : : }
1415 : :
1416 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1417 : 2840 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1418 : :
1419 : 97 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
1420 : : {
1421 : 97 : outer_attrs = std::move (new_attrs);
1422 : 0 : }
1423 : :
1424 : 114 : NodeId get_node_id () const override { return _node_id; }
1425 : :
1426 : 99 : Expr::Kind get_expr_kind () const override
1427 : : {
1428 : 99 : return Expr::Kind::QualifiedPathInExpression;
1429 : : }
1430 : :
1431 : : protected:
1432 : : /* Use covariance to implement clone function as returning this object
1433 : : * rather than base */
1434 : 0 : QualifiedPathInExpression *clone_pattern_impl () const final override
1435 : : {
1436 : 0 : return clone_qual_path_in_expression_impl ();
1437 : : }
1438 : :
1439 : : /* Use covariance to implement clone function as returning this object
1440 : : * rather than base */
1441 : : QualifiedPathInExpression *
1442 : 0 : clone_expr_without_block_impl () const final override
1443 : : {
1444 : 0 : return clone_qual_path_in_expression_impl ();
1445 : : }
1446 : :
1447 : : /*virtual*/ QualifiedPathInExpression *
1448 : 96 : clone_qual_path_in_expression_impl () const
1449 : : {
1450 : 96 : return new QualifiedPathInExpression (*this);
1451 : : }
1452 : : };
1453 : :
1454 : : /* Represents a qualified path in a type; used for disambiguating trait
1455 : : * function calls */
1456 : : class QualifiedPathInType : public TypeNoBounds
1457 : : {
1458 : : QualifiedPathType path_type;
1459 : : std::unique_ptr<TypePathSegment> associated_segment;
1460 : : std::vector<std::unique_ptr<TypePathSegment>> segments;
1461 : : location_t locus;
1462 : :
1463 : : protected:
1464 : : /* Use covariance to implement clone function as returning this object
1465 : : * rather than base */
1466 : 625 : QualifiedPathInType *clone_type_no_bounds_impl () const override
1467 : : {
1468 : 625 : return new QualifiedPathInType (*this);
1469 : : }
1470 : 0 : QualifiedPathInType *reconstruct_impl () const override
1471 : : {
1472 : 0 : return new QualifiedPathInType (path_type,
1473 : 0 : associated_segment->reconstruct (),
1474 : 0 : reconstruct_vec (segments), locus);
1475 : : }
1476 : :
1477 : : public:
1478 : 323 : QualifiedPathInType (
1479 : : QualifiedPathType qual_path_type,
1480 : : std::unique_ptr<TypePathSegment> associated_segment,
1481 : : std::vector<std::unique_ptr<TypePathSegment>> path_segments,
1482 : : location_t locus)
1483 : 646 : : path_type (std::move (qual_path_type)),
1484 : 323 : associated_segment (std::move (associated_segment)),
1485 : 323 : segments (std::move (path_segments)), locus (locus)
1486 : 323 : {}
1487 : :
1488 : : // Copy constructor with vector clone
1489 : 625 : QualifiedPathInType (QualifiedPathInType const &other)
1490 : 625 : : path_type (other.path_type), locus (other.locus)
1491 : : {
1492 : 625 : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1493 : 625 : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1494 : :
1495 : 625 : segments.reserve (other.segments.size ());
1496 : 625 : for (const auto &e : other.segments)
1497 : 0 : segments.push_back (e->clone_type_path_segment ());
1498 : 625 : }
1499 : :
1500 : : // Overloaded assignment operator with vector clone
1501 : : QualifiedPathInType &operator= (QualifiedPathInType const &other)
1502 : : {
1503 : : auto seg = other.associated_segment->clone_type_path_segment_impl ();
1504 : : associated_segment = std::unique_ptr<TypePathSegment> (seg);
1505 : :
1506 : : path_type = other.path_type;
1507 : : locus = other.locus;
1508 : :
1509 : : segments.reserve (other.segments.size ());
1510 : : for (const auto &e : other.segments)
1511 : : segments.push_back (e->clone_type_path_segment ());
1512 : :
1513 : : return *this;
1514 : : }
1515 : :
1516 : : // move constructors
1517 : 323 : QualifiedPathInType (QualifiedPathInType &&other) = default;
1518 : : QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
1519 : :
1520 : : // Returns whether qualified path in type is in an error state.
1521 : 323 : bool is_error () const { return path_type.is_error (); }
1522 : :
1523 : : // Creates an error state qualified path in type.
1524 : 0 : static QualifiedPathInType create_error ()
1525 : : {
1526 : 0 : return QualifiedPathInType (
1527 : 0 : QualifiedPathType::create_error (), nullptr,
1528 : 0 : std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
1529 : : }
1530 : :
1531 : : std::string as_string () const override;
1532 : :
1533 : : void accept_vis (ASTVisitor &vis) override;
1534 : :
1535 : : // TODO: is this better? Or is a "vis_pattern" better?
1536 : 7317 : QualifiedPathType &get_qualified_path_type ()
1537 : : {
1538 : 7317 : rust_assert (!path_type.is_error ());
1539 : 7317 : return path_type;
1540 : : }
1541 : :
1542 : : std::unique_ptr<TypePathSegment> &get_associated_segment ()
1543 : : {
1544 : 4678 : return associated_segment;
1545 : : }
1546 : :
1547 : : // TODO: this seems kinda dodgy
1548 : : std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
1549 : : {
1550 : 5373 : return segments;
1551 : : }
1552 : : const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
1553 : : {
1554 : : return segments;
1555 : : }
1556 : :
1557 : 241 : location_t get_locus () const override final { return locus; }
1558 : : };
1559 : : } // namespace AST
1560 : : } // namespace Rust
1561 : :
1562 : : #endif
|