diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index b6c6263e0b05..48b128f960af 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -84,6 +84,15 @@ struct GenericArgsBinding // and also identifier is empty, but cheaper computation } + GenericArgsBinding reconstruct () const + { + std::unique_ptr new_type = nullptr; + if (type) + new_type = type->reconstruct (); + + return GenericArgsBinding (identifier, std::move (new_type), locus); + } + // Creates an error state generic args binding. static GenericArgsBinding create_error () { @@ -190,6 +199,22 @@ class GenericArg return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus); } + GenericArg reconstruct () const + { + switch (kind) + { + case Kind::Type: + return create_type (type->reconstruct ()); + case Kind::Const: + // FIXME: Use reconstruct_expr when available + return create_const (expression->clone_expr ()); + case Kind::Either: + default: + // For ambiguous or error states, copy constructs are sufficient + return GenericArg (*this); + } + } + GenericArg (const GenericArg &other) : path (other.path), kind (other.kind), locus (other.locus) { @@ -460,6 +485,23 @@ struct GenericArgs ~GenericArgs () = default; + GenericArgs reconstruct () const + { + std::vector new_args; + new_args.reserve (generic_args.size ()); + for (const auto &arg : generic_args) + new_args.push_back (arg.reconstruct ()); + + std::vector new_bindings; + new_bindings.reserve (binding_args.size ()); + for (const auto &binding : binding_args) + new_bindings.push_back (binding.reconstruct ()); + + // Lifetimes are values, so they can be copied directly + return GenericArgs (lifetime_args, std::move (new_args), + std::move (new_bindings), locus); + } + // overloaded assignment operator to vector clone GenericArgs &operator= (GenericArgs const &other) { @@ -563,6 +605,11 @@ class PathExprSegment NodeId get_node_id () const { return node_id; } + PathExprSegment reconstruct () const + { + return PathExprSegment (segment_name, locus, generic_args.reconstruct ()); + } + bool is_super_path_seg () const { return !has_generic_args () && get_ident_segment ().is_super_path_seg (); @@ -705,6 +752,20 @@ class PathInExpression : public Path, public ExprWithoutBlock return convert_to_simple_path (has_opening_scope_resolution); } + std::unique_ptr reconstruct () const + { + std::vector new_segments; + new_segments.reserve (segments.size ()); + for (const auto &seg : segments) + new_segments.push_back (seg.reconstruct ()); + + auto *new_path + = new PathInExpression (std::move (new_segments), outer_attrs, locus, + has_opening_scope_resolution); + + return std::unique_ptr (new_path); + } + location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -1004,6 +1065,14 @@ class TypePathSegmentGeneric : public TypePathSegment { return new TypePathSegmentGeneric (*this); } + + TypePathSegmentGeneric *reconstruct_impl () const override + { + return new TypePathSegmentGeneric (get_ident_segment (), + has_separating_scope_resolution, + generic_args.reconstruct (), + get_locus ()); + } }; // A function as represented in a type path @@ -1112,6 +1181,21 @@ struct TypePathFunction return return_type; } + TypePathFunction reconstruct () const + { + std::vector> new_inputs; + new_inputs.reserve (inputs.size ()); + for (const auto &e : inputs) + new_inputs.push_back (e->reconstruct ()); + + std::unique_ptr new_ret = nullptr; + if (return_type) + new_ret = return_type->reconstruct (); + + return TypePathFunction (std::move (new_inputs), locus, + std::move (new_ret)); + } + location_t get_locus () const { return locus; } }; @@ -1159,6 +1243,14 @@ class TypePathSegmentFunction : public TypePathSegment { return new TypePathSegmentFunction (*this); } + + TypePathSegmentFunction *reconstruct_impl () const override + { + return new TypePathSegmentFunction (get_ident_segment (), + has_separating_scope_resolution, + function_path.reconstruct (), + get_locus ()); + } }; class TypePath : public TypeNoBounds @@ -1327,6 +1419,20 @@ struct QualifiedPathType QualifiedPathType (QualifiedPathType &&other) = default; QualifiedPathType &operator= (QualifiedPathType &&other) = default; + QualifiedPathType reconstruct () const + { + auto new_type = type_to_invoke_on->reconstruct (); + + // trait_path is stored by value, but reconstruct returns a unique_ptr. + // We must dereference it to pass to the constructor. + // This is safe because the constructor makes its own copy/move. + auto new_trait_path_ptr = trait_path.reconstruct (); + TypePath *concrete_ptr + = static_cast (new_trait_path_ptr.get ()); + + return QualifiedPathType (std::move (new_type), locus, *concrete_ptr); + } + // Returns whether the qualified path type has a rebind as clause. bool has_as_clause () const { return !trait_path.is_error (); } @@ -1433,6 +1539,20 @@ class QualifiedPathInExpression : public Path, public ExprWithoutBlock return Expr::Kind::QualifiedPathInExpression; } + std::unique_ptr reconstruct () const + { + std::vector new_segments; + new_segments.reserve (segments.size ()); + for (const auto &seg : segments) + new_segments.push_back (seg.reconstruct ()); + + auto *new_path = new QualifiedPathInExpression (path_type.reconstruct (), + std::move (new_segments), + outer_attrs, locus); + + return std::unique_ptr (new_path); + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1474,7 +1594,7 @@ class QualifiedPathInType : public TypeNoBounds } QualifiedPathInType *reconstruct_impl () const override { - return new QualifiedPathInType (path_type, + return new QualifiedPathInType (path_type.reconstruct (), associated_segment->reconstruct (), reconstruct_vec (segments), locus); } diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index 99100023d36c..3b8bf6da6e03 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -96,9 +96,8 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) }); } - // TODO: Replace with `reconstruct()` instead of building these twice auto self_variant_path = builder.variant_path (enum_path, variant_path); - auto other_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = self_variant_path.reconstruct (); auto self_pattern_items = std::unique_ptr ( new TupleStructItemsNoRest (std::move (self_patterns))); @@ -111,7 +110,7 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) false, false, builder.loc)); auto other_pattern = std::unique_ptr (new ReferencePattern ( std::unique_ptr (new TupleStructPattern ( - other_variant_path, std::move (other_pattern_items))), + *other_variant_path, std::move (other_pattern_items))), false, false, builder.loc)); auto tuple_items = std::make_unique ( @@ -159,9 +158,8 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw) }); } - // TODO: Replace with `reconstruct()` instead of building these twice auto self_variant_path = builder.variant_path (enum_path, variant_path); - auto other_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = self_variant_path.reconstruct (); auto self_elts = StructPatternElements (std::move (self_fields)); auto other_elts = StructPatternElements (std::move (other_fields)); @@ -172,7 +170,7 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw) false, false, builder.loc)); auto other_pattern = std::unique_ptr ( new ReferencePattern (std::unique_ptr ( - new StructPattern (other_variant_path, builder.loc, + new StructPattern (*other_variant_path, builder.loc, std::move (other_elts))), false, false, builder.loc));