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