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