From: Arthur Cohen <arthur.co...@embecosm.com> gcc/rust/ChangeLog:
* expand/rust-derive.cc (DeriveVisitor::setup_impl_generics): New method. * expand/rust-derive.h: Declare it, define DeriveVisitor::ImplGenerics struct. --- gcc/rust/expand/rust-derive.cc | 74 ++++++++++++++++++++++++++++++++++ gcc/rust/expand/rust-derive.h | 23 +++++++++++ 2 files changed, 97 insertions(+) diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index a3784837ad7..13675ba594c 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -50,5 +50,79 @@ DeriveVisitor::derive (Item &item, const Attribute &attr, }; } +DeriveVisitor::ImplGenerics +DeriveVisitor::setup_impl_generics ( + const std::string &type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics, + tl::optional<std::unique_ptr<TypeParamBound>> &&extra_bound) const +{ + std::vector<Lifetime> lifetime_args; + std::vector<GenericArg> generic_args; + std::vector<std::unique_ptr<GenericParam>> 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<Type> 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)); + + std::vector<std::unique_ptr<TypeParamBound>> extra_bounds; + + if (extra_bound) + extra_bounds.emplace_back (std::move (*extra_bound)); + + auto impl_type_param + = builder.new_type_param (type_param, std::move (extra_bounds)); + + 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<Expr> const_expr = nullptr; + + // GenericArg type_arg + // = GenericArg::create_const (std::move (const_expr)); + // generic_args.push_back (std::move (type_arg)); + } + break; + } + } + + auto generic_args_for_self + = GenericArgs (lifetime_args, generic_args, {} /*binding args*/, loc); + + std::unique_ptr<Type> self_type_path + = impl_generics.empty () + ? builder.single_type_path (type_name) + : builder.single_generic_type_path (type_name, generic_args_for_self); + + return ImplGenerics{std::move (self_type_path), std::move (impl_generics)}; +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 1924432d8ed..a494cc3c312 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -43,6 +43,29 @@ protected: location_t loc; Builder builder; + struct ImplGenerics + { + /* The type we are deriving the impl for */ + std::unique_ptr<Type> self_type; + + /* Generics for the impl itself */ + std::vector<std::unique_ptr<GenericParam>> impl; + }; + + /** + * Create the generic parameters for a derive impl block. Derived impl blocks + * will often share the same structure of reusing the exact same bounds as + * their original type, plus adding an extra one for the trait we are + * deriving. For example, when deriving `Clone` on `Foo<T>`, you want to make + * sure that you implement `Clone` only if `T: Clone` - so you add an extra + * `Clone` bound to all of your generics. + */ + ImplGenerics setup_impl_generics ( + const std::string &type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics, + tl::optional<std::unique_ptr<TypeParamBound>> &&extra_bound + = tl::nullopt) const; + private: // the 4 "allowed" visitors, which a derive-visitor can specify and override virtual void visit_struct (StructStruct &struct_item) = 0; -- 2.45.2