aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2025-01-30 10:50:30 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2025-02-02 18:29:35 +0000
commit8a768c72cc077a8d62a7966a7c95727fa760c291 (patch)
tree9198b67a79f96d64d9cb21013e252a0370bb81da /gcc
parentf4c396ce225bba720c2478ba80c8ac80faf4587d (diff)
downloadgcc-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.cc74
-rw-r--r--gcc/rust/expand/rust-derive.h23
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;