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