return std::unique_ptr<Expr> (new DereferenceExpr (std::move (of), {}, loc));
}
+std::unique_ptr<Expr>
+AstBuilder::struct_expr (std::string struct_name,
+ std::vector<std::unique_ptr<StructExprField>> &&fields)
+{
+ return std::unique_ptr<Expr> (
+ new StructExprStructFields (path_in_expression ({struct_name}),
+ std::move (fields), loc));
+}
+
+std::unique_ptr<StructExprField>
+AstBuilder::struct_expr_field (std::string field_name,
+ std::unique_ptr<Expr> &&value)
+{
+ return std::unique_ptr<StructExprField> (
+ new StructExprFieldIdentifierValue (field_name, std::move (value), loc));
+}
+
+std::unique_ptr<Expr>
+AstBuilder::field_access (std::unique_ptr<Expr> &&instance, std::string field)
+{
+ return std::unique_ptr<Expr> (
+ new FieldAccessExpr (std::move (instance), field, {}, loc));
+}
+
} // namespace AST
} // namespace Rust
/* Create a struct expression for unit structs (`S`) */
std::unique_ptr<Expr> struct_expr_struct (std::string struct_name);
+ /**
+ * Create an expression for struct instantiation with fields (`S { a, b: c }`)
+ */
+ std::unique_ptr<Expr>
+ struct_expr (std::string struct_name,
+ std::vector<std::unique_ptr<StructExprField>> &&fields);
+
+ /* Create a field expression for struct instantiation (`field_name: value`) */
+ std::unique_ptr<StructExprField>
+ struct_expr_field (std::string field_name, std::unique_ptr<Expr> &&value);
+
+ /* Create a field access expression (`instance.field`) */
+ std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
+ std::string field);
+
private:
/**
* Location of the generated AST nodes
auto unit_ctor = builder.struct_expr_struct (item.get_struct_name ());
expanded = clone_impl (clone_fn (std::move (unit_ctor)),
item.get_struct_name ());
+ return;
}
- else
+
+ auto cloned_fields = std::vector<std::unique_ptr<StructExprField>> ();
+ for (auto &field : item.get_fields ())
{
- rust_sorry_at (item.get_locus (), "cannot derive %qs for these items yet",
- "Clone");
+ auto name = field.get_field_name ();
+ auto expr = clone_call (
+ builder.ref (builder.field_access (builder.identifier ("self"), name)));
+
+ cloned_fields.emplace_back (
+ builder.struct_expr_field (std::move (name), std::move (expr)));
}
+
+ auto ctor
+ = builder.struct_expr (item.get_struct_name (), std::move (cloned_fields));
+ expanded = clone_impl (clone_fn (std::move (ctor)), item.get_struct_name ());
}
void
--- /dev/null
+pub trait Clone {
+ fn clone(&self) -> Self;
+}
+
+#[derive(Clone)]
+struct Foo {
+ a: i32,
+}
+
+#[derive(Clone)]
+struct S {
+ a: i32,
+ b: Foo,
+}
+
+impl Clone for i32 {
+ fn clone(&self) -> Self { *self }
+}
+
+fn main() -> i32 {
+ let s1 = S { a: 15, b: Foo { a: 14 }};
+ let s2 = s1.clone();
+
+ let l = s1.a - s2.a;
+ let r = s1.b.a - s2.b.a;
+
+ // should be 0 if all fields were cloned correctly
+ l + r
+}
\ No newline at end of file