1 // Copyright (C) 2020-2023 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 locus
)
39 : segment_name (std::move (segment_name
)), locus (locus
)
42 // Creates an error PathIdentSegment.
43 static PathIdentSegment
create_error ()
45 return PathIdentSegment ("", 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
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 locus
= 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?
123 std::unique_ptr
<Type
> &get_type ()
125 rust_assert (type
!= nullptr);
129 Location
get_locus () const { return locus
; }
131 Identifier
get_identifier () const { return identifier
; }
134 /* Class representing a const generic application */
139 * const generic arguments cannot always be differentiated with generic type
140 * arguments during parsing, e.g:
145 * Is N a type? A constant defined elsewhere? The parser cannot know, and must
146 * not draw any conclusions. We must wait until later passes of the compiler
147 * to decide whether this refers to a constant item or a type.
149 * On the other hand, simple expressions like literals or block expressions
150 * will always be constant expressions: There is no ambiguity at all.
155 Const
, // A const value
156 Type
, // A type argument (not discernable during parsing)
157 Either
, // Either a type or a const value, cleared up during resolving
160 static GenericArg
create_error ()
162 return GenericArg (nullptr, nullptr, "", Kind::Error
, Location ());
165 static GenericArg
create_const (std::unique_ptr
<Expr
> expression
)
167 auto locus
= expression
->get_locus ();
168 return GenericArg (std::move (expression
), nullptr, "", Kind::Const
, locus
);
171 static GenericArg
create_type (std::unique_ptr
<Type
> type
)
173 auto locus
= type
->get_locus ();
174 return GenericArg (nullptr, std::move (type
), "", Kind::Type
, locus
);
177 static GenericArg
create_ambiguous (Identifier path
, Location locus
)
179 return GenericArg (nullptr, nullptr, std::move (path
), Kind::Either
, locus
);
182 GenericArg (const GenericArg
&other
)
183 : path (other
.path
), kind (other
.kind
), locus (other
.locus
)
185 if (other
.expression
)
186 expression
= other
.expression
->clone_expr ();
188 type
= other
.type
->clone_type ();
191 GenericArg
operator= (const GenericArg
&other
)
197 if (other
.expression
)
198 expression
= other
.expression
->clone_expr ();
200 type
= other
.type
->clone_type ();
205 bool is_error () const { return kind
== Kind::Error
; }
207 Kind
get_kind () const { return kind
; }
208 const Location
&get_locus () const { return locus
; }
210 std::unique_ptr
<Expr
> &get_expression ()
212 rust_assert (kind
== Kind::Const
);
217 std::unique_ptr
<Type
> &get_type ()
219 rust_assert (kind
== Kind::Type
);
224 const std::string
&get_path () const
226 rust_assert (kind
== Kind::Either
);
231 std::string
as_string () const
238 return "Ambiguous: " + path
;
240 return "Const: { " + expression
->as_string () + " }";
242 return "Type: " + type
->as_string ();
249 * Disambiguate an ambiguous generic argument to a const generic argument,
252 GenericArg
disambiguate_to_const () const;
255 * Disambiguate an ambiguous generic argument to a type argument,
258 GenericArg
disambiguate_to_type () const;
261 GenericArg (std::unique_ptr
<Expr
> expression
, std::unique_ptr
<Type
> type
,
262 Identifier path
, Kind kind
, Location locus
)
263 : expression (std::move (expression
)), type (std::move (type
)),
264 path (std::move (path
)), kind (kind
), locus (locus
)
268 * Expression associated with a `Clear` const generic application
269 * A null pointer here is allowed in the case that the const argument is
272 std::unique_ptr
<Expr
> expression
;
275 * If the argument ends up being a type argument instead. A null pointer will
276 * be present here until the resolving phase.
278 std::unique_ptr
<Type
> type
;
281 * Optional path which cannot be differentiated between a constant item and
282 * a type. Only used for ambiguous const generic arguments, otherwise
287 /* Which kind of const generic application are we dealing with */
294 * Representation of const generic parameters
296 class ConstGenericParam
: public GenericParam
298 /* Name of the parameter */
301 /* Mandatory type of the const parameter - a null pointer is an error */
302 std::unique_ptr
<AST::Type
> type
;
305 * Default value for the const generic parameter
307 GenericArg default_value
;
309 Attribute outer_attr
;
313 ConstGenericParam (Identifier name
, std::unique_ptr
<AST::Type
> type
,
314 GenericArg default_value
, Attribute outer_attr
,
316 : name (name
), type (std::move (type
)),
317 default_value (std::move (default_value
)), outer_attr (outer_attr
),
321 ConstGenericParam (const ConstGenericParam
&other
)
322 : GenericParam (), name (other
.name
), type (other
.type
->clone_type ()),
323 default_value (other
.default_value
), outer_attr (other
.outer_attr
),
327 bool has_type () const { return type
!= nullptr; }
328 bool has_default_value () const { return !default_value
.is_error (); }
330 const Identifier
&get_name () const { return name
; }
332 std::unique_ptr
<AST::Type
> &get_type ()
334 rust_assert (has_type ());
339 GenericArg
&get_default_value ()
341 rust_assert (has_default_value ());
343 return default_value
;
346 const GenericArg
&get_default_value () const
348 rust_assert (has_default_value ());
350 return default_value
;
353 std::string
as_string () const override
;
355 void accept_vis (ASTVisitor
&vis
) override
;
357 Location
get_locus () const override final
{ return locus
; }
359 Kind
get_kind () const override final
{ return Kind::Const
; }
362 /* Use covariance to implement clone function as returning this object rather
364 ConstGenericParam
*clone_generic_param_impl () const override
366 return new ConstGenericParam (*this);
370 // Generic arguments allowed in each path expression segment - inline?
373 std::vector
<Lifetime
> lifetime_args
;
374 std::vector
<GenericArg
> generic_args
;
375 std::vector
<GenericArgsBinding
> binding_args
;
379 // Returns true if there are any generic arguments
380 bool has_generic_args () const
382 return !(lifetime_args
.empty () && generic_args
.empty ()
383 && binding_args
.empty ());
386 GenericArgs (std::vector
<Lifetime
> lifetime_args
,
387 std::vector
<GenericArg
> generic_args
,
388 std::vector
<GenericArgsBinding
> binding_args
,
389 Location locus
= Location ())
390 : lifetime_args (std::move (lifetime_args
)),
391 generic_args (std::move (generic_args
)),
392 binding_args (std::move (binding_args
)), locus (locus
)
395 // copy constructor with vector clone
396 GenericArgs (GenericArgs
const &other
)
397 : lifetime_args (other
.lifetime_args
), generic_args (other
.generic_args
),
398 binding_args (other
.binding_args
), locus (other
.locus
)
401 ~GenericArgs () = default;
403 // overloaded assignment operator to vector clone
404 GenericArgs
&operator= (GenericArgs
const &other
)
406 lifetime_args
= other
.lifetime_args
;
407 generic_args
= other
.generic_args
;
408 binding_args
= other
.binding_args
;
415 GenericArgs (GenericArgs
&&other
) = default;
416 GenericArgs
&operator= (GenericArgs
&&other
) = default;
418 // Creates an empty GenericArgs (no arguments)
419 static GenericArgs
create_empty () { return GenericArgs ({}, {}, {}); }
421 std::string
as_string () const;
423 // TODO: is this better? Or is a "vis_pattern" better?
424 std::vector
<GenericArg
> &get_generic_args () { return generic_args
; }
426 // TODO: is this better? Or is a "vis_pattern" better?
427 std::vector
<GenericArgsBinding
> &get_binding_args () { return binding_args
; }
429 std::vector
<Lifetime
> &get_lifetime_args () { return lifetime_args
; };
431 Location
get_locus () { return locus
; }
434 /* A segment of a path in expression, including an identifier aspect and maybe
436 class PathExprSegment
437 { // or should this extend PathIdentSegment?
439 PathIdentSegment segment_name
;
440 GenericArgs generic_args
;
445 // Returns true if there are any generic arguments
446 bool has_generic_args () const { return generic_args
.has_generic_args (); }
448 // Constructor for segment (from IdentSegment and GenericArgs)
449 PathExprSegment (PathIdentSegment segment_name
, Location locus
,
450 GenericArgs generic_args
= GenericArgs::create_empty ())
451 : segment_name (std::move (segment_name
)),
452 generic_args (std::move (generic_args
)), locus (locus
),
453 node_id (Analysis::Mappings::get ()->get_next_node_id ())
456 /* Constructor for segment with generic arguments (from segment name and all
458 PathExprSegment (std::string segment_name
, Location locus
,
459 std::vector
<Lifetime
> lifetime_args
= {},
460 std::vector
<GenericArg
> generic_args
= {},
461 std::vector
<GenericArgsBinding
> binding_args
= {})
462 : segment_name (PathIdentSegment (std::move (segment_name
), locus
)),
463 generic_args (GenericArgs (std::move (lifetime_args
),
464 std::move (generic_args
),
465 std::move (binding_args
))),
466 locus (locus
), node_id (Analysis::Mappings::get ()->get_next_node_id ())
469 // Returns whether path expression segment is in an error state.
470 bool is_error () const { return segment_name
.is_error (); }
472 // Creates an error-state path expression segment.
473 static PathExprSegment
create_error ()
475 return PathExprSegment (PathIdentSegment::create_error (), Location ());
478 std::string
as_string () const;
480 Location
get_locus () const { return locus
; }
482 // TODO: is this better? Or is a "vis_pattern" better?
483 GenericArgs
&get_generic_args ()
485 rust_assert (has_generic_args ());
489 PathIdentSegment
&get_ident_segment () { return segment_name
; }
490 const PathIdentSegment
&get_ident_segment () const { return segment_name
; }
492 NodeId
get_node_id () const { return node_id
; }
494 bool is_super_path_seg () const
496 return !has_generic_args () && get_ident_segment ().is_super_segment ();
499 bool is_crate_path_seg () const
501 return !has_generic_args () && get_ident_segment ().is_crate_segment ();
503 bool is_lower_self_seg () const
505 return !has_generic_args () && get_ident_segment ().is_lower_self ();
509 // AST node representing a pattern that involves a "path" - abstract base
511 class PathPattern
: public Pattern
513 std::vector
<PathExprSegment
> segments
;
516 PathPattern (std::vector
<PathExprSegment
> segments
)
517 : segments (std::move (segments
))
520 // Returns whether path has segments.
521 bool has_segments () const { return !segments
.empty (); }
523 /* Converts path segments to their equivalent SimplePath segments if
524 * possible, and creates a SimplePath from them. */
525 SimplePath
convert_to_simple_path (bool with_opening_scope_resolution
) const;
527 // Removes all segments of the path.
528 void remove_all_segments ()
531 segments
.shrink_to_fit ();
535 /* Returns whether the path is a single segment (excluding qualified path
536 * initial as segment). */
537 bool is_single_segment () const { return segments
.size () == 1; }
539 std::string
as_string () const override
;
541 // TODO: this seems kinda dodgy
542 std::vector
<PathExprSegment
> &get_segments () { return segments
; }
543 const std::vector
<PathExprSegment
> &get_segments () const { return segments
; }
546 /* AST node representing a path-in-expression pattern (path that allows
547 * generic arguments) */
548 class PathInExpression
: public PathPattern
, public PathExpr
550 std::vector
<Attribute
> outer_attrs
;
551 bool has_opening_scope_resolution
;
556 std::string
as_string () const override
;
559 PathInExpression (std::vector
<PathExprSegment
> path_segments
,
560 std::vector
<Attribute
> outer_attrs
, Location locus
,
561 bool has_opening_scope_resolution
= false)
562 : PathPattern (std::move (path_segments
)),
563 outer_attrs (std::move (outer_attrs
)),
564 has_opening_scope_resolution (has_opening_scope_resolution
),
565 locus (locus
), _node_id (Analysis::Mappings::get ()->get_next_node_id ())
568 // Creates an error state path in expression.
569 static PathInExpression
create_error ()
571 return PathInExpression ({}, {}, Location ());
574 // Returns whether path in expression is in an error state.
575 bool is_error () const { return !has_segments (); }
577 /* Converts PathInExpression to SimplePath if possible (i.e. no generic
578 * arguments). Otherwise returns an empty SimplePath. */
579 SimplePath
as_simple_path () const
581 /* delegate to parent class as can't access segments. however,
582 * QualifiedPathInExpression conversion to simple path wouldn't make
583 * sense, so the method in the parent class should be protected, not
584 * public. Have to pass in opening scope resolution as parent class has no
587 return convert_to_simple_path (has_opening_scope_resolution
);
590 Location
get_locus () const override final
{ return locus
; }
592 void accept_vis (ASTVisitor
&vis
) override
;
594 // Invalid if path is empty (error state), so base stripping on that.
595 void mark_for_strip () override
{ remove_all_segments (); }
596 bool is_marked_for_strip () const override
{ return is_error (); }
598 bool opening_scope_resolution () const
600 return has_opening_scope_resolution
;
603 NodeId
get_node_id () const override
{ return _node_id
; }
605 const std::vector
<Attribute
> &get_outer_attrs () const { return outer_attrs
; }
606 std::vector
<Attribute
> &get_outer_attrs () { return outer_attrs
; }
608 void set_outer_attrs (std::vector
<Attribute
> new_attrs
) override
610 outer_attrs
= std::move (new_attrs
);
613 NodeId
get_pattern_node_id () const override final
{ return get_node_id (); }
616 /* Use covariance to implement clone function as returning this object
617 * rather than base */
618 PathInExpression
*clone_pattern_impl () const final override
620 return clone_path_in_expression_impl ();
623 /* Use covariance to implement clone function as returning this object
624 * rather than base */
625 PathInExpression
*clone_expr_without_block_impl () const final override
627 return clone_path_in_expression_impl ();
630 /*virtual*/ PathInExpression
*clone_path_in_expression_impl () const
632 return new PathInExpression (*this);
636 /* Base class for segments used in type paths - not abstract (represents an
637 * ident-only segment) */
638 class TypePathSegment
649 PathIdentSegment ident_segment
;
653 /* This is protected because it is only really used by derived classes, not
655 bool has_separating_scope_resolution
;
658 // Clone function implementation - not pure virtual as overrided by
660 virtual TypePathSegment
*clone_type_path_segment_impl () const
662 return new TypePathSegment (*this);
666 virtual ~TypePathSegment () {}
668 virtual SegmentType
get_type () const { return SegmentType::REG
; }
670 // Unique pointer custom clone function
671 std::unique_ptr
<TypePathSegment
> clone_type_path_segment () const
673 return std::unique_ptr
<TypePathSegment
> (clone_type_path_segment_impl ());
676 TypePathSegment (PathIdentSegment ident_segment
,
677 bool has_separating_scope_resolution
, Location locus
)
678 : ident_segment (std::move (ident_segment
)), locus (locus
),
679 has_separating_scope_resolution (has_separating_scope_resolution
),
680 node_id (Analysis::Mappings::get ()->get_next_node_id ())
683 TypePathSegment (std::string segment_name
,
684 bool has_separating_scope_resolution
, Location locus
)
685 : ident_segment (PathIdentSegment (std::move (segment_name
), locus
)),
687 has_separating_scope_resolution (has_separating_scope_resolution
),
688 node_id (Analysis::Mappings::get ()->get_next_node_id ())
691 virtual std::string
as_string () const { return ident_segment
.as_string (); }
693 /* Returns whether the type path segment is in an error state. May be
694 * virtual in future. */
695 bool is_error () const { return ident_segment
.is_error (); }
697 /* Returns whether segment is identifier only (as opposed to generic args or
698 * function). Overridden in derived classes with other segments. */
699 virtual bool is_ident_only () const { return true; }
701 Location
get_locus () const { return locus
; }
703 // not pure virtual as class not abstract
704 virtual void accept_vis (ASTVisitor
&vis
);
706 bool get_separating_scope_resolution () const
708 return has_separating_scope_resolution
;
711 PathIdentSegment
&get_ident_segment () { return ident_segment
; };
712 const PathIdentSegment
&get_ident_segment () const { return ident_segment
; };
714 NodeId
get_node_id () const { return node_id
; }
716 bool is_crate_path_seg () const
718 return get_ident_segment ().is_crate_segment ();
720 bool is_super_path_seg () const
722 return get_ident_segment ().is_super_segment ();
724 bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
725 bool is_lower_self_seg () const
727 return get_ident_segment ().is_lower_self ();
731 // Segment used in type path with generic args
732 class TypePathSegmentGeneric
: public TypePathSegment
734 GenericArgs generic_args
;
737 SegmentType
get_type () const override
{ return SegmentType::GENERIC
; }
739 bool has_generic_args () const { return generic_args
.has_generic_args (); }
741 bool is_ident_only () const override
{ return false; }
743 // Constructor with PathIdentSegment and GenericArgs
744 TypePathSegmentGeneric (PathIdentSegment ident_segment
,
745 bool has_separating_scope_resolution
,
746 GenericArgs generic_args
, Location locus
)
747 : TypePathSegment (std::move (ident_segment
),
748 has_separating_scope_resolution
, locus
),
749 generic_args (std::move (generic_args
))
752 // Constructor from segment name and all args
753 TypePathSegmentGeneric (std::string segment_name
,
754 bool has_separating_scope_resolution
,
755 std::vector
<Lifetime
> lifetime_args
,
756 std::vector
<GenericArg
> generic_args
,
757 std::vector
<GenericArgsBinding
> binding_args
,
759 : TypePathSegment (std::move (segment_name
),
760 has_separating_scope_resolution
, locus
),
761 generic_args (GenericArgs (std::move (lifetime_args
),
762 std::move (generic_args
),
763 std::move (binding_args
)))
766 std::string
as_string () const override
;
768 void accept_vis (ASTVisitor
&vis
) override
;
770 // TODO: is this better? Or is a "vis_pattern" better?
771 GenericArgs
&get_generic_args ()
773 rust_assert (has_generic_args ());
778 // Use covariance to override base class method
779 TypePathSegmentGeneric
*clone_type_path_segment_impl () const override
781 return new TypePathSegmentGeneric (*this);
785 // A function as represented in a type path
786 struct TypePathFunction
791 TypePathFnInputs inputs;*/
792 // inlined from TypePathFnInputs
793 std::vector
<std::unique_ptr
<Type
> > inputs
;
796 std::unique_ptr
<Type
> return_type
;
798 // FIXME: think of better way to mark as invalid than taking up storage
804 // Constructor only used to create invalid type path functions.
805 TypePathFunction (bool is_invalid
, Location locus
)
806 : is_invalid (is_invalid
), locus (locus
)
810 // Returns whether the return type of the function has been specified.
811 bool has_return_type () const { return return_type
!= nullptr; }
813 // Returns whether the function has inputs.
814 bool has_inputs () const { return !inputs
.empty (); }
816 // Returns whether function is in an error state.
817 bool is_error () const { return is_invalid
; }
819 // Creates an error state function.
820 static TypePathFunction
create_error ()
822 return TypePathFunction (true, Location ());
826 TypePathFunction (std::vector
<std::unique_ptr
<Type
> > inputs
, Location locus
,
827 std::unique_ptr
<Type
> type
= nullptr)
828 : inputs (std::move (inputs
)), return_type (std::move (type
)),
829 is_invalid (false), locus (locus
)
832 // Copy constructor with clone
833 TypePathFunction (TypePathFunction
const &other
)
834 : is_invalid (other
.is_invalid
)
836 // guard to protect from null pointer dereference
837 if (other
.return_type
!= nullptr)
838 return_type
= other
.return_type
->clone_type ();
840 inputs
.reserve (other
.inputs
.size ());
841 for (const auto &e
: other
.inputs
)
842 inputs
.push_back (e
->clone_type ());
845 ~TypePathFunction () = default;
847 // Overloaded assignment operator to clone type
848 TypePathFunction
&operator= (TypePathFunction
const &other
)
850 is_invalid
= other
.is_invalid
;
852 // guard to protect from null pointer dereference
853 if (other
.return_type
!= nullptr)
854 return_type
= other
.return_type
->clone_type ();
856 return_type
= nullptr;
858 inputs
.reserve (other
.inputs
.size ());
859 for (const auto &e
: other
.inputs
)
860 inputs
.push_back (e
->clone_type ());
866 TypePathFunction (TypePathFunction
&&other
) = default;
867 TypePathFunction
&operator= (TypePathFunction
&&other
) = default;
869 std::string
as_string () const;
871 // TODO: this mutable getter seems really dodgy. Think up better way.
872 const std::vector
<std::unique_ptr
<Type
> > &get_params () const
876 std::vector
<std::unique_ptr
<Type
> > &get_params () { return inputs
; }
878 // TODO: is this better? Or is a "vis_pattern" better?
879 std::unique_ptr
<Type
> &get_return_type ()
881 rust_assert (has_return_type ());
886 // Segment used in type path with a function argument
887 class TypePathSegmentFunction
: public TypePathSegment
889 TypePathFunction function_path
;
892 SegmentType
get_type () const override
{ return SegmentType::FUNCTION
; }
894 // Constructor with PathIdentSegment and TypePathFn
895 TypePathSegmentFunction (PathIdentSegment ident_segment
,
896 bool has_separating_scope_resolution
,
897 TypePathFunction function_path
, Location locus
)
898 : TypePathSegment (std::move (ident_segment
),
899 has_separating_scope_resolution
, locus
),
900 function_path (std::move (function_path
))
903 // Constructor with segment name and TypePathFn
904 TypePathSegmentFunction (std::string segment_name
,
905 bool has_separating_scope_resolution
,
906 TypePathFunction function_path
, Location locus
)
907 : TypePathSegment (std::move (segment_name
),
908 has_separating_scope_resolution
, locus
),
909 function_path (std::move (function_path
))
912 std::string
as_string () const override
;
914 bool is_ident_only () const override
{ return false; }
916 void accept_vis (ASTVisitor
&vis
) override
;
918 // TODO: is this better? Or is a "vis_pattern" better?
919 TypePathFunction
&get_type_path_function ()
921 rust_assert (!function_path
.is_error ());
922 return function_path
;
926 // Use covariance to override base class method
927 TypePathSegmentFunction
*clone_type_path_segment_impl () const override
929 return new TypePathSegmentFunction (*this);
933 // Path used inside types
934 class TypePath
: public TypeNoBounds
936 bool has_opening_scope_resolution
;
937 std::vector
<std::unique_ptr
<TypePathSegment
> > segments
;
941 /* Use covariance to implement clone function as returning this object
942 * rather than base */
943 TypePath
*clone_type_no_bounds_impl () const override
945 return new TypePath (*this);
949 /* Returns whether the TypePath has an opening scope resolution operator
950 * (i.e. is global path or crate-relative path, not module-relative) */
951 bool has_opening_scope_resolution_op () const
953 return has_opening_scope_resolution
;
956 // Returns whether the TypePath is in an invalid state.
957 bool is_error () const { return segments
.empty (); }
959 // Creates an error state TypePath.
960 static TypePath
create_error ()
962 return TypePath (std::vector
<std::unique_ptr
<TypePathSegment
> > (),
967 TypePath (std::vector
<std::unique_ptr
<TypePathSegment
> > segments
,
968 Location locus
, bool has_opening_scope_resolution
= false)
970 has_opening_scope_resolution (has_opening_scope_resolution
),
971 segments (std::move (segments
)), locus (locus
)
974 // Copy constructor with vector clone
975 TypePath (TypePath
const &other
)
976 : has_opening_scope_resolution (other
.has_opening_scope_resolution
),
979 segments
.reserve (other
.segments
.size ());
980 for (const auto &e
: other
.segments
)
981 segments
.push_back (e
->clone_type_path_segment ());
984 // Overloaded assignment operator with clone
985 TypePath
&operator= (TypePath
const &other
)
987 has_opening_scope_resolution
= other
.has_opening_scope_resolution
;
990 segments
.reserve (other
.segments
.size ());
991 for (const auto &e
: other
.segments
)
992 segments
.push_back (e
->clone_type_path_segment ());
998 TypePath (TypePath
&&other
) = default;
999 TypePath
&operator= (TypePath
&&other
) = default;
1001 std::string
as_string () const override
;
1003 /* Converts TypePath to SimplePath if possible (i.e. no generic or function
1004 * arguments). Otherwise returns an empty SimplePath. */
1005 SimplePath
as_simple_path () const;
1007 // Creates a trait bound with a clone of this type path as its only element.
1008 TraitBound
*to_trait_bound (bool in_parens
) const override
;
1010 Location
get_locus () const override final
{ return locus
; }
1012 void accept_vis (ASTVisitor
&vis
) override
;
1014 // TODO: this seems kinda dodgy
1015 std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments ()
1019 const std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments () const
1024 size_t get_num_segments () const { return segments
.size (); }
1027 struct QualifiedPathType
1030 std::unique_ptr
<Type
> type_to_invoke_on
;
1031 TypePath trait_path
;
1037 QualifiedPathType (std::unique_ptr
<Type
> invoke_on_type
,
1038 Location locus
= Location (),
1039 TypePath trait_path
= TypePath::create_error ())
1040 : type_to_invoke_on (std::move (invoke_on_type
)),
1041 trait_path (std::move (trait_path
)), locus (locus
),
1042 node_id (Analysis::Mappings::get ()->get_next_node_id ())
1045 // Copy constructor uses custom deep copy for Type to preserve polymorphism
1046 QualifiedPathType (QualifiedPathType
const &other
)
1047 : trait_path (other
.trait_path
), locus (other
.locus
)
1049 node_id
= other
.node_id
;
1050 // guard to prevent null dereference
1051 if (other
.type_to_invoke_on
!= nullptr)
1052 type_to_invoke_on
= other
.type_to_invoke_on
->clone_type ();
1055 // default destructor
1056 ~QualifiedPathType () = default;
1058 // overload assignment operator to use custom clone method
1059 QualifiedPathType
&operator= (QualifiedPathType
const &other
)
1061 node_id
= other
.node_id
;
1062 trait_path
= other
.trait_path
;
1063 locus
= other
.locus
;
1065 // guard to prevent null dereference
1066 if (other
.type_to_invoke_on
!= nullptr)
1067 type_to_invoke_on
= other
.type_to_invoke_on
->clone_type ();
1069 type_to_invoke_on
= nullptr;
1075 QualifiedPathType (QualifiedPathType
&&other
) = default;
1076 QualifiedPathType
&operator= (QualifiedPathType
&&other
) = default;
1078 // Returns whether the qualified path type has a rebind as clause.
1079 bool has_as_clause () const { return !trait_path
.is_error (); }
1081 // Returns whether the qualified path type is in an error state.
1082 bool is_error () const { return type_to_invoke_on
== nullptr; }
1084 // Creates an error state qualified path type.
1085 static QualifiedPathType
create_error ()
1087 return QualifiedPathType (nullptr);
1090 std::string
as_string () const;
1092 Location
get_locus () const { return locus
; }
1094 // TODO: is this better? Or is a "vis_pattern" better?
1095 std::unique_ptr
<Type
> &get_type ()
1097 rust_assert (type_to_invoke_on
!= nullptr);
1098 return type_to_invoke_on
;
1101 // TODO: is this better? Or is a "vis_pattern" better?
1102 TypePath
&get_as_type_path ()
1104 rust_assert (has_as_clause ());
1108 NodeId
get_node_id () const { return node_id
; }
1111 /* AST node representing a qualified path-in-expression pattern (path that
1112 * allows specifying trait functions) */
1113 class QualifiedPathInExpression
: public PathPattern
, public PathExpr
1115 std::vector
<Attribute
> outer_attrs
;
1116 QualifiedPathType path_type
;
1121 std::string
as_string () const override
;
1123 QualifiedPathInExpression (QualifiedPathType qual_path_type
,
1124 std::vector
<PathExprSegment
> path_segments
,
1125 std::vector
<Attribute
> outer_attrs
, Location locus
)
1126 : PathPattern (std::move (path_segments
)),
1127 outer_attrs (std::move (outer_attrs
)),
1128 path_type (std::move (qual_path_type
)), locus (locus
),
1129 _node_id (Analysis::Mappings::get ()->get_next_node_id ())
1132 /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1133 * elements as params */
1135 // Returns whether qualified path in expression is in an error state.
1136 bool is_error () const { return path_type
.is_error (); }
1138 // Creates an error qualified path in expression.
1139 static QualifiedPathInExpression
create_error ()
1141 return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
1145 Location
get_locus () const override final
{ return locus
; }
1147 void accept_vis (ASTVisitor
&vis
) override
;
1149 // Invalid if path_type is error, so base stripping on that.
1150 void mark_for_strip () override
1152 path_type
= QualifiedPathType::create_error ();
1154 bool is_marked_for_strip () const override
{ return is_error (); }
1156 // TODO: is this better? Or is a "vis_pattern" better?
1157 QualifiedPathType
&get_qualified_path_type ()
1159 rust_assert (!path_type
.is_error ());
1163 const std::vector
<Attribute
> &get_outer_attrs () const { return outer_attrs
; }
1164 std::vector
<Attribute
> &get_outer_attrs () { return outer_attrs
; }
1166 void set_outer_attrs (std::vector
<Attribute
> new_attrs
) override
1168 outer_attrs
= std::move (new_attrs
);
1171 NodeId
get_node_id () const override
{ return _node_id
; }
1173 NodeId
get_pattern_node_id () const override final
{ return get_node_id (); }
1176 /* Use covariance to implement clone function as returning this object
1177 * rather than base */
1178 QualifiedPathInExpression
*clone_pattern_impl () const final override
1180 return clone_qual_path_in_expression_impl ();
1183 /* Use covariance to implement clone function as returning this object
1184 * rather than base */
1185 QualifiedPathInExpression
*
1186 clone_expr_without_block_impl () const final override
1188 return clone_qual_path_in_expression_impl ();
1191 /*virtual*/ QualifiedPathInExpression
*
1192 clone_qual_path_in_expression_impl () const
1194 return new QualifiedPathInExpression (*this);
1198 /* Represents a qualified path in a type; used for disambiguating trait
1200 class QualifiedPathInType
: public TypeNoBounds
1202 QualifiedPathType path_type
;
1203 std::unique_ptr
<TypePathSegment
> associated_segment
;
1204 std::vector
<std::unique_ptr
<TypePathSegment
> > segments
;
1208 /* Use covariance to implement clone function as returning this object
1209 * rather than base */
1210 QualifiedPathInType
*clone_type_no_bounds_impl () const override
1212 return new QualifiedPathInType (*this);
1216 QualifiedPathInType (
1217 QualifiedPathType qual_path_type
,
1218 std::unique_ptr
<TypePathSegment
> associated_segment
,
1219 std::vector
<std::unique_ptr
<TypePathSegment
> > path_segments
,
1221 : path_type (std::move (qual_path_type
)),
1222 associated_segment (std::move (associated_segment
)),
1223 segments (std::move (path_segments
)), locus (locus
)
1226 /* TODO: maybe make a shortcut constructor that has QualifiedPathType
1227 * elements as params */
1229 // Copy constructor with vector clone
1230 QualifiedPathInType (QualifiedPathInType
const &other
)
1231 : path_type (other
.path_type
), locus (other
.locus
)
1233 segments
.reserve (other
.segments
.size ());
1234 for (const auto &e
: other
.segments
)
1235 segments
.push_back (e
->clone_type_path_segment ());
1238 // Overloaded assignment operator with vector clone
1239 QualifiedPathInType
&operator= (QualifiedPathInType
const &other
)
1241 path_type
= other
.path_type
;
1242 locus
= other
.locus
;
1244 segments
.reserve (other
.segments
.size ());
1245 for (const auto &e
: other
.segments
)
1246 segments
.push_back (e
->clone_type_path_segment ());
1251 // move constructors
1252 QualifiedPathInType (QualifiedPathInType
&&other
) = default;
1253 QualifiedPathInType
&operator= (QualifiedPathInType
&&other
) = default;
1255 // Returns whether qualified path in type is in an error state.
1256 bool is_error () const { return path_type
.is_error (); }
1258 // Creates an error state qualified path in type.
1259 static QualifiedPathInType
create_error ()
1261 return QualifiedPathInType (
1262 QualifiedPathType::create_error (), nullptr,
1263 std::vector
<std::unique_ptr
<TypePathSegment
> > (), Location ());
1266 std::string
as_string () const override
;
1268 void accept_vis (ASTVisitor
&vis
) override
;
1270 // TODO: is this better? Or is a "vis_pattern" better?
1271 QualifiedPathType
&get_qualified_path_type ()
1273 rust_assert (!path_type
.is_error ());
1277 std::unique_ptr
<TypePathSegment
> &get_associated_segment ()
1279 return associated_segment
;
1282 // TODO: this seems kinda dodgy
1283 std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments ()
1287 const std::vector
<std::unique_ptr
<TypePathSegment
> > &get_segments () const
1292 Location
get_locus () const override final
{ return locus
; }