diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-01-30 10:50:30 +0100 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2025-02-02 18:29:35 +0000 |
commit | 8a768c72cc077a8d62a7966a7c95727fa760c291 (patch) | |
tree | 9198b67a79f96d64d9cb21013e252a0370bb81da /gcc | |
parent | f4c396ce225bba720c2478ba80c8ac80faf4587d (diff) | |
download | gcc-8a768c72cc077a8d62a7966a7c95727fa760c291.zip gcc-8a768c72cc077a8d62a7966a7c95727fa760c291.tar.gz gcc-8a768c72cc077a8d62a7966a7c95727fa760c291.tar.bz2 |
derive-visitor: Add method for setting up derived impl generics
gcc/rust/ChangeLog:
* expand/rust-derive.cc (DeriveVisitor::setup_impl_generics): New method.
* expand/rust-derive.h: Declare it, define DeriveVisitor::ImplGenerics struct.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/expand/rust-derive.cc | 74 | ||||
-rw-r--r-- | gcc/rust/expand/rust-derive.h | 23 |
2 files changed, 97 insertions, 0 deletions
diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index e6778fe..c988412 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 517fee6..93025f1 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; |