aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2023-05-12 15:14:49 +0200
committerCohenArthur <arthur.cohen@embecosm.com>2023-06-02 14:32:58 +0000
commitd9c676cbfc3e5f2566b4d55fa52b00919ee338ca (patch)
treed443ad50c64dcb7cd5923e6432b83e47c32a3636 /gcc
parent2946327ff94f1653dd57f7362b6402e9b8353643 (diff)
downloadgcc-d9c676cbfc3e5f2566b4d55fa52b00919ee338ca.zip
gcc-d9c676cbfc3e5f2566b4d55fa52b00919ee338ca.tar.gz
gcc-d9c676cbfc3e5f2566b4d55fa52b00919ee338ca.tar.bz2
derive: Add proper derive(Clone) for unions
gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (AstBuilder::struct_expr_struct): New function. (AstBuilder::let): Likewise. (AstBuilder::struct_expr): Likewise. (AstBuilder::struct_expr_field): Likewise. (AstBuilder::field_access): Likewise. (AstBuilder::wildcard): Likewise. * ast/rust-ast-builder.h: Likewise. * expand/rust-derive-clone.cc (DeriveClone::visit_union): Implement properly. gcc/testsuite/ChangeLog: * rust/compile/derive_macro4.rs: New test. * rust/compile/derive_macro6.rs: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc26
-rw-r--r--gcc/rust/ast/rust-ast-builder.h3
-rw-r--r--gcc/rust/expand/rust-derive-clone.cc25
-rw-r--r--gcc/testsuite/rust/compile/derive_macro4.rs16
-rw-r--r--gcc/testsuite/rust/compile/derive_macro6.rs21
5 files changed, 79 insertions, 12 deletions
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index d37f143..b630cfa 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -82,13 +82,6 @@ AstBuilder::path_in_expression (std::vector<std::string> &&segments)
}
std::unique_ptr<Expr>
-AstBuilder::struct_expr_struct (std::string struct_name)
-{
- return std::unique_ptr<Expr> (
- new StructExprStruct (path_in_expression ({struct_name}), {}, {}, loc));
-}
-
-std::unique_ptr<Expr>
AstBuilder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr)
{
@@ -100,9 +93,9 @@ std::unique_ptr<Stmt>
AstBuilder::let (std::unique_ptr<Pattern> pattern, std::unique_ptr<Type> type,
std::unique_ptr<Expr> init)
{
- return std::unique_ptr<Stmt> (
- new LetStmt (/* needs a pattern here, not just a name */ nullptr,
- std::move (init), std::move (type), {}, loc));
+ return std::unique_ptr<Stmt> (new LetStmt (std::move (pattern),
+ std::move (init), std::move (type),
+ {}, loc));
}
std::unique_ptr<Expr>
@@ -119,6 +112,13 @@ AstBuilder::deref (std::unique_ptr<Expr> &&of)
}
std::unique_ptr<Expr>
+AstBuilder::struct_expr_struct (std::string struct_name)
+{
+ return std::unique_ptr<Expr> (
+ new StructExprStruct (path_in_expression ({struct_name}), {}, {}, loc));
+}
+
+std::unique_ptr<Expr>
AstBuilder::struct_expr (std::string struct_name,
std::vector<std::unique_ptr<StructExprField>> &&fields)
{
@@ -142,5 +142,11 @@ AstBuilder::field_access (std::unique_ptr<Expr> &&instance, std::string field)
new FieldAccessExpr (std::move (instance), field, {}, loc));
}
+std::unique_ptr<Pattern>
+AstBuilder::wildcard ()
+{
+ return std::unique_ptr<Pattern> (new WildcardPattern (loc));
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 1c524b4..524b390 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -100,6 +100,9 @@ public:
std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
std::string field);
+ /* Create a wildcard pattern (`_`) */
+ std::unique_ptr<Pattern> wildcard ();
+
private:
/**
* Location of the generated AST nodes
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index 176cee9..8529bac5 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -155,8 +155,29 @@ DeriveClone::visit_enum (Enum &item)
void
DeriveClone::visit_union (Union &item)
{
- rust_sorry_at (item.get_locus (), "cannot derive %qs for these items yet",
- "Clone");
+ // FIXME: Should be $crate::core::clone::AssertParamIsCopy (or similar)
+
+ // <Self>
+ auto arg = GenericArg::create_type (builder.single_type_path ("Self"));
+
+ // AssertParamIsCopy::<Self>
+ auto type = std::unique_ptr<TypePathSegment> (
+ new TypePathSegmentGeneric (PathIdentSegment ("AssertParamIsCopy", loc),
+ false, GenericArgs ({}, {arg}, {}, loc), loc));
+ auto type_paths = std::vector<std::unique_ptr<TypePathSegment>> ();
+ type_paths.emplace_back (std::move (type));
+
+ auto full_path
+ = std::unique_ptr<Type> (new TypePath ({std::move (type_paths)}, loc));
+
+ auto stmts = std::vector<std::unique_ptr<Stmt>> ();
+ stmts.emplace_back (
+ builder.let (builder.wildcard (), std::move (full_path), nullptr));
+ auto tail_expr = builder.deref (builder.identifier ("self"));
+
+ auto block = builder.block (std::move (stmts), std::move (tail_expr));
+
+ expanded = clone_impl (clone_fn (std::move (block)), item.get_identifier ());
}
} // namespace AST
diff --git a/gcc/testsuite/rust/compile/derive_macro4.rs b/gcc/testsuite/rust/compile/derive_macro4.rs
new file mode 100644
index 0000000..564555f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive_macro4.rs
@@ -0,0 +1,16 @@
+pub trait Copy {}
+pub trait Clone {
+ fn clone(&self) -> Self;
+}
+
+struct PhantomData<T>;
+
+pub struct AssertParamIsCopy<T: Copy> {
+ _field: PhantomData<T>,
+}
+
+#[derive(Clone)] // { dg-error "bounds not satisfied for U .Copy. is not satisfied" }
+union U {
+ i: i32,
+ f: f64,
+}
diff --git a/gcc/testsuite/rust/compile/derive_macro6.rs b/gcc/testsuite/rust/compile/derive_macro6.rs
new file mode 100644
index 0000000..0254754
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive_macro6.rs
@@ -0,0 +1,21 @@
+pub trait Copy {}
+pub trait Clone {
+ fn clone(&self) -> Self;
+}
+
+#[lang = "phantom_data"]
+pub struct PhantomData<T>;
+
+pub struct AssertParamIsCopy<T: Copy> {
+ pub _field: PhantomData<T>,
+}
+
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for U {}
+
+#[derive(Clone)]
+union U {
+ i: i32,
+ f: f64,
+}