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