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
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
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. */
30 // The "identifier" (not generic args) aspect of each path expression segment
31 class PathIdentSegment
33 std::string segment_name
;
36 // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
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
65 Identifier identifier
;
66 std::unique_ptr
<Type
> type
;
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 ();
99 ~GenericArgsBinding () = default;
101 // Overload assignment operator to deep copy the pointed-to type
102 GenericArgsBinding
&operator= (GenericArgsBinding
const &other
)
104 identifier
= other
.identifier
;
107 // guard to protect from null pointer dereference
108 if (other
.type
!= nullptr)
109 type
= other
.type
->clone_type ();
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?
125 rust_assert (type
!= nullptr);
129 std::unique_ptr
<Type
> &get_type_ptr ()
131 rust_assert (type
!= nullptr);
135 location_t
get_locus () const { return locus
; }
137 Identifier
get_identifier () const { return identifier
; }
140 /* Class representing a const generic application */
145 * const generic arguments cannot always be differentiated with generic type
146 * arguments during parsing, e.g:
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.
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
,
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 ();
195 type
= other
.type
->clone_type ();
198 GenericArg
operator= (const GenericArg
&other
)
204 if (other
.expression
)
205 expression
= other
.expression
->clone_expr ();
207 type
= other
.type
->clone_type ();
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
)
225 get_expression ().accept_vis (visitor
);
228 get_type ().accept_vis (visitor
);
237 Expr
&get_expression ()
239 rust_assert (kind
== Kind::Const
);
244 std::unique_ptr
<Expr
> &get_expression_ptr ()
246 rust_assert (kind
== Kind::Const
);
253 rust_assert (kind
== Kind::Type
);
258 std::unique_ptr
<Type
> &get_type_ptr ()
260 rust_assert (kind
== Kind::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
279 return "Ambiguous: " + path
.as_string ();
281 return "Const: { " + expression
->as_string () + " }";
283 return "Type: " + type
->as_string ();
290 * Disambiguate an ambiguous generic argument to a const generic argument,
293 GenericArg
disambiguate_to_const () const;
296 * Disambiguate an ambiguous generic argument to a type argument,
299 GenericArg
disambiguate_to_type () const;
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
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
328 /* Which kind of const generic application are we dealing with */
335 * Representation of const generic parameters
337 class ConstGenericParam
: public GenericParam
339 /* Name of the parameter */
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
;
354 ConstGenericParam (Identifier name
, std::unique_ptr
<AST::Type
> type
,
355 GenericArg default_value
, Attribute outer_attr
,
357 : name (name
), type (std::move (type
)),
358 default_value (std::move (default_value
)), outer_attr (outer_attr
),
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
),
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 ());
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
; }
405 /* Use covariance to implement clone function as returning this object rather
407 ConstGenericParam
*clone_generic_param_impl () const override
409 return new ConstGenericParam (*this);
413 // Generic arguments allowed in each path expression segment - inline?
416 std::vector
<Lifetime
> lifetime_args
;
417 std::vector
<GenericArg
> generic_args
;
418 std::vector
<GenericArgsBinding
> binding_args
;
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
),
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
;
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
));
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
492 class PathExprSegment
493 { // or should this extend PathIdentSegment?
495 PathIdentSegment segment_name
;
496 GenericArgs generic_args
;
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
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 ());
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
568 class PathPattern
: public Pattern
570 std::vector
<PathExprSegment
> segments
;
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 ()
588 segments
.shrink_to_fit ();
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
;
615 std::string
as_string () const override
;
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
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 ();
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
714 PathIdentSegment ident_segment
;
718 /* This is protected because it is only really used by derived classes, not
720 bool has_separating_scope_resolution
;
724 // Clone function implementation - not pure virtual as overrided by
726 virtual TypePathSegment
*clone_type_path_segment_impl () const
728 return new TypePathSegment (*this);
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
)),
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
;
767 has_separating_scope_resolution
= other
.has_separating_scope_resolution
;
768 node_id
= other
.node_id
;
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
;
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
,
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
;
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 ());
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
892 TypePathFnInputs inputs;*/
893 // inlined from TypePathFnInputs
894 std::vector
<std::unique_ptr
<Type
> > inputs
;
897 std::unique_ptr
<Type
> return_type
;
899 // FIXME: think of better way to mark as invalid than taking up storage
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
)
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
);
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 ();
957 return_type
= nullptr;
959 inputs
.reserve (other
.inputs
.size ());
960 for (const auto &e
: other
.inputs
)
961 inputs
.push_back (e
->clone_type ());
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
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 ());
986 std::unique_ptr
<Type
> &get_return_type_ptr ()
988 rust_assert (has_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
;
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
;
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);
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
> > (),
1075 TypePath (std::vector
<std::unique_ptr
<TypePathSegment
> > segments
,
1076 location_t locus
, bool has_opening_scope_resolution
= false)
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
),
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 ());
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 ()
1129 const std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments () const
1134 size_t get_num_segments () const { return segments
.size (); }
1137 struct QualifiedPathType
1140 std::unique_ptr
<Type
> type_to_invoke_on
;
1141 TypePath trait_path
;
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 ();
1179 type_to_invoke_on
= nullptr;
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?
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 ());
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
;
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
,
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 ());
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
; }
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
1315 class QualifiedPathInType
: public TypeNoBounds
1317 QualifiedPathType path_type
;
1318 std::unique_ptr
<TypePathSegment
> associated_segment
;
1319 std::vector
<std::unique_ptr
<TypePathSegment
> > segments
;
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);
1331 QualifiedPathInType (
1332 QualifiedPathType qual_path_type
,
1333 std::unique_ptr
<TypePathSegment
> associated_segment
,
1334 std::vector
<std::unique_ptr
<TypePathSegment
> > path_segments
,
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 ());
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 ());
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 ()
1405 const std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments () const
1410 location_t
get_locus () const override final
{ return locus
; }