diff options
Diffstat (limited to 'gcc/rust/ast/rust-path.h')
-rw-r--r-- | gcc/rust/ast/rust-path.h | 405 |
1 files changed, 145 insertions, 260 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index ae40a7e..c5afc8f 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -21,6 +21,7 @@ /* "Path" (identifier within namespaces, essentially) handling. Required include * for virtually all AST-related functionality. */ +#include "optional.h" #include "rust-ast.h" #include "rust-hir-map.h" #include "rust-mapping-common.h" @@ -589,115 +590,75 @@ public: { LangItem, Regular, - Type, }; - virtual Kind get_path_kind () const = 0; - - Pattern::Kind get_pattern_kind () override final - { - return Pattern::Kind::Path; - } - - std::unique_ptr<Path> clone_path () - { - return std::unique_ptr<Path> (clone_path_impl ()); - } - - Pattern *clone_pattern_impl () const override final - { - return clone_path_impl (); - } - -protected: - virtual Path *clone_path_impl () const = 0; -}; - -class RegularPath : public Path -{ - std::vector<PathExprSegment> segments; - NodeId node_id; - location_t locus; - -public: - explicit RegularPath (std::vector<PathExprSegment> &&segments, - location_t locus, NodeId node_id) - : segments (std::move (segments)), node_id (node_id), locus (locus) + Path (std::vector<PathExprSegment> segments) + : segments (std::move (segments)), lang_item (tl::nullopt), + kind (Kind::Regular) {} - std::string as_string () const override; + Path (LangItem::Kind lang_item) + : segments ({}), lang_item (lang_item), kind (Kind::LangItem) + {} // Returns whether path has segments. - bool has_segments () const { return !segments.empty (); } - - std::vector<PathExprSegment> &get_segments () { return segments; } - - const std::vector<PathExprSegment> &get_segments () const { return segments; } - - /* Returns whether the path is a single segment (excluding qualified path - * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } + bool has_segments () const + { + rust_assert (kind == Kind::Regular); + return !segments.empty (); + } /* Converts path segments to their equivalent SimplePath segments if * possible, and creates a SimplePath from them. */ SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; - Path::Kind get_path_kind () const override { return Path::Kind::Regular; } - - void accept_vis (ASTVisitor &vis) override; - - Path *clone_path_impl () const override + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + bool is_single_segment () const { - return new RegularPath (std::vector<PathExprSegment> (segments), locus, - node_id); + rust_assert (kind == Kind::Regular); + return segments.size () == 1; } - NodeId get_node_id () const override { return node_id; } - location_t get_locus () const override { return locus; } -}; - -class LangItemPath : public Path -{ - LangItem::Kind kind; - NodeId node_id; - location_t locus; - - LangItemPath (LangItem::Kind kind, NodeId node_id, location_t locus) - : kind (kind), node_id (node_id), locus (locus) - {} - -public: - explicit LangItemPath (LangItem::Kind kind, location_t locus) - : kind (kind), node_id (Analysis::Mappings::get ().get_next_node_id ()), - locus (locus) - {} - - Path::Kind get_path_kind () const override { return Path::Kind::LangItem; } + std::string as_string () const override; - void accept_vis (ASTVisitor &vis) override; + // TODO: this seems kinda dodgy + std::vector<PathExprSegment> &get_segments () + { + rust_assert (kind == Kind::Regular); + return segments; + } + const std::vector<PathExprSegment> &get_segments () const + { + rust_assert (kind == Kind::Regular); + return segments; + } - Path *clone_path_impl () const override + LangItem::Kind get_lang_item () const { - return new LangItemPath (kind, node_id, locus); + rust_assert (kind == Kind::LangItem); + return *lang_item; } - std::string as_string () const override; + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + Path::Kind get_path_kind () { return kind; } - LangItem::Kind get_lang_item_kind () { return kind; } +protected: + std::vector<PathExprSegment> segments; + tl::optional<LangItem::Kind> lang_item; - NodeId get_node_id () const override { return node_id; } - location_t get_locus () const override { return locus; } + Path::Kind kind; }; /* AST node representing a path-in-expression pattern (path that allows * generic arguments) */ -class PathInExpression : public Pattern, public ExprWithoutBlock +class PathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; bool has_opening_scope_resolution; location_t locus; NodeId _node_id; - std::unique_ptr<Path> path; + bool marked_for_strip; public: @@ -707,52 +668,20 @@ public: PathInExpression (std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus, bool has_opening_scope_resolution = false) - : outer_attrs (std::move (outer_attrs)), + : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)), has_opening_scope_resolution (has_opening_scope_resolution), locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), - path (std::make_unique<RegularPath> (std::move (path_segments), locus, - _node_id)), marked_for_strip (false) {} - PathInExpression (LangItem::Kind lang_item_kind, + PathInExpression (LangItem::Kind lang_item, std::vector<Attribute> outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), + : Path (lang_item), outer_attrs (std::move (outer_attrs)), has_opening_scope_resolution (false), locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), - path (std::make_unique<LangItemPath> (lang_item_kind, locus)), marked_for_strip (false) {} - PathInExpression (std::unique_ptr<Path> path, - std::vector<Attribute> outer_attrs, location_t locus, - bool has_opening_scope_resolution = false) - : outer_attrs (std::move (outer_attrs)), - has_opening_scope_resolution (has_opening_scope_resolution), - locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), - path (std::move (path)), marked_for_strip (false) - {} - - PathInExpression (const PathInExpression &other) - : outer_attrs (other.outer_attrs), - has_opening_scope_resolution (other.has_opening_scope_resolution), - locus (other.locus), _node_id (other._node_id), - path (other.path->clone_path ()), - marked_for_strip (other.marked_for_strip) - {} - - PathInExpression &operator= (const PathInExpression &other) - { - outer_attrs = other.outer_attrs; - has_opening_scope_resolution = other.has_opening_scope_resolution; - locus = other.locus; - _node_id = other._node_id; - path = other.path->clone_path (); - marked_for_strip = other.marked_for_strip; - - return *this; - } - // Creates an error state path in expression. static PathInExpression create_error () { @@ -761,25 +690,19 @@ public: } // Returns whether path in expression is in an error state. - bool is_error () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return !static_cast<RegularPath &> (*path).has_segments (); - - rust_unreachable (); - } + bool is_error () const { return !has_segments (); } /* Converts PathInExpression to SimplePath if possible (i.e. no generic * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const { - // FIXME: Cleanup - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).convert_to_simple_path ( - has_opening_scope_resolution); - else - // FIXME: lang item to simple path? - rust_unreachable (); + /* delegate to parent class as can't access segments. however, + * QualifiedPathInExpression conversion to simple path wouldn't make + * sense, so the method in the parent class should be protected, not + * public. Have to pass in opening scope resolution as parent class has no + * access to it. + */ + return convert_to_simple_path (has_opening_scope_resolution); } location_t get_locus () const override final { return locus; } @@ -806,66 +729,18 @@ public: NodeId get_pattern_node_id () const { return get_node_id (); } - PathExprSegment &get_final_segment () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().back (); - - // lang item segment? - rust_unreachable (); - } - + PathExprSegment &get_final_segment () { return get_segments ().back (); } const PathExprSegment &get_final_segment () const { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().back (); - - // lang item segment? - rust_unreachable (); + return get_segments ().back (); } - const std::vector<PathExprSegment> &get_segments () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - std::vector<PathExprSegment> &get_segments () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - bool is_single_segment () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().size () == 1; - - rust_unreachable (); - } - - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - Expr::Kind get_expr_kind () const override { return Expr::Kind::PathInExpression; } protected: - PathInExpression (std::vector<Attribute> &&outer_attrs, - bool has_opening_scope_resolution, location_t locus, - NodeId node_id, std::unique_ptr<Path> &&path, - bool marked_for_strip) - : outer_attrs (std::move (outer_attrs)), - has_opening_scope_resolution (has_opening_scope_resolution), - locus (locus), _node_id (node_id), path (std::move (path)), - marked_for_strip (marked_for_strip) - {} - /* Use covariance to implement clone function as returning this object * rather than base */ PathInExpression *clone_pattern_impl () const final override @@ -899,7 +774,8 @@ public: }; private: - PathIdentSegment ident_segment; + tl::optional<LangItem::Kind> lang_item; + tl::optional<PathIdentSegment> ident_segment; location_t locus; protected: @@ -929,21 +805,30 @@ public: TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) - : ident_segment (std::move (ident_segment)), locus (locus), + : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)), + locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + TypePathSegment (LangItem::Kind lang_item, location_t locus) + : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus), + has_separating_scope_resolution (false), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (std::string segment_name, bool has_separating_scope_resolution, location_t locus) - : ident_segment (PathIdentSegment (std::move (segment_name), locus)), + : lang_item (tl::nullopt), + ident_segment (PathIdentSegment (std::move (segment_name), locus)), locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} TypePathSegment (TypePathSegment const &other) - : ident_segment (other.ident_segment), locus (other.locus), + : lang_item (other.lang_item), ident_segment (other.ident_segment), + locus (other.locus), has_separating_scope_resolution (other.has_separating_scope_resolution), node_id (other.node_id) {} @@ -951,6 +836,7 @@ public: TypePathSegment &operator= (TypePathSegment const &other) { ident_segment = other.ident_segment; + lang_item = other.lang_item; locus = other.locus; has_separating_scope_resolution = other.has_separating_scope_resolution; node_id = other.node_id; @@ -961,16 +847,28 @@ public: TypePathSegment (TypePathSegment &&other) = default; TypePathSegment &operator= (TypePathSegment &&other) = default; - virtual std::string as_string () const { return ident_segment.as_string (); } + virtual std::string as_string () const + { + if (lang_item.has_value ()) + return LangItem::PrettyString (*lang_item); + + return ident_segment->as_string (); + } /* Returns whether the type path segment is in an error state. May be * virtual in future. */ - bool is_error () const { return ident_segment.is_error (); } + bool is_error () const + { + rust_assert (ident_segment); + return ident_segment->is_error (); + } /* Returns whether segment is identifier only (as opposed to generic args or * function). Overridden in derived classes with other segments. */ virtual bool is_ident_only () const { return true; } + bool is_lang_item () const { return lang_item.has_value (); } + location_t get_locus () const { return locus; } // not pure virtual as class not abstract @@ -981,8 +879,23 @@ public: return has_separating_scope_resolution; } - PathIdentSegment &get_ident_segment () { return ident_segment; }; - const PathIdentSegment &get_ident_segment () const { return ident_segment; }; + PathIdentSegment &get_ident_segment () + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + const PathIdentSegment &get_ident_segment () const + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + LangItem::Kind get_lang_item () const + { + rust_assert (is_lang_item ()); + return *lang_item; + } NodeId get_node_id () const { return node_id; } @@ -1025,6 +938,12 @@ public: generic_args (std::move (generic_args)) {} + TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args, + location_t locus) + : TypePathSegment (lang_item, locus), + generic_args (std::move (generic_args)) + {} + // Constructor from segment name and all args TypePathSegmentGeneric (std::string segment_name, bool has_separating_scope_resolution, @@ -1082,7 +1001,7 @@ private: /*bool has_inputs; TypePathFnInputs inputs;*/ // inlined from TypePathFnInputs - std::vector<std::unique_ptr<Type> > inputs; + std::vector<std::unique_ptr<Type>> inputs; // bool has_type; std::unique_ptr<Type> return_type; @@ -1115,8 +1034,8 @@ public: } // Constructor - TypePathFunction (std::vector<std::unique_ptr<Type> > inputs, - location_t locus, std::unique_ptr<Type> type = nullptr) + TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus, + std::unique_ptr<Type> type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false), locus (locus) {} @@ -1161,11 +1080,11 @@ public: std::string as_string () const; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Type> > &get_params () const + const std::vector<std::unique_ptr<Type>> &get_params () const { return inputs; } - std::vector<std::unique_ptr<Type> > &get_params () { return inputs; } + std::vector<std::unique_ptr<Type>> &get_params () { return inputs; } // TODO: is this better? Or is a "vis_pattern" better? Type &get_return_type () @@ -1229,10 +1148,10 @@ public: } }; -class TypePath : public TypeNoBounds, public Path +class TypePath : public TypeNoBounds { bool has_opening_scope_resolution; - std::vector<std::unique_ptr<TypePathSegment> > segments; + std::vector<std::unique_ptr<TypePathSegment>> segments; location_t locus; protected: @@ -1257,12 +1176,20 @@ public: // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (), + return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION); } // Constructor - TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments, + TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments, + location_t locus, bool has_opening_scope_resolution = false) + : TypeNoBounds (), + has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)), locus (locus) + {} + + TypePath (LangItem::Kind lang_item, + std::vector<std::unique_ptr<TypePathSegment>> segments, location_t locus, bool has_opening_scope_resolution = false) : TypeNoBounds (), has_opening_scope_resolution (has_opening_scope_resolution), @@ -1308,7 +1235,7 @@ public: TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } - NodeId get_node_id () const override final { return node_id; } + NodeId get_node_id () const { return node_id; } void mark_for_strip () override {} bool is_marked_for_strip () const override { return false; } @@ -1316,27 +1243,23 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this seems kinda dodgy - std::vector<std::unique_ptr<TypePathSegment> > &get_segments () + std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; } - const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const + const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; } size_t get_num_segments () const { return segments.size (); } - - Path::Kind get_path_kind () const override { return Path::Kind::Type; } - - Path *clone_path_impl () const override { return new TypePath (*this); } }; struct QualifiedPathType { private: std::unique_ptr<Type> type_to_invoke_on; - std::unique_ptr<Path> trait_path; + TypePath trait_path; location_t locus; NodeId node_id; @@ -1345,14 +1268,13 @@ public: QualifiedPathType (std::unique_ptr<Type> invoke_on_type, location_t locus = UNDEF_LOCATION, TypePath trait_path = TypePath::create_error ()) - : type_to_invoke_on (std::move (invoke_on_type)), - trait_path (std::unique_ptr<TypePath> (new TypePath (trait_path))), + : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor uses custom deep copy for Type to preserve polymorphism QualifiedPathType (QualifiedPathType const &other) - : trait_path (other.trait_path->clone_path ()), locus (other.locus) + : trait_path (other.trait_path), locus (other.locus) { node_id = other.node_id; // guard to prevent null dereference @@ -1367,7 +1289,7 @@ public: QualifiedPathType &operator= (QualifiedPathType const &other) { node_id = other.node_id; - trait_path = other.trait_path->clone_path (); + trait_path = other.trait_path; locus = other.locus; // guard to prevent null dereference @@ -1384,11 +1306,7 @@ public: QualifiedPathType &operator= (QualifiedPathType &&other) = default; // Returns whether the qualified path type has a rebind as clause. - bool has_as_clause () const - { - rust_assert (trait_path->get_path_kind () == Path::Kind::Type); - return !static_cast<TypePath &> (*trait_path).is_error (); - } + bool has_as_clause () const { return !trait_path.is_error (); } // Returns whether the qualified path type is in an error state. bool is_error () const { return type_to_invoke_on == nullptr; } @@ -1417,10 +1335,10 @@ public: } // TODO: is this better? Or is a "vis_pattern" better? - Path &get_as_type_path () + TypePath &get_as_type_path () { rust_assert (has_as_clause ()); - return *trait_path; + return trait_path; } NodeId get_node_id () const { return node_id; } @@ -1428,12 +1346,12 @@ public: /* AST node representing a qualified path-in-expression pattern (path that * allows specifying trait functions) */ -class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock +class QualifiedPathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; QualifiedPathType path_type; - - std::unique_ptr<Path> path; + location_t locus; + NodeId _node_id; public: std::string as_string () const override; @@ -1442,16 +1360,9 @@ public: std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), - path_type (std::move (qual_path_type)), - path (std::make_unique<RegularPath> ( - std::move (path_segments), locus, - Analysis::Mappings::get ().get_next_node_id ())) - {} - - QualifiedPathInExpression (const QualifiedPathInExpression &other) - : outer_attrs (other.outer_attrs), path_type (other.path_type), - path (other.path->clone_path ()) + : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)), + path_type (std::move (qual_path_type)), locus (locus), + _node_id (Analysis::Mappings::get ().get_next_node_id ()) {} /* TODO: maybe make a shortcut constructor that has QualifiedPathType @@ -1467,9 +1378,7 @@ public: {}, UNDEF_LOCATION); } - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - - location_t get_locus () const override final { return path->get_locus (); } + location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -1495,31 +1404,7 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_node_id () const override { return path->get_node_id (); } - - const std::vector<PathExprSegment> &get_segments () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - std::vector<PathExprSegment> &get_segments () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - bool is_single_segment () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().size () == 1; - - rust_unreachable (); - } + NodeId get_node_id () const override { return _node_id; } Expr::Kind get_expr_kind () const override { @@ -1555,7 +1440,7 @@ class QualifiedPathInType : public TypeNoBounds { QualifiedPathType path_type; std::unique_ptr<TypePathSegment> associated_segment; - std::vector<std::unique_ptr<TypePathSegment> > segments; + std::vector<std::unique_ptr<TypePathSegment>> segments; location_t locus; protected: @@ -1570,7 +1455,7 @@ public: QualifiedPathInType ( QualifiedPathType qual_path_type, std::unique_ptr<TypePathSegment> associated_segment, - std::vector<std::unique_ptr<TypePathSegment> > path_segments, + std::vector<std::unique_ptr<TypePathSegment>> path_segments, location_t locus) : path_type (std::move (qual_path_type)), associated_segment (std::move (associated_segment)), @@ -1617,7 +1502,7 @@ public: { return QualifiedPathInType ( QualifiedPathType::create_error (), nullptr, - std::vector<std::unique_ptr<TypePathSegment> > (), UNDEF_LOCATION); + std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION); } std::string as_string () const override; @@ -1637,11 +1522,11 @@ public: } // TODO: this seems kinda dodgy - std::vector<std::unique_ptr<TypePathSegment> > &get_segments () + std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; } - const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const + const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; } |