Daily bump.
[official-gcc.git] / gcc / rust / ast / rust-path.h
blob46d1a930d66354516d0cfc92f8c8c708cd93c105
1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
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. */
24 #include "rust-ast.h"
25 #include "system.h"
27 namespace Rust {
28 namespace AST {
30 // The "identifier" (not generic args) aspect of each path expression segment
31 class PathIdentSegment
33 std::string segment_name;
34 location_t locus;
36 // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
37 public:
38 PathIdentSegment (std::string segment_name, location_t locus)
39 : segment_name (std::move (segment_name)), locus (locus)
42 // Creates an error PathIdentSegment.
43 static PathIdentSegment create_error ()
45 return PathIdentSegment ("", UNDEF_LOCATION);
48 // Returns whether PathIdentSegment is in an error state.
49 bool is_error () const { return segment_name.empty (); }
51 std::string as_string () const { return segment_name; }
53 location_t get_locus () const { return locus; }
55 bool is_super_segment () const { return as_string ().compare ("super") == 0; }
56 bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
57 bool is_lower_self () const { return as_string ().compare ("self") == 0; }
58 bool is_big_self () const { return as_string ().compare ("Self") == 0; }
61 // A binding of an identifier to a type used in generic arguments in paths
62 struct GenericArgsBinding
64 private:
65 Identifier identifier;
66 std::unique_ptr<Type> type;
67 location_t locus;
69 public:
70 // Returns whether binding is in an error state.
71 bool is_error () const
73 return type == nullptr;
74 // and also identifier is empty, but cheaper computation
77 // Creates an error state generic args binding.
78 static GenericArgsBinding create_error ()
80 return GenericArgsBinding ({""}, nullptr);
83 // Pointer type for type in constructor to enable polymorphism
84 GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
85 location_t locus = UNDEF_LOCATION)
86 : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
89 // Copy constructor has to deep copy the type as it is a unique pointer
90 GenericArgsBinding (GenericArgsBinding const &other)
91 : identifier (other.identifier), locus (other.locus)
93 // guard to protect from null pointer dereference
94 if (other.type != nullptr)
95 type = other.type->clone_type ();
98 // default destructor
99 ~GenericArgsBinding () = default;
101 // Overload assignment operator to deep copy the pointed-to type
102 GenericArgsBinding &operator= (GenericArgsBinding const &other)
104 identifier = other.identifier;
105 locus = other.locus;
107 // guard to protect from null pointer dereference
108 if (other.type != nullptr)
109 type = other.type->clone_type ();
110 else
111 type = nullptr;
113 return *this;
116 // move constructors
117 GenericArgsBinding (GenericArgsBinding &&other) = default;
118 GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
120 std::string as_string () const;
122 // TODO: is this better? Or is a "vis_pattern" better?
123 Type &get_type ()
125 rust_assert (type != nullptr);
126 return *type;
129 std::unique_ptr<Type> &get_type_ptr ()
131 rust_assert (type != nullptr);
132 return type;
135 location_t get_locus () const { return locus; }
137 Identifier get_identifier () const { return identifier; }
140 /* Class representing a const generic application */
141 class GenericArg
143 public:
145 * const generic arguments cannot always be differentiated with generic type
146 * arguments during parsing, e.g:
147 * ```rust
148 * let a: Foo<N>;
149 * ```
151 * Is N a type? A constant defined elsewhere? The parser cannot know, and must
152 * not draw any conclusions. We must wait until later passes of the compiler
153 * to decide whether this refers to a constant item or a type.
155 * On the other hand, simple expressions like literals or block expressions
156 * will always be constant expressions: There is no ambiguity at all.
158 enum class Kind
160 Error,
161 Const, // A const value
162 Type, // A type argument (not discernable during parsing)
163 Either, // Either a type or a const value, cleared up during resolving
166 static GenericArg create_error ()
168 return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION);
171 static GenericArg create_const (std::unique_ptr<Expr> expression)
173 auto locus = expression->get_locus ();
174 return GenericArg (std::move (expression), nullptr, {""}, Kind::Const,
175 locus);
178 static GenericArg create_type (std::unique_ptr<Type> type)
180 auto locus = type->get_locus ();
181 return GenericArg (nullptr, std::move (type), {""}, Kind::Type, locus);
184 static GenericArg create_ambiguous (Identifier path, location_t locus)
186 return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
189 GenericArg (const GenericArg &other)
190 : path (other.path), kind (other.kind), locus (other.locus)
192 if (other.expression)
193 expression = other.expression->clone_expr ();
194 if (other.type)
195 type = other.type->clone_type ();
198 GenericArg operator= (const GenericArg &other)
200 kind = other.kind;
201 path = other.path;
202 locus = other.locus;
204 if (other.expression)
205 expression = other.expression->clone_expr ();
206 if (other.type)
207 type = other.type->clone_type ();
209 return *this;
212 GenericArg (GenericArg &&other) = default;
213 GenericArg &operator= (GenericArg &&other) = default;
215 bool is_error () const { return kind == Kind::Error; }
217 Kind get_kind () const { return kind; }
218 location_t get_locus () const { return locus; }
220 void accept_vis (AST::ASTVisitor &visitor)
222 switch (get_kind ())
224 case Kind::Const:
225 get_expression ().accept_vis (visitor);
226 break;
227 case Kind::Type:
228 get_type ().accept_vis (visitor);
229 break;
230 case Kind::Either:
231 break;
232 case Kind::Error:
233 rust_unreachable ();
237 Expr &get_expression ()
239 rust_assert (kind == Kind::Const);
241 return *expression;
244 std::unique_ptr<Expr> &get_expression_ptr ()
246 rust_assert (kind == Kind::Const);
248 return expression;
251 Type &get_type ()
253 rust_assert (kind == Kind::Type);
255 return *type;
258 std::unique_ptr<Type> &get_type_ptr ()
260 rust_assert (kind == Kind::Type);
262 return type;
265 const std::string get_path () const
267 rust_assert (kind == Kind::Either);
269 return path.as_string ();
272 std::string as_string () const
274 switch (get_kind ())
276 case Kind::Error:
277 rust_unreachable ();
278 case Kind::Either:
279 return "Ambiguous: " + path.as_string ();
280 case Kind::Const:
281 return "Const: { " + expression->as_string () + " }";
282 case Kind::Type:
283 return "Type: " + type->as_string ();
286 return "";
290 * Disambiguate an ambiguous generic argument to a const generic argument,
291 * unequivocally
293 GenericArg disambiguate_to_const () const;
296 * Disambiguate an ambiguous generic argument to a type argument,
297 * unequivocally
299 GenericArg disambiguate_to_type () const;
301 private:
302 GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
303 Identifier path, Kind kind, location_t locus)
304 : expression (std::move (expression)), type (std::move (type)),
305 path (std::move (path)), kind (kind), locus (locus)
309 * Expression associated with a `Clear` const generic application
310 * A null pointer here is allowed in the case that the const argument is
311 * ambiguous.
313 std::unique_ptr<Expr> expression;
316 * If the argument ends up being a type argument instead. A null pointer will
317 * be present here until the resolving phase.
319 std::unique_ptr<Type> type;
322 * Optional path which cannot be differentiated between a constant item and
323 * a type. Only used for ambiguous const generic arguments, otherwise
324 * empty.
326 Identifier path;
328 /* Which kind of const generic application are we dealing with */
329 Kind kind;
331 location_t locus;
335 * Representation of const generic parameters
337 class ConstGenericParam : public GenericParam
339 /* Name of the parameter */
340 Identifier name;
342 /* Mandatory type of the const parameter - a null pointer is an error */
343 std::unique_ptr<AST::Type> type;
346 * Default value for the const generic parameter
348 GenericArg default_value;
350 Attribute outer_attr;
351 location_t locus;
353 public:
354 ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
355 GenericArg default_value, Attribute outer_attr,
356 location_t locus)
357 : name (name), type (std::move (type)),
358 default_value (std::move (default_value)), outer_attr (outer_attr),
359 locus (locus)
362 ConstGenericParam (const ConstGenericParam &other)
363 : GenericParam (), name (other.name), type (other.type->clone_type ()),
364 default_value (other.default_value), outer_attr (other.outer_attr),
365 locus (other.locus)
368 bool has_type () const { return type != nullptr; }
369 bool has_default_value () const { return !default_value.is_error (); }
371 const Identifier &get_name () const { return name; }
373 Attribute &get_outer_attribute () { return outer_attr; }
375 AST::Type &get_type ()
377 rust_assert (has_type ());
379 return *type;
382 GenericArg &get_default_value ()
384 rust_assert (has_default_value ());
386 return default_value;
389 const GenericArg &get_default_value () const
391 rust_assert (has_default_value ());
393 return default_value;
396 std::string as_string () const override;
398 void accept_vis (ASTVisitor &vis) override;
400 location_t get_locus () const override final { return locus; }
402 Kind get_kind () const override final { return Kind::Const; }
404 protected:
405 /* Use covariance to implement clone function as returning this object rather
406 * than base */
407 ConstGenericParam *clone_generic_param_impl () const override
409 return new ConstGenericParam (*this);
413 // Generic arguments allowed in each path expression segment - inline?
414 struct GenericArgs
416 std::vector<Lifetime> lifetime_args;
417 std::vector<GenericArg> generic_args;
418 std::vector<GenericArgsBinding> binding_args;
419 location_t locus;
421 public:
422 // Returns true if there are any generic arguments
423 bool has_generic_args () const
425 return !(lifetime_args.empty () && generic_args.empty ()
426 && binding_args.empty ());
429 GenericArgs (std::vector<Lifetime> lifetime_args,
430 std::vector<GenericArg> generic_args,
431 std::vector<GenericArgsBinding> binding_args,
432 location_t locus = UNDEF_LOCATION)
433 : lifetime_args (std::move (lifetime_args)),
434 generic_args (std::move (generic_args)),
435 binding_args (std::move (binding_args)), locus (locus)
438 // copy constructor with vector clone
439 GenericArgs (GenericArgs const &other)
440 : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
441 locus (other.locus)
443 generic_args.clear ();
444 generic_args.reserve (other.generic_args.size ());
445 for (const auto &arg : other.generic_args)
447 generic_args.push_back (GenericArg (arg));
451 ~GenericArgs () = default;
453 // overloaded assignment operator to vector clone
454 GenericArgs &operator= (GenericArgs const &other)
456 lifetime_args = other.lifetime_args;
457 binding_args = other.binding_args;
458 locus = other.locus;
460 generic_args.clear ();
461 generic_args.reserve (other.generic_args.size ());
462 for (const auto &arg : other.generic_args)
464 generic_args.push_back (GenericArg (arg));
467 return *this;
470 // move constructors
471 GenericArgs (GenericArgs &&other) = default;
472 GenericArgs &operator= (GenericArgs &&other) = default;
474 // Creates an empty GenericArgs (no arguments)
475 static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
477 std::string as_string () const;
479 // TODO: is this better? Or is a "vis_pattern" better?
480 std::vector<GenericArg> &get_generic_args () { return generic_args; }
482 // TODO: is this better? Or is a "vis_pattern" better?
483 std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
485 std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
487 location_t get_locus () { return locus; }
490 /* A segment of a path in expression, including an identifier aspect and maybe
491 * generic args */
492 class PathExprSegment
493 { // or should this extend PathIdentSegment?
494 private:
495 PathIdentSegment segment_name;
496 GenericArgs generic_args;
497 location_t locus;
498 NodeId node_id;
500 public:
501 // Returns true if there are any generic arguments
502 bool has_generic_args () const { return generic_args.has_generic_args (); }
504 // Constructor for segment (from IdentSegment and GenericArgs)
505 PathExprSegment (PathIdentSegment segment_name, location_t locus,
506 GenericArgs generic_args = GenericArgs::create_empty ())
507 : segment_name (std::move (segment_name)),
508 generic_args (std::move (generic_args)), locus (locus),
509 node_id (Analysis::Mappings::get ()->get_next_node_id ())
512 /* Constructor for segment with generic arguments (from segment name and all
513 * args) */
514 PathExprSegment (std::string segment_name, location_t locus,
515 std::vector<Lifetime> lifetime_args = {},
516 std::vector<GenericArg> generic_args = {},
517 std::vector<GenericArgsBinding> binding_args = {})
518 : segment_name (PathIdentSegment (std::move (segment_name), locus)),
519 generic_args (GenericArgs (std::move (lifetime_args),
520 std::move (generic_args),
521 std::move (binding_args))),
522 locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
525 // Returns whether path expression segment is in an error state.
526 bool is_error () const { return segment_name.is_error (); }
528 // Creates an error-state path expression segment.
529 static PathExprSegment create_error ()
531 return PathExprSegment (PathIdentSegment::create_error (), UNDEF_LOCATION);
534 std::string as_string () const;
536 location_t get_locus () const { return locus; }
538 // TODO: is this better? Or is a "vis_pattern" better?
539 GenericArgs &get_generic_args ()
541 rust_assert (has_generic_args ());
542 return generic_args;
545 PathIdentSegment &get_ident_segment () { return segment_name; }
546 const PathIdentSegment &get_ident_segment () const { return segment_name; }
548 NodeId get_node_id () const { return node_id; }
550 bool is_super_path_seg () const
552 return !has_generic_args () && get_ident_segment ().is_super_segment ();
555 bool is_crate_path_seg () const
557 return !has_generic_args () && get_ident_segment ().is_crate_segment ();
560 bool is_lower_self_seg () const
562 return !has_generic_args () && get_ident_segment ().is_lower_self ();
566 // AST node representing a pattern that involves a "path" - abstract base
567 // class
568 class PathPattern : public Pattern
570 std::vector<PathExprSegment> segments;
572 protected:
573 PathPattern (std::vector<PathExprSegment> segments)
574 : segments (std::move (segments))
577 // Returns whether path has segments.
578 bool has_segments () const { return !segments.empty (); }
580 /* Converts path segments to their equivalent SimplePath segments if
581 * possible, and creates a SimplePath from them. */
582 SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
584 // Removes all segments of the path.
585 void remove_all_segments ()
587 segments.clear ();
588 segments.shrink_to_fit ();
591 public:
592 /* Returns whether the path is a single segment (excluding qualified path
593 * initial as segment). */
594 bool is_single_segment () const { return segments.size () == 1; }
596 std::string as_string () const override;
598 // TODO: this seems kinda dodgy
599 std::vector<PathExprSegment> &get_segments () { return segments; }
600 const std::vector<PathExprSegment> &get_segments () const { return segments; }
602 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
605 /* AST node representing a path-in-expression pattern (path that allows
606 * generic arguments) */
607 class PathInExpression : public PathPattern, public PathExpr
609 std::vector<Attribute> outer_attrs;
610 bool has_opening_scope_resolution;
611 location_t locus;
612 NodeId _node_id;
614 public:
615 std::string as_string () const override;
617 // Constructor
618 PathInExpression (std::vector<PathExprSegment> path_segments,
619 std::vector<Attribute> outer_attrs, location_t locus,
620 bool has_opening_scope_resolution = false)
621 : PathPattern (std::move (path_segments)),
622 outer_attrs (std::move (outer_attrs)),
623 has_opening_scope_resolution (has_opening_scope_resolution),
624 locus (locus), _node_id (Analysis::Mappings::get ()->get_next_node_id ())
627 // Creates an error state path in expression.
628 static PathInExpression create_error ()
630 return PathInExpression ({}, {}, UNDEF_LOCATION);
633 // Returns whether path in expression is in an error state.
634 bool is_error () const { return !has_segments (); }
636 /* Converts PathInExpression to SimplePath if possible (i.e. no generic
637 * arguments). Otherwise returns an empty SimplePath. */
638 SimplePath as_simple_path () const
640 /* delegate to parent class as can't access segments. however,
641 * QualifiedPathInExpression conversion to simple path wouldn't make
642 * sense, so the method in the parent class should be protected, not
643 * public. Have to pass in opening scope resolution as parent class has no
644 * access to it.
646 return convert_to_simple_path (has_opening_scope_resolution);
649 location_t get_locus () const override final { return locus; }
651 void accept_vis (ASTVisitor &vis) override;
653 // Invalid if path is empty (error state), so base stripping on that.
654 void mark_for_strip () override { remove_all_segments (); }
655 bool is_marked_for_strip () const override { return is_error (); }
657 bool opening_scope_resolution () const
659 return has_opening_scope_resolution;
662 NodeId get_node_id () const override { return _node_id; }
664 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
665 std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
667 void set_outer_attrs (std::vector<Attribute> new_attrs) override
669 outer_attrs = std::move (new_attrs);
672 NodeId get_pattern_node_id () const { return get_node_id (); }
674 PathExprSegment &get_final_segment () { return get_segments ().back (); }
675 const PathExprSegment &get_final_segment () const
677 return get_segments ().back ();
680 protected:
681 /* Use covariance to implement clone function as returning this object
682 * rather than base */
683 PathInExpression *clone_pattern_impl () const final override
685 return clone_path_in_expression_impl ();
688 /* Use covariance to implement clone function as returning this object
689 * rather than base */
690 PathInExpression *clone_expr_without_block_impl () const final override
692 return clone_path_in_expression_impl ();
695 /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
697 return new PathInExpression (*this);
701 /* Base class for segments used in type paths - not abstract (represents an
702 * ident-only segment) */
703 class TypePathSegment
705 public:
706 enum SegmentType
708 REG,
709 GENERIC,
710 FUNCTION
713 private:
714 PathIdentSegment ident_segment;
715 location_t locus;
717 protected:
718 /* This is protected because it is only really used by derived classes, not
719 * the base. */
720 bool has_separating_scope_resolution;
721 NodeId node_id;
723 public:
724 // Clone function implementation - not pure virtual as overrided by
725 // subclasses
726 virtual TypePathSegment *clone_type_path_segment_impl () const
728 return new TypePathSegment (*this);
731 public:
732 virtual ~TypePathSegment () {}
734 virtual SegmentType get_type () const { return SegmentType::REG; }
736 // Unique pointer custom clone function
737 std::unique_ptr<TypePathSegment> clone_type_path_segment () const
739 return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
742 TypePathSegment (PathIdentSegment ident_segment,
743 bool has_separating_scope_resolution, location_t locus)
744 : ident_segment (std::move (ident_segment)), locus (locus),
745 has_separating_scope_resolution (has_separating_scope_resolution),
746 node_id (Analysis::Mappings::get ()->get_next_node_id ())
749 TypePathSegment (std::string segment_name,
750 bool has_separating_scope_resolution, location_t locus)
751 : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
752 locus (locus),
753 has_separating_scope_resolution (has_separating_scope_resolution),
754 node_id (Analysis::Mappings::get ()->get_next_node_id ())
757 TypePathSegment (TypePathSegment const &other)
758 : ident_segment (other.ident_segment), locus (other.locus),
759 has_separating_scope_resolution (other.has_separating_scope_resolution),
760 node_id (other.node_id)
763 TypePathSegment &operator= (TypePathSegment const &other)
765 ident_segment = other.ident_segment;
766 locus = other.locus;
767 has_separating_scope_resolution = other.has_separating_scope_resolution;
768 node_id = other.node_id;
770 return *this;
773 TypePathSegment (TypePathSegment &&other) = default;
774 TypePathSegment &operator= (TypePathSegment &&other) = default;
776 virtual std::string as_string () const { return ident_segment.as_string (); }
778 /* Returns whether the type path segment is in an error state. May be
779 * virtual in future. */
780 bool is_error () const { return ident_segment.is_error (); }
782 /* Returns whether segment is identifier only (as opposed to generic args or
783 * function). Overridden in derived classes with other segments. */
784 virtual bool is_ident_only () const { return true; }
786 location_t get_locus () const { return locus; }
788 // not pure virtual as class not abstract
789 virtual void accept_vis (ASTVisitor &vis);
791 bool get_separating_scope_resolution () const
793 return has_separating_scope_resolution;
796 PathIdentSegment &get_ident_segment () { return ident_segment; };
797 const PathIdentSegment &get_ident_segment () const { return ident_segment; };
799 NodeId get_node_id () const { return node_id; }
801 bool is_crate_path_seg () const
803 return get_ident_segment ().is_crate_segment ();
805 bool is_super_path_seg () const
807 return get_ident_segment ().is_super_segment ();
809 bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
810 bool is_lower_self_seg () const
812 return get_ident_segment ().is_lower_self ();
816 // Segment used in type path with generic args
817 class TypePathSegmentGeneric : public TypePathSegment
819 GenericArgs generic_args;
821 public:
822 SegmentType get_type () const override { return SegmentType::GENERIC; }
824 bool has_generic_args () const { return generic_args.has_generic_args (); }
826 bool is_ident_only () const override { return false; }
828 // Constructor with PathIdentSegment and GenericArgs
829 TypePathSegmentGeneric (PathIdentSegment ident_segment,
830 bool has_separating_scope_resolution,
831 GenericArgs generic_args, location_t locus)
832 : TypePathSegment (std::move (ident_segment),
833 has_separating_scope_resolution, locus),
834 generic_args (std::move (generic_args))
837 // Constructor from segment name and all args
838 TypePathSegmentGeneric (std::string segment_name,
839 bool has_separating_scope_resolution,
840 std::vector<Lifetime> lifetime_args,
841 std::vector<GenericArg> generic_args,
842 std::vector<GenericArgsBinding> binding_args,
843 location_t locus)
844 : TypePathSegment (std::move (segment_name),
845 has_separating_scope_resolution, locus),
846 generic_args (GenericArgs (std::move (lifetime_args),
847 std::move (generic_args),
848 std::move (binding_args)))
851 // Copy constructor with vector clone
852 TypePathSegmentGeneric (TypePathSegmentGeneric const &other)
853 : TypePathSegment (other), generic_args (other.generic_args)
856 // Overloaded assignment operator with vector clone
857 TypePathSegmentGeneric &operator= (TypePathSegmentGeneric const &other)
859 generic_args = other.generic_args;
861 return *this;
864 // move constructors
865 TypePathSegmentGeneric (TypePathSegmentGeneric &&other) = default;
866 TypePathSegmentGeneric &operator= (TypePathSegmentGeneric &&other) = default;
868 std::string as_string () const override;
870 void accept_vis (ASTVisitor &vis) override;
872 // TODO: is this better? Or is a "vis_pattern" better?
873 GenericArgs &get_generic_args ()
875 rust_assert (has_generic_args ());
876 return generic_args;
879 // Use covariance to override base class method
880 TypePathSegmentGeneric *clone_type_path_segment_impl () const override
882 return new TypePathSegmentGeneric (*this);
886 // A function as represented in a type path
887 struct TypePathFunction
889 private:
890 // TODO: remove
891 /*bool has_inputs;
892 TypePathFnInputs inputs;*/
893 // inlined from TypePathFnInputs
894 std::vector<std::unique_ptr<Type> > inputs;
896 // bool has_type;
897 std::unique_ptr<Type> return_type;
899 // FIXME: think of better way to mark as invalid than taking up storage
900 bool is_invalid;
902 location_t locus;
904 protected:
905 // Constructor only used to create invalid type path functions.
906 TypePathFunction (bool is_invalid, location_t locus)
907 : is_invalid (is_invalid), locus (locus)
910 public:
911 // Returns whether the return type of the function has been specified.
912 bool has_return_type () const { return return_type != nullptr; }
914 // Returns whether the function has inputs.
915 bool has_inputs () const { return !inputs.empty (); }
917 // Returns whether function is in an error state.
918 bool is_error () const { return is_invalid; }
920 // Creates an error state function.
921 static TypePathFunction create_error ()
923 return TypePathFunction (true, UNDEF_LOCATION);
926 // Constructor
927 TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
928 location_t locus, std::unique_ptr<Type> type = nullptr)
929 : inputs (std::move (inputs)), return_type (std::move (type)),
930 is_invalid (false), locus (locus)
933 // Copy constructor with clone
934 TypePathFunction (TypePathFunction const &other)
935 : is_invalid (other.is_invalid)
937 // guard to protect from null pointer dereference
938 if (other.return_type != nullptr)
939 return_type = other.return_type->clone_type ();
941 inputs.reserve (other.inputs.size ());
942 for (const auto &e : other.inputs)
943 inputs.push_back (e->clone_type ());
946 ~TypePathFunction () = default;
948 // Overloaded assignment operator to clone type
949 TypePathFunction &operator= (TypePathFunction const &other)
951 is_invalid = other.is_invalid;
953 // guard to protect from null pointer dereference
954 if (other.return_type != nullptr)
955 return_type = other.return_type->clone_type ();
956 else
957 return_type = nullptr;
959 inputs.reserve (other.inputs.size ());
960 for (const auto &e : other.inputs)
961 inputs.push_back (e->clone_type ());
963 return *this;
966 // move constructors
967 TypePathFunction (TypePathFunction &&other) = default;
968 TypePathFunction &operator= (TypePathFunction &&other) = default;
970 std::string as_string () const;
972 // TODO: this mutable getter seems really dodgy. Think up better way.
973 const std::vector<std::unique_ptr<Type> > &get_params () const
975 return inputs;
977 std::vector<std::unique_ptr<Type> > &get_params () { return inputs; }
979 // TODO: is this better? Or is a "vis_pattern" better?
980 Type &get_return_type ()
982 rust_assert (has_return_type ());
983 return *return_type;
986 std::unique_ptr<Type> &get_return_type_ptr ()
988 rust_assert (has_return_type ());
989 return return_type;
992 location_t get_locus () const { return locus; }
995 // Segment used in type path with a function argument
996 class TypePathSegmentFunction : public TypePathSegment
998 TypePathFunction function_path;
1000 public:
1001 SegmentType get_type () const override { return SegmentType::FUNCTION; }
1003 // Constructor with PathIdentSegment and TypePathFn
1004 TypePathSegmentFunction (PathIdentSegment ident_segment,
1005 bool has_separating_scope_resolution,
1006 TypePathFunction function_path, location_t locus)
1007 : TypePathSegment (std::move (ident_segment),
1008 has_separating_scope_resolution, locus),
1009 function_path (std::move (function_path))
1012 // Constructor with segment name and TypePathFn
1013 TypePathSegmentFunction (std::string segment_name,
1014 bool has_separating_scope_resolution,
1015 TypePathFunction function_path, location_t locus)
1016 : TypePathSegment (std::move (segment_name),
1017 has_separating_scope_resolution, locus),
1018 function_path (std::move (function_path))
1021 std::string as_string () const override;
1023 bool is_ident_only () const override { return false; }
1025 void accept_vis (ASTVisitor &vis) override;
1027 // TODO: is this better? Or is a "vis_pattern" better?
1028 TypePathFunction &get_type_path_function ()
1030 rust_assert (!function_path.is_error ());
1031 return function_path;
1034 // Use covariance to override base class method
1035 TypePathSegmentFunction *clone_type_path_segment_impl () const override
1037 return new TypePathSegmentFunction (*this);
1041 // Path used inside types
1042 class TypePath : public TypeNoBounds
1044 bool has_opening_scope_resolution;
1045 std::vector<std::unique_ptr<TypePathSegment> > segments;
1046 location_t locus;
1048 protected:
1049 /* Use covariance to implement clone function as returning this object
1050 * rather than base */
1051 TypePath *clone_type_no_bounds_impl () const override
1053 return new TypePath (*this);
1056 public:
1057 /* Returns whether the TypePath has an opening scope resolution operator
1058 * (i.e. is global path or crate-relative path, not module-relative) */
1059 bool has_opening_scope_resolution_op () const
1061 return has_opening_scope_resolution;
1064 // Returns whether the TypePath is in an invalid state.
1065 bool is_error () const { return segments.empty (); }
1067 // Creates an error state TypePath.
1068 static TypePath create_error ()
1070 return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
1071 UNDEF_LOCATION);
1074 // Constructor
1075 TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
1076 location_t locus, bool has_opening_scope_resolution = false)
1077 : TypeNoBounds (),
1078 has_opening_scope_resolution (has_opening_scope_resolution),
1079 segments (std::move (segments)), locus (locus)
1082 // Copy constructor with vector clone
1083 TypePath (TypePath const &other)
1084 : has_opening_scope_resolution (other.has_opening_scope_resolution),
1085 locus (other.locus)
1087 node_id = other.node_id;
1088 segments.reserve (other.segments.size ());
1089 for (const auto &e : other.segments)
1090 segments.push_back (e->clone_type_path_segment ());
1093 // Overloaded assignment operator with clone
1094 TypePath &operator= (TypePath const &other)
1096 node_id = other.node_id;
1097 has_opening_scope_resolution = other.has_opening_scope_resolution;
1098 locus = other.locus;
1100 segments.reserve (other.segments.size ());
1101 for (const auto &e : other.segments)
1102 segments.push_back (e->clone_type_path_segment ());
1104 return *this;
1107 // move constructors
1108 TypePath (TypePath &&other) = default;
1109 TypePath &operator= (TypePath &&other) = default;
1111 std::string as_string () const override;
1113 /* Converts TypePath to SimplePath if possible (i.e. no generic or function
1114 * arguments). Otherwise returns an empty SimplePath. */
1115 SimplePath as_simple_path () const;
1117 // Creates a trait bound with a clone of this type path as its only element.
1118 TraitBound *to_trait_bound (bool in_parens) const override;
1120 location_t get_locus () const override final { return locus; }
1122 void accept_vis (ASTVisitor &vis) override;
1124 // TODO: this seems kinda dodgy
1125 std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
1127 return segments;
1129 const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
1131 return segments;
1134 size_t get_num_segments () const { return segments.size (); }
1137 struct QualifiedPathType
1139 private:
1140 std::unique_ptr<Type> type_to_invoke_on;
1141 TypePath trait_path;
1142 location_t locus;
1143 NodeId node_id;
1145 public:
1146 // Constructor
1147 QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
1148 location_t locus = UNDEF_LOCATION,
1149 TypePath trait_path = TypePath::create_error ())
1150 : type_to_invoke_on (std::move (invoke_on_type)),
1151 trait_path (std::move (trait_path)), locus (locus),
1152 node_id (Analysis::Mappings::get ()->get_next_node_id ())
1155 // Copy constructor uses custom deep copy for Type to preserve polymorphism
1156 QualifiedPathType (QualifiedPathType const &other)
1157 : trait_path (other.trait_path), locus (other.locus)
1159 node_id = other.node_id;
1160 // guard to prevent null dereference
1161 if (other.type_to_invoke_on != nullptr)
1162 type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1165 // default destructor
1166 ~QualifiedPathType () = default;
1168 // overload assignment operator to use custom clone method
1169 QualifiedPathType &operator= (QualifiedPathType const &other)
1171 node_id = other.node_id;
1172 trait_path = other.trait_path;
1173 locus = other.locus;
1175 // guard to prevent null dereference
1176 if (other.type_to_invoke_on != nullptr)
1177 type_to_invoke_on = other.type_to_invoke_on->clone_type ();
1178 else
1179 type_to_invoke_on = nullptr;
1181 return *this;
1184 // move constructor
1185 QualifiedPathType (QualifiedPathType &&other) = default;
1186 QualifiedPathType &operator= (QualifiedPathType &&other) = default;
1188 // Returns whether the qualified path type has a rebind as clause.
1189 bool has_as_clause () const { return !trait_path.is_error (); }
1191 // Returns whether the qualified path type is in an error state.
1192 bool is_error () const { return type_to_invoke_on == nullptr; }
1194 // Creates an error state qualified path type.
1195 static QualifiedPathType create_error ()
1197 return QualifiedPathType (nullptr);
1200 std::string as_string () const;
1202 location_t get_locus () const { return locus; }
1204 // TODO: is this better? Or is a "vis_pattern" better?
1205 Type &get_type ()
1207 rust_assert (type_to_invoke_on != nullptr);
1208 return *type_to_invoke_on;
1211 std::unique_ptr<Type> &get_type_ptr ()
1213 rust_assert (type_to_invoke_on != nullptr);
1214 return type_to_invoke_on;
1217 // TODO: is this better? Or is a "vis_pattern" better?
1218 TypePath &get_as_type_path ()
1220 rust_assert (has_as_clause ());
1221 return trait_path;
1224 NodeId get_node_id () const { return node_id; }
1227 /* AST node representing a qualified path-in-expression pattern (path that
1228 * allows specifying trait functions) */
1229 class QualifiedPathInExpression : public PathPattern, public PathExpr
1231 std::vector<Attribute> outer_attrs;
1232 QualifiedPathType path_type;
1233 location_t locus;
1234 NodeId _node_id;
1236 public:
1237 std::string as_string () const override;
1239 QualifiedPathInExpression (QualifiedPathType qual_path_type,
1240 std::vector<PathExprSegment> path_segments,
1241 std::vector<Attribute> outer_attrs,
1242 location_t locus)
1243 : PathPattern (std::move (path_segments)),
1244 outer_attrs (std::move (outer_attrs)),
1245 path_type (std::move (qual_path_type)), locus (locus),
1246 _node_id (Analysis::Mappings::get ()->get_next_node_id ())
1249 /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1250 * elements as params */
1252 // Returns whether qualified path in expression is in an error state.
1253 bool is_error () const { return path_type.is_error (); }
1255 // Creates an error qualified path in expression.
1256 static QualifiedPathInExpression create_error ()
1258 return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
1259 {}, UNDEF_LOCATION);
1262 location_t get_locus () const override final { return locus; }
1264 void accept_vis (ASTVisitor &vis) override;
1266 // Invalid if path_type is error, so base stripping on that.
1267 void mark_for_strip () override
1269 path_type = QualifiedPathType::create_error ();
1271 bool is_marked_for_strip () const override { return is_error (); }
1273 // TODO: is this better? Or is a "vis_pattern" better?
1274 QualifiedPathType &get_qualified_path_type ()
1276 rust_assert (!path_type.is_error ());
1277 return path_type;
1280 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1281 std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1283 void set_outer_attrs (std::vector<Attribute> new_attrs) override
1285 outer_attrs = std::move (new_attrs);
1288 NodeId get_node_id () const override { return _node_id; }
1290 protected:
1291 /* Use covariance to implement clone function as returning this object
1292 * rather than base */
1293 QualifiedPathInExpression *clone_pattern_impl () const final override
1295 return clone_qual_path_in_expression_impl ();
1298 /* Use covariance to implement clone function as returning this object
1299 * rather than base */
1300 QualifiedPathInExpression *
1301 clone_expr_without_block_impl () const final override
1303 return clone_qual_path_in_expression_impl ();
1306 /*virtual*/ QualifiedPathInExpression *
1307 clone_qual_path_in_expression_impl () const
1309 return new QualifiedPathInExpression (*this);
1313 /* Represents a qualified path in a type; used for disambiguating trait
1314 * function calls */
1315 class QualifiedPathInType : public TypeNoBounds
1317 QualifiedPathType path_type;
1318 std::unique_ptr<TypePathSegment> associated_segment;
1319 std::vector<std::unique_ptr<TypePathSegment> > segments;
1320 location_t locus;
1322 protected:
1323 /* Use covariance to implement clone function as returning this object
1324 * rather than base */
1325 QualifiedPathInType *clone_type_no_bounds_impl () const override
1327 return new QualifiedPathInType (*this);
1330 public:
1331 QualifiedPathInType (
1332 QualifiedPathType qual_path_type,
1333 std::unique_ptr<TypePathSegment> associated_segment,
1334 std::vector<std::unique_ptr<TypePathSegment> > path_segments,
1335 location_t locus)
1336 : path_type (std::move (qual_path_type)),
1337 associated_segment (std::move (associated_segment)),
1338 segments (std::move (path_segments)), locus (locus)
1341 // Copy constructor with vector clone
1342 QualifiedPathInType (QualifiedPathInType const &other)
1343 : path_type (other.path_type), locus (other.locus)
1345 auto seg = other.associated_segment->clone_type_path_segment_impl ();
1346 associated_segment = std::unique_ptr<TypePathSegment> (seg);
1348 segments.reserve (other.segments.size ());
1349 for (const auto &e : other.segments)
1350 segments.push_back (e->clone_type_path_segment ());
1353 // Overloaded assignment operator with vector clone
1354 QualifiedPathInType &operator= (QualifiedPathInType const &other)
1356 auto seg = other.associated_segment->clone_type_path_segment_impl ();
1357 associated_segment = std::unique_ptr<TypePathSegment> (seg);
1359 path_type = other.path_type;
1360 locus = other.locus;
1362 segments.reserve (other.segments.size ());
1363 for (const auto &e : other.segments)
1364 segments.push_back (e->clone_type_path_segment ());
1366 return *this;
1369 // move constructors
1370 QualifiedPathInType (QualifiedPathInType &&other) = default;
1371 QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
1373 // Returns whether qualified path in type is in an error state.
1374 bool is_error () const { return path_type.is_error (); }
1376 // Creates an error state qualified path in type.
1377 static QualifiedPathInType create_error ()
1379 return QualifiedPathInType (
1380 QualifiedPathType::create_error (), nullptr,
1381 std::vector<std::unique_ptr<TypePathSegment> > (), UNDEF_LOCATION);
1384 std::string as_string () const override;
1386 void accept_vis (ASTVisitor &vis) override;
1388 // TODO: is this better? Or is a "vis_pattern" better?
1389 QualifiedPathType &get_qualified_path_type ()
1391 rust_assert (!path_type.is_error ());
1392 return path_type;
1395 std::unique_ptr<TypePathSegment> &get_associated_segment ()
1397 return associated_segment;
1400 // TODO: this seems kinda dodgy
1401 std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
1403 return segments;
1405 const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
1407 return segments;
1410 location_t get_locus () const override final { return locus; }
1412 } // namespace AST
1413 } // namespace Rust
1415 #endif