diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 58a5d5f7363..7f04136fe63 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -92,6 +92,7 @@ GRS_OBJS = \
rust/rust-cfg-strip.o \
rust/rust-expand-visitor.o \
rust/rust-ast-builder.o \
+ rust/rust-ast-builder-type.o \
rust/rust-derive.o \
rust/rust-derive-clone.o \
rust/rust-derive-copy.o \
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
new file mode 100644
index 00000000000..e76d0de0e9a
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-builder-type.cc
@@ -0,0 +1,164 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-ast-builder-type.h"
+#include "rust-ast-builder.h"
+#include "rust-ast-full.h"
+#include "rust-common.h"
+#include "rust-make-unique.h"
+
+namespace Rust {
+namespace AST {
+
+ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}
+
+Type *
+ASTTypeBuilder::build (Type &type)
+{
+ ASTTypeBuilder builder;
+ type.accept_vis (builder);
+ rust_assert (builder.translated != nullptr);
+ return builder.translated;
+}
+
+void
+ASTTypeBuilder::visit (BareFunctionType &fntype)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (TupleType &tuple)
+{
+ std::vector > elems;
+ for (auto &elem : tuple.get_elems ())
+ {
+ Type *t = ASTTypeBuilder::build (*elem.get ());
+ std::unique_ptr ty (t);
+ elems.push_back (std::move (ty));
+ }
+ translated = new TupleType (std::move (elems), tuple.get_locus ());
+}
+
+void
+ASTTypeBuilder::visit (TypePath &path)
+{
+ std::vector > segments;
+ for (auto &seg : path.get_segments ())
+ {
+ switch (seg->get_type ())
+ {
+ case TypePathSegment::REG: {
+ const TypePathSegment &segment
+ = (const TypePathSegment &) (*seg.get ());
+ TypePathSegment *s
+ = new TypePathSegment (segment.get_ident_segment (),
+ segment.get_separating_scope_resolution (),
+ segment.get_locus ());
+ std::unique_ptr sg (s);
+ segments.push_back (std::move (sg));
+ }
+ break;
+
+ case TypePathSegment::GENERIC: {
+ TypePathSegmentGeneric &generic
+ = (TypePathSegmentGeneric &) (*seg.get ());
+
+ GenericArgs args
+ = Builder::new_generic_args (generic.get_generic_args ());
+ TypePathSegmentGeneric *s
+ = new TypePathSegmentGeneric (generic.get_ident_segment (), false,
+ std::move (args),
+ generic.get_locus ());
+ std::unique_ptr sg (s);
+ segments.push_back (std::move (sg));
+ }
+ break;
+
+ case TypePathSegment::FUNCTION: {
+ rust_unreachable ();
+ // TODO
+ // const TypePathSegmentFunction &fn
+ // = (const TypePathSegmentFunction &) (*seg.get ());
+ }
+ break;
+ }
+ }
+
+ translated = new TypePath (std::move (segments), path.get_locus (),
+ path.has_opening_scope_resolution_op ());
+}
+
+void
+ASTTypeBuilder::visit (QualifiedPathInType &path)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (ArrayType &type)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (ReferenceType &type)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (RawPointerType &type)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (SliceType &type)
+{
+ Type *t = ASTTypeBuilder::build (type.get_elem_type ());
+ std::unique_ptr ty (t);
+ translated = new SliceType (std::move (ty), type.get_locus ());
+}
+
+void
+ASTTypeBuilder::visit (InferredType &type)
+{
+ translated = new InferredType (type.get_locus ());
+}
+
+void
+ASTTypeBuilder::visit (NeverType &type)
+{
+ translated = new NeverType (type.get_locus ());
+}
+
+void
+ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
+{
+ /* TODO */
+}
+
+void
+ASTTypeBuilder::visit (TraitObjectType &type)
+{
+ /* TODO */
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h
new file mode 100644
index 00000000000..b67ae3b553f
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-builder-type.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#ifndef RUST_AST_BUILDER_TYPE
+#define RUST_AST_BUILDER_TYPE
+
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace AST {
+
+class ASTTypeBuilder : public DefaultASTVisitor
+{
+protected:
+ using DefaultASTVisitor::visit;
+
+public:
+ static Type *build (Type &type);
+
+ void visit (BareFunctionType &fntype) override;
+ void visit (TupleType &tuple) override;
+ void visit (TypePath &path) override;
+ void visit (QualifiedPathInType &path) override;
+ void visit (ArrayType &type) override;
+ void visit (ReferenceType &type) override;
+ void visit (RawPointerType &type) override;
+ void visit (SliceType &type) override;
+ void visit (InferredType &type) override;
+ void visit (NeverType &type) override;
+ void visit (TraitObjectTypeOneBound &type) override;
+ void visit (TraitObjectType &type) override;
+
+private:
+ ASTTypeBuilder ();
+
+ Type *translated;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // RUST_AST_BUILDER_TYPE
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 381501498bd..121b8c8d7e0 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -17,8 +17,7 @@
// .
#include "rust-ast-builder.h"
-#include "rust-ast-full-decls.h"
-#include "rust-ast-full.h"
+#include "rust-ast-builder-type.h"
#include "rust-common.h"
#include "rust-expr.h"
#include "rust-token.h"
@@ -83,6 +82,13 @@ Builder::type_path_segment (std::string seg) const
new TypePathSegment (seg, false, loc));
}
+std::unique_ptr
+Builder::generic_type_path_segment (std::string seg, GenericArgs args) const
+{
+ return std::unique_ptr (
+ new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc));
+}
+
std::unique_ptr
Builder::single_type_path (std::string type) const
{
@@ -92,6 +98,15 @@ Builder::single_type_path (std::string type) const
return std::unique_ptr (new TypePath (std::move (segments), loc));
}
+std::unique_ptr
+Builder::single_generic_type_path (std::string type, GenericArgs args) const
+{
+ auto segments = std::vector> ();
+ segments.emplace_back (generic_type_path_segment (type, args));
+
+ return std::unique_ptr (new TypePath (std::move (segments), loc));
+}
+
PathInExpression
Builder::path_in_expression (std::vector &&segments) const
{
@@ -174,5 +189,187 @@ Builder::wildcard () const
return std::unique_ptr (new WildcardPattern (loc));
}
+std::unique_ptr
+Builder::new_type (Type &type)
+{
+ Type *t = ASTTypeBuilder::build (type);
+ return std::unique_ptr (t);
+}
+
+std::unique_ptr
+Builder::new_lifetime_param (LifetimeParam ¶m)
+{
+ Lifetime l = new_lifetime (param.get_lifetime ());
+ std::vector lifetime_bounds;
+ for (auto b : param.get_lifetime_bounds ())
+ {
+ Lifetime bl = new_lifetime (b);
+ lifetime_bounds.push_back (bl);
+ }
+
+ auto p = new LifetimeParam (l, std::move (lifetime_bounds),
+ param.get_outer_attrs (), param.get_locus ());
+ return std::unique_ptr (p);
+}
+
+std::unique_ptr
+Builder::new_type_param (TypeParam ¶m)
+{
+ location_t locus = param.get_locus ();
+ AST::AttrVec outer_attrs = param.get_outer_attrs ();
+ Identifier type_representation = param.get_type_representation ();
+ std::vector> type_param_bounds;
+ std::unique_ptr type = nullptr;
+
+ if (param.has_type ())
+ type = new_type (param.get_type ());
+
+ for (const auto &b : param.get_type_param_bounds ())
+ {
+ switch (b->get_bound_type ())
+ {
+ case TypeParamBound::TypeParamBoundType::TRAIT: {
+ const TraitBound &tb = (const TraitBound &) *b.get ();
+ const TypePath &path = tb.get_type_path ();
+
+ std::vector for_lifetimes;
+ for (const auto &lifetime : tb.get_for_lifetimes ())
+ {
+ std::vector lifetime_bounds;
+ for (const auto &b : lifetime.get_lifetime_bounds ())
+ {
+ Lifetime bl = new_lifetime (b);
+ lifetime_bounds.push_back (std::move (bl));
+ }
+
+ Lifetime nl = new_lifetime (lifetime.get_lifetime ());
+ LifetimeParam p (std::move (nl), std::move (lifetime_bounds),
+ {}, lifetime.get_locus ());
+ for_lifetimes.push_back (std::move (p));
+ }
+
+ std::vector> segments;
+ for (auto &seg : path.get_segments ())
+ {
+ switch (seg->get_type ())
+ {
+ case TypePathSegment::REG: {
+ const TypePathSegment &segment
+ = (const TypePathSegment &) (*seg.get ());
+ TypePathSegment *s = new TypePathSegment (
+ segment.get_ident_segment (),
+ segment.get_separating_scope_resolution (),
+ segment.get_locus ());
+ std::unique_ptr sg (s);
+ segments.push_back (std::move (sg));
+ }
+ break;
+
+ case TypePathSegment::GENERIC: {
+ TypePathSegmentGeneric &generic
+ = (TypePathSegmentGeneric &) (*seg.get ());
+
+ GenericArgs args
+ = new_generic_args (generic.get_generic_args ());
+ TypePathSegmentGeneric *s = new TypePathSegmentGeneric (
+ generic.get_ident_segment (), false, std::move (args),
+ generic.get_locus ());
+ std::unique_ptr sg (s);
+ segments.push_back (std::move (sg));
+ }
+ break;
+
+ case TypePathSegment::FUNCTION: {
+ rust_unreachable ();
+ // TODO
+ // const TypePathSegmentFunction &fn
+ // = (const TypePathSegmentFunction &) (*seg.get ());
+ }
+ break;
+ }
+ }
+
+ TypePath p (std::move (segments), path.get_locus (),
+ path.has_opening_scope_resolution_op ());
+
+ TraitBound *b = new TraitBound (std::move (p), tb.get_locus (),
+ tb.is_in_parens (),
+ tb.has_opening_question_mark (),
+ std::move (for_lifetimes));
+ std::unique_ptr bound (b);
+ type_param_bounds.push_back (std::move (bound));
+ }
+ break;
+
+ case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ const Lifetime &l = (const Lifetime &) *b.get ();
+
+ auto bl = new Lifetime (l.get_lifetime_type (),
+ l.get_lifetime_name (), l.get_locus ());
+ std::unique_ptr bound (bl);
+ type_param_bounds.push_back (std::move (bound));
+ }
+ break;
+ }
+ }
+
+ auto type_param
+ = new TypeParam (type_representation, locus, std::move (type_param_bounds),
+ std::move (type), std::move (outer_attrs));
+
+ return std::unique_ptr (type_param);
+}
+
+Lifetime
+Builder::new_lifetime (const Lifetime &lifetime)
+{
+ return Lifetime (lifetime.get_lifetime_type (), lifetime.get_lifetime_name (),
+ lifetime.get_locus ());
+}
+
+GenericArgs
+Builder::new_generic_args (GenericArgs &args)
+{
+ std::vector lifetime_args;
+ std::vector generic_args;
+ std::vector binding_args;
+ location_t locus = args.get_locus ();
+
+ for (const auto &lifetime : args.get_lifetime_args ())
+ {
+ Lifetime l = new_lifetime (lifetime);
+ lifetime_args.push_back (std::move (l));
+ }
+
+ for (auto &binding : args.get_binding_args ())
+ {
+ Type &t = *binding.get_type_ptr ().get ();
+ std::unique_ptr ty = new_type (t);
+ GenericArgsBinding b (binding.get_identifier (), std::move (ty),
+ binding.get_locus ());
+ binding_args.push_back (std::move (b));
+ }
+
+ for (auto &arg : args.get_generic_args ())
+ {
+ switch (arg.get_kind ())
+ {
+ case GenericArg::Kind::Type: {
+ std::unique_ptr ty = new_type (arg.get_type ());
+ GenericArg arg = GenericArg::create_type (std::move (ty));
+ }
+ break;
+
+ default:
+ // FIXME
+ rust_unreachable ();
+ break;
+ }
+ }
+
+ return GenericArgs (std::move (lifetime_args), std::move (generic_args),
+ std::move (binding_args), locus);
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 5c33954131f..fa258c7dfa8 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -82,10 +82,16 @@ class Builder
/* And similarly for type path segments */
std::unique_ptr type_path_segment (std::string seg) const;
+ std::unique_ptr
+ generic_type_path_segment (std::string seg, GenericArgs args) const;
+
/* Create a Type from a single string - the most basic kind of type in our AST
*/
std::unique_ptr single_type_path (std::string type) const;
+ std::unique_ptr single_generic_type_path (std::string type,
+ GenericArgs args) const;
+
/**
* Create a path in expression from multiple segments (`Clone::clone`). You
* do not need to separate the segments using `::`, you can simply provide a
@@ -116,6 +122,17 @@ class Builder
/* Create a wildcard pattern (`_`) */
std::unique_ptr wildcard () const;
+ static std::unique_ptr new_type (Type &type);
+
+ static std::unique_ptr
+ new_lifetime_param (LifetimeParam ¶m);
+
+ static std::unique_ptr new_type_param (TypeParam ¶m);
+
+ static Lifetime new_lifetime (const Lifetime &lifetime);
+
+ static GenericArgs new_generic_args (GenericArgs &args);
+
private:
/**
* Location of the generated AST nodes
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 35f27e37dcd..f83c99a57d2 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1477,6 +1477,12 @@ class TypeNoBounds : public Type
class TypeParamBound : public Visitable
{
public:
+ enum TypeParamBoundType
+ {
+ TRAIT,
+ LIFETIME
+ };
+
virtual ~TypeParamBound () {}
// Unique pointer custom clone function
@@ -1491,6 +1497,8 @@ class TypeParamBound : public Visitable
virtual location_t get_locus () const = 0;
+ virtual TypeParamBoundType get_bound_type () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
@@ -1546,12 +1554,17 @@ class Lifetime : public TypeParamBound
void accept_vis (ASTVisitor &vis) override;
- LifetimeType get_lifetime_type () { return lifetime_type; }
+ LifetimeType get_lifetime_type () const { return lifetime_type; }
location_t get_locus () const override final { return locus; }
std::string get_lifetime_name () const { return lifetime_name; }
+ TypeParamBoundType get_bound_type () const override
+ {
+ return TypeParamBound::TypeParamBoundType::LIFETIME;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1619,6 +1632,11 @@ class LifetimeParam : public GenericParam
std::vector &get_lifetime_bounds () { return lifetime_bounds; }
+ const std::vector &get_lifetime_bounds () const
+ {
+ return lifetime_bounds;
+ }
+
// Returns whether the lifetime param has an outer attribute.
bool has_outer_attribute () const { return !outer_attrs.empty (); }
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 3b88a15f777..5ca2c7f4394 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -479,15 +479,23 @@ struct GenericArgs
std::string as_string () const;
- // TODO: is this better? Or is a "vis_pattern" better?
std::vector &get_generic_args () { return generic_args; }
- // TODO: is this better? Or is a "vis_pattern" better?
std::vector &get_binding_args () { return binding_args; }
+ const std::vector &get_binding_args () const
+ {
+ return binding_args;
+ }
+
std::vector &get_lifetime_args () { return lifetime_args; };
- location_t get_locus () { return locus; }
+ const std::vector &get_lifetime_args () const
+ {
+ return lifetime_args;
+ };
+
+ location_t get_locus () const { return locus; }
};
/* A segment of a path in expression, including an identifier aspect and maybe
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 410d64819bb..b6b76497d3b 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -48,6 +48,11 @@ class TraitBound : public TypeParamBound
std::vector &get_for_lifetimes () { return for_lifetimes; }
+ const std::vector &get_for_lifetimes () const
+ {
+ return for_lifetimes;
+ }
+
TraitBound (TypePath type_path, location_t locus, bool in_parens = false,
bool opening_question_mark = false,
std::vector for_lifetimes
@@ -81,6 +86,11 @@ class TraitBound : public TypeParamBound
bool is_in_parens () const { return in_parens; }
bool has_opening_question_mark () const { return opening_question_mark; }
+ TypeParamBoundType get_bound_type () const override
+ {
+ return TypeParamBound::TypeParamBoundType::TRAIT;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index d09ea2c455b..2d1b5995ba2 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -73,8 +73,9 @@ DeriveClone::clone_fn (std::unique_ptr &&clone_expr)
*
*/
std::unique_ptr-
-DeriveClone::clone_impl (std::unique_ptr &&clone_fn,
- std::string name)
+DeriveClone::clone_impl (
+ std::unique_ptr &&clone_fn, std::string name,
+ const std::vector> &type_generics)
{
// should that be `$crate::core::clone::Clone` instead?
auto segments = std::vector> ();
@@ -84,10 +85,79 @@ DeriveClone::clone_impl (std::unique_ptr &&clone_fn,
auto trait_items = std::vector> ();
trait_items.emplace_back (std::move (clone_fn));
+ // we need to build up the generics for this impl block which will be just a
+ // clone of the types specified ones
+ //
+ // for example:
+ //
+ // #[derive(Clone)]
+ // struct Be { ... }
+ //
+ // we need to generate the impl block:
+ //
+ // impl Clone for Be
+
+ std::vector lifetime_args;
+ std::vector generic_args;
+ std::vector> impl_generics;
+ for (const auto &generic : type_generics)
+ {
+ switch (generic->get_kind ())
+ {
+ case GenericParam::Kind::Lifetime: {
+ LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get ();
+
+ Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ());
+ lifetime_args.push_back (std::move (l));
+
+ auto impl_lifetime_param
+ = builder.new_lifetime_param (lifetime_param);
+ impl_generics.push_back (std::move (impl_lifetime_param));
+ }
+ break;
+
+ case GenericParam::Kind::Type: {
+ TypeParam &type_param = (TypeParam &) *generic.get ();
+
+ std::unique_ptr associated_type = builder.single_type_path (
+ type_param.get_type_representation ().as_string ());
+
+ GenericArg type_arg
+ = GenericArg::create_type (std::move (associated_type));
+ generic_args.push_back (std::move (type_arg));
+
+ auto impl_type_param = builder.new_type_param (type_param);
+ impl_generics.push_back (std::move (impl_type_param));
+ }
+ break;
+
+ case GenericParam::Kind::Const: {
+ rust_unreachable ();
+
+ // TODO
+ // const ConstGenericParam *const_param
+ // = (const ConstGenericParam *) generic.get ();
+ // std::unique_ptr const_expr = nullptr;
+
+ // GenericArg type_arg
+ // = GenericArg::create_const (std::move (const_expr));
+ // generic_args.push_back (std::move (type_arg));
+ }
+ break;
+ }
+ }
+
+ GenericArgs generic_args_for_self (lifetime_args, generic_args,
+ {} /*binding args*/, loc);
+ std::unique_ptr self_type_path
+ = impl_generics.empty ()
+ ? builder.single_type_path (name)
+ : builder.single_generic_type_path (name, generic_args_for_self);
+
return std::unique_ptr
- (
new TraitImpl (clone, /* unsafe */ false,
/* exclam */ false, std::move (trait_items),
- /* generics */ {}, builder.single_type_path (name),
+ std::move (impl_generics), std::move (self_type_path),
WhereClause::create_empty (), Visibility::create_private (),
{}, {}, loc));
}
@@ -122,7 +192,8 @@ DeriveClone::visit_tuple (TupleStruct &item)
auto constructor = builder.call (std::move (path), std::move (cloned_fields));
expanded = clone_impl (clone_fn (std::move (constructor)),
- item.get_identifier ().as_string ());
+ item.get_identifier ().as_string (),
+ item.get_generic_params ());
}
void
@@ -133,7 +204,8 @@ DeriveClone::visit_struct (StructStruct &item)
auto unit_ctor
= builder.struct_expr_struct (item.get_struct_name ().as_string ());
expanded = clone_impl (clone_fn (std::move (unit_ctor)),
- item.get_struct_name ().as_string ());
+ item.get_struct_name ().as_string (),
+ item.get_generic_params ());
return;
}
@@ -151,7 +223,8 @@ DeriveClone::visit_struct (StructStruct &item)
auto ctor = builder.struct_expr (item.get_struct_name ().as_string (),
std::move (cloned_fields));
expanded = clone_impl (clone_fn (std::move (ctor)),
- item.get_struct_name ().as_string ());
+ item.get_struct_name ().as_string (),
+ item.get_generic_params ());
}
void
@@ -187,7 +260,8 @@ DeriveClone::visit_union (Union &item)
auto block = builder.block (std::move (stmts), std::move (tail_expr));
expanded = clone_impl (clone_fn (std::move (block)),
- item.get_identifier ().as_string ());
+ item.get_identifier ().as_string (),
+ item.get_generic_params ());
}
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h
index 31756576c5f..043f9182efa 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -59,8 +59,9 @@ class DeriveClone : DeriveVisitor
* }
*
*/
- std::unique_ptr
- clone_impl (std::unique_ptr &&clone_fn,
- std::string name);
+ std::unique_ptr
-
+ clone_impl (std::unique_ptr &&clone_fn, std::string name,
+ const std::vector> &type_generics);
virtual void visit_struct (StructStruct &item);
virtual void visit_tuple (TupleStruct &item);
diff --git a/gcc/rust/expand/rust-derive-copy.cc b/gcc/rust/expand/rust-derive-copy.cc
index a9a300bf750..070a7cd63bc 100644
--- a/gcc/rust/expand/rust-derive-copy.cc
+++ b/gcc/rust/expand/rust-derive-copy.cc
@@ -37,17 +37,88 @@ DeriveCopy::go (Item &item)
}
std::unique_ptr
-
-DeriveCopy::copy_impl (std::string name)
+DeriveCopy::copy_impl (
+ std::string name,
+ const std::vector> &type_generics)
{
// `$crate::core::marker::Copy` instead
auto segments = std::vector> ();
segments.emplace_back (builder.type_path_segment ("Copy"));
auto copy = TypePath (std::move (segments), loc);
+ // we need to build up the generics for this impl block which will be just a
+ // clone of the types specified ones
+ //
+ // for example:
+ //
+ // #[derive(Copy)]
+ // struct Be { ... }
+ //
+ // we need to generate the impl block:
+ //
+ // impl Clone for Be
+
+ std::vector lifetime_args;
+ std::vector generic_args;
+ std::vector> impl_generics;
+ for (const auto &generic : type_generics)
+ {
+ switch (generic->get_kind ())
+ {
+ case GenericParam::Kind::Lifetime: {
+ LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get ();
+
+ Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ());
+ lifetime_args.push_back (std::move (l));
+
+ auto impl_lifetime_param
+ = builder.new_lifetime_param (lifetime_param);
+ impl_generics.push_back (std::move (impl_lifetime_param));
+ }
+ break;
+
+ case GenericParam::Kind::Type: {
+ TypeParam &type_param = (TypeParam &) *generic.get ();
+
+ std::unique_ptr associated_type = builder.single_type_path (
+ type_param.get_type_representation ().as_string ());
+
+ GenericArg type_arg
+ = GenericArg::create_type (std::move (associated_type));
+ generic_args.push_back (std::move (type_arg));
+
+ auto impl_type_param = builder.new_type_param (type_param);
+ impl_generics.push_back (std::move (impl_type_param));
+ }
+ break;
+
+ case GenericParam::Kind::Const: {
+ rust_unreachable ();
+
+ // TODO
+ // const ConstGenericParam *const_param
+ // = (const ConstGenericParam *) generic.get ();
+ // std::unique_ptr const_expr = nullptr;
+
+ // GenericArg type_arg
+ // = GenericArg::create_const (std::move (const_expr));
+ // generic_args.push_back (std::move (type_arg));
+ }
+ break;
+ }
+ }
+
+ GenericArgs generic_args_for_self (lifetime_args, generic_args,
+ {} /*binding args*/, loc);
+ std::unique_ptr self_type_path
+ = impl_generics.empty ()
+ ? builder.single_type_path (name)
+ : builder.single_generic_type_path (name, generic_args_for_self);
+
return std::unique_ptr
- (
new TraitImpl (copy, /* unsafe */ false,
/* exclam */ false, /* trait items */ {},
- /* generics */ {}, builder.single_type_path (name),
+ std::move (impl_generics), std::move (self_type_path),
WhereClause::create_empty (), Visibility::create_private (),
{}, {}, loc));
}
@@ -55,25 +126,29 @@ DeriveCopy::copy_impl (std::string name)
void
DeriveCopy::visit_struct (StructStruct &item)
{
- expanded = copy_impl (item.get_struct_name ().as_string ());
+ expanded = copy_impl (item.get_struct_name ().as_string (),
+ item.get_generic_params ());
}
void
DeriveCopy::visit_tuple (TupleStruct &item)
{
- expanded = copy_impl (item.get_struct_name ().as_string ());
+ expanded = copy_impl (item.get_struct_name ().as_string (),
+ item.get_generic_params ());
}
void
DeriveCopy::visit_enum (Enum &item)
{
- expanded = copy_impl (item.get_identifier ().as_string ());
+ expanded = copy_impl (item.get_identifier ().as_string (),
+ item.get_generic_params ());
}
void
DeriveCopy::visit_union (Union &item)
{
- expanded = copy_impl (item.get_identifier ().as_string ());
+ expanded = copy_impl (item.get_identifier ().as_string (),
+ item.get_generic_params ());
}
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h
index 73903b901b3..ef6817679ed 100644
--- a/gcc/rust/expand/rust-derive-copy.h
+++ b/gcc/rust/expand/rust-derive-copy.h
@@ -40,7 +40,9 @@ class DeriveCopy : DeriveVisitor
*
* impl Copy for {}
*/
- std::unique_ptr
- copy_impl (std::string name);
+ std::unique_ptr
-
+ copy_impl (std::string name,
+ const std::vector> &type_generics);
virtual void visit_struct (StructStruct &item);
virtual void visit_tuple (TupleStruct &item);
diff --git a/gcc/testsuite/rust/compile/issue-3139-1.rs b/gcc/testsuite/rust/compile/issue-3139-1.rs
new file mode 100644
index 00000000000..84ca3ddd6ef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3139-1.rs
@@ -0,0 +1,45 @@
+#![feature(lang_items)]
+
+#[lang = "clone"]
+trait Clone {
+ fn clone(&self) -> Self;
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+struct Abound {
+ a: u32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+ b: u32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+#[derive(Clone)]
+struct Be {
+ a: T,
+ b: Abound,
+}
+
+impl Clone for u32 {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Clone for usize {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Clone for Abound {
+ fn clone(&self) -> Self {
+ return Abound { a: self.a.clone(), b: self.b.clone() };
+ }
+}
+
+fn main() {
+ let b: Be = Be {a:1,b:Abound { a:0,b:1 }};
+ let _: Be = b.clone();
+}
diff --git a/gcc/testsuite/rust/compile/issue-3139-2.rs b/gcc/testsuite/rust/compile/issue-3139-2.rs
new file mode 100644
index 00000000000..0d298fa20a5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3139-2.rs
@@ -0,0 +1,57 @@
+#![feature(lang_items)]
+
+#[lang = "clone"]
+trait Clone {
+ fn clone(&self) -> Self;
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+struct Abound {
+ a: u32,
+ b: u32,
+}
+
+struct Be {
+ a: T,
+ b: Abound,
+}
+
+impl Clone for Be {
+ fn clone(&self) -> Self {
+ return Be:: {
+ a: self.a.clone(),
+ b: self.b.clone(),
+ };
+ }
+}
+
+impl Clone for u32 {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Clone for usize {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Clone for Abound {
+ fn clone(&self) -> Self {
+ return Abound {
+ a: self.a.clone(),
+ b: self.b.clone(),
+ };
+ }
+}
+
+fn main() {
+ let b: Be = Be {
+ a: 1,
+ b: Abound { a: 0, b: 1 },
+ };
+ let _: Be = b.clone();
+}
diff --git a/gcc/testsuite/rust/compile/issue-3139-3.rs b/gcc/testsuite/rust/compile/issue-3139-3.rs
new file mode 100644
index 00000000000..4a4546e823b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3139-3.rs
@@ -0,0 +1,32 @@
+#![feature(lang_items)]
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[derive(Copy)]
+struct Abound {
+ a: u32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+ b: u32,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+#[derive(Copy)]
+struct Be {
+ a: T,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+ b: Abound,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl Copy for usize {}
+
+fn main() {
+ let _: Be = Be {
+ a: 1,
+ b: Abound { a: 0, b: 1 },
+ };
+}
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
index 769a6de8931..bfb51fd7fee 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -249,3 +249,6 @@ inline_asm_parse_output_operand.rs
issue-3030.rs
issue-3035.rs
issue-3082.rs
+issue-3139-1.rs
+issue-3139-2.rs
+issue-3139-3.rs