diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index d10b64e6e25..eccc474187f 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -18,9 +18,13 @@ #include "rust-ast-builder.h" #include "rust-ast-builder-type.h" +#include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-path.h" +#include "rust-item.h" +#include "rust-path.h" +#include "rust-system.h" #include "rust-token.h" namespace Rust { @@ -99,12 +103,27 @@ Builder::type_path_segment (std::string seg) const } std::unique_ptr -Builder::generic_type_path_segment (std::string seg, GenericArgs args) const +Builder::type_path_segment (LangItem::Kind lang_item) const +{ + return std::unique_ptr ( + new TypePathSegment (lang_item, loc)); +} + +std::unique_ptr +Builder::type_path_segment_generic (std::string seg, GenericArgs args) const { return std::unique_ptr ( new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc)); } +std::unique_ptr +Builder::type_path_segment_generic (LangItem::Kind lang_item, + GenericArgs args) const +{ + return std::unique_ptr ( + new TypePathSegmentGeneric (lang_item, args, loc)); +} + std::unique_ptr Builder::single_type_path (std::string type) const { @@ -114,15 +133,52 @@ Builder::single_type_path (std::string type) const return std::unique_ptr (new TypePath (std::move (segments), loc)); } +std::unique_ptr +Builder::single_type_path (LangItem::Kind lang_item) const +{ + return std::unique_ptr (new TypePath (lang_item, {}, loc)); +} + std::unique_ptr Builder::single_generic_type_path (std::string type, GenericArgs args) const { auto segments = std::vector> (); - segments.emplace_back (generic_type_path_segment (type, args)); + segments.emplace_back (type_path_segment_generic (type, args)); + + return std::unique_ptr (new TypePath (std::move (segments), loc)); +} + +std::unique_ptr +Builder::single_generic_type_path (LangItem::Kind lang_item, + GenericArgs args) const +{ + auto segments = std::vector> (); + segments.emplace_back (type_path_segment_generic (lang_item, args)); return std::unique_ptr (new TypePath (std::move (segments), loc)); } +TypePath +Builder::type_path (std::unique_ptr &&segment) const +{ + auto segments = std::vector> (); + segments.emplace_back (std::move (segment)); + + return TypePath (std::move (segments), loc); +} + +TypePath +Builder::type_path (std::string type) const +{ + return type_path (type_path_segment (type)); +} + +TypePath +Builder::type_path (LangItem::Kind lang_item) const +{ + return type_path (type_path_segment (lang_item)); +} + PathInExpression Builder::path_in_expression (std::vector &&segments) const { @@ -182,6 +238,19 @@ Builder::deref (std::unique_ptr &&of) const return std::unique_ptr (new DereferenceExpr (std::move (of), {}, loc)); } +std::unique_ptr +Builder::struct_struct (std::string struct_name, + std::vector> &&generics, + std::vector &&fields) +{ + auto is_unit = fields.empty (); + + return std::unique_ptr ( + new StructStruct (std::move (fields), struct_name, std::move (generics), + WhereClause::create_empty (), is_unit, + Visibility::create_private (), {}, loc)); +} + std::unique_ptr Builder::struct_expr_struct (std::string struct_name) const { @@ -193,10 +262,17 @@ std::unique_ptr Builder::struct_expr ( std::string struct_name, std::vector> &&fields) const +{ + return struct_expr (path_in_expression ({struct_name}), std::move (fields)); +} + +std::unique_ptr +Builder::struct_expr ( + PathInExpression struct_name, + std::vector> &&fields) const { return std::unique_ptr ( - new StructExprStructFields (path_in_expression ({struct_name}), - std::move (fields), loc)); + new StructExprStructFields (struct_name, std::move (fields), loc)); } std::unique_ptr diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 2c7b3f8007a..7e224d3db5f 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -21,10 +21,35 @@ #include "rust-ast-full.h" #include "rust-expr.h" +#include "rust-ast.h" +#include "rust-item.h" namespace Rust { namespace AST { +template +std::vector> +vec (std::unique_ptr &&t) +{ + auto v = std::vector> (); + + v.emplace_back (std::move (t)); + + return v; +} + +template +std::vector> +vec (std::unique_ptr &&t1, std::unique_ptr &&t2) +{ + auto v = std::vector> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (t2)); + + return v; +} + // TODO: Use this builder when expanding regular macros /* Builder class with helper methods to create AST nodes. This builder is * tailored towards generating multiple AST nodes from a single location, and @@ -89,16 +114,27 @@ class Builder /* And similarly for type path segments */ std::unique_ptr type_path_segment (std::string seg) const; + std::unique_ptr + type_path_segment (LangItem::Kind lang_item) const; std::unique_ptr - generic_type_path_segment (std::string seg, GenericArgs args) const; + type_path_segment_generic (std::string seg, GenericArgs args) const; + std::unique_ptr + type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const; /* Create a Type from a single string - the most basic kind of type in our AST */ std::unique_ptr single_type_path (std::string type) const; + std::unique_ptr single_type_path (LangItem::Kind lang_item) const; std::unique_ptr single_generic_type_path (std::string type, GenericArgs args) const; + std::unique_ptr single_generic_type_path (LangItem::Kind lang_item, + GenericArgs args) const; + + TypePath type_path (std::unique_ptr &&segment) const; + TypePath type_path (std::string type) const; + TypePath type_path (LangItem::Kind lang_item) const; /** * Create a path in expression from multiple segments (`Clone::clone`). You @@ -113,15 +149,26 @@ class Builder */ PathInExpression path_in_expression (LangItem::Kind lang_item) const; + /* Create a new struct */ + std::unique_ptr + struct_struct (std::string struct_name, + std::vector> &&generics, + std::vector &&fields); + /* Create a struct expression for unit structs (`S`) */ std::unique_ptr struct_expr_struct (std::string struct_name) const; /** * Create an expression for struct instantiation with fields (`S { a, b: c }`) + * Tuple expressions are call expressions and can thus be constructed with + * `call` */ std::unique_ptr struct_expr (std::string struct_name, std::vector> &&fields) const; + std::unique_ptr + struct_expr (PathInExpression struct_name, + std::vector> &&fields) const; /* Create a field expression for struct instantiation (`field_name: value`) */ std::unique_ptr diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 2d1b5995ba2..e914d6012b6 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -17,7 +17,13 @@ // . #include "rust-derive-clone.h" +#include "rust-ast.h" +#include "rust-ast-dump.h" +#include "rust-expr.h" #include "rust-item.h" +#include "rust-path.h" +#include "rust-pattern.h" +#include "rust-system.h" namespace Rust { namespace AST { @@ -28,6 +34,15 @@ DeriveClone::clone_call (std::unique_ptr &&to_clone) // $crate::core::clone::Clone::clone for the fully qualified path - we don't // link with `core` yet so that might be an issue. Use `Clone::clone` for now? // TODO: Factor this function inside the DeriveAccumulator + + // Interestingly, later versions of Rust have a `clone_fn` lang item which + // corresponds to this. But because we are first targeting 1.49, we cannot use + // it yet. Once we target a new, more recent version of the language, we'll + // have figured out how to compile and distribute `core`, meaning we'll be + // able to directly call `::core::clone::Clone::clone()` + + // Not sure how to call it properly in the meantime... + auto path = std::unique_ptr ( new PathInExpression (builder.path_in_expression ({"Clone", "clone"}))); @@ -77,10 +92,7 @@ DeriveClone::clone_impl ( std::unique_ptr &&clone_fn, std::string name, const std::vector> &type_generics) { - // should that be `$crate::core::clone::Clone` instead? - auto segments = std::vector> (); - segments.emplace_back (builder.type_path_segment ("Clone")); - auto clone = TypePath (std::move (segments), loc); + auto clone = builder.type_path (LangItem::Kind::CLONE); auto trait_items = std::vector> (); trait_items.emplace_back (std::move (clone_fn)); @@ -227,24 +239,216 @@ DeriveClone::visit_struct (StructStruct &item) item.get_generic_params ()); } +PathInExpression +DeriveClone::variant_match_path (Enum &item, const Identifier &variant) +{ + return PathInExpression ({builder.path_segment ( + item.get_identifier ().as_string ()), + builder.path_segment (variant.as_string ())}, + {}, loc, false); +} + +MatchCase +DeriveClone::clone_enum_identifier (Enum &item, + const std::unique_ptr &variant) +{ + auto variant_path = variant_match_path (item, variant->get_identifier ()); + + auto pattern = std::unique_ptr (new ReferencePattern ( + std::unique_ptr (new PathInExpression (variant_path)), false, + false, loc)); + auto expr = std::unique_ptr (new PathInExpression (variant_path)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + +MatchCase +DeriveClone::clone_enum_tuple (Enum &item, const EnumItemTuple &variant) +{ + auto variant_path = variant_match_path (item, variant.get_identifier ()); + + auto patterns = std::vector> (); + auto cloned_patterns = std::vector> (); + + for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) + { + // The pattern we're creating for each field is `self_` where `i` is + // the index of the field. It doesn't actually matter what we use, as long + // as it's ordered, unique, and that we can reuse it in the match case's + // return expression to clone the field. + auto pattern_str = "__self_" + std::to_string (i); + + patterns.emplace_back (builder.identifier_pattern (pattern_str)); + + // Now, for each tuple's element, we create a new expression calling + // `clone` on it for the match case's return expression + cloned_patterns.emplace_back ( + clone_call (builder.ref (builder.identifier (pattern_str)))); + } + + auto pattern_items = std::unique_ptr ( + new TupleStructItemsNoRange (std::move (patterns))); + + auto pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new TupleStructPattern ( + variant_path, std::move (pattern_items))), + false, false, loc)); + + auto expr + = builder.call (std::unique_ptr (new PathInExpression (variant_path)), + std::move (cloned_patterns)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + +MatchCase +DeriveClone::clone_enum_struct (Enum &item, const EnumItemStruct &variant) +{ + auto variant_path = variant_match_path (item, variant.get_identifier ()); + + auto field_patterns = std::vector> (); + auto cloned_fields = std::vector> (); + +#if 0 + // NOTE: We currently do not support compiling struct patterns where an + // identifier is assigned a new pattern, e.g. Bloop { f0: x } + // This is the code we should eventually produce as it mimics what rustc does + // - which is probably here for a good reason. In the meantime, we can just + // use the field's identifier as the pattern: Bloop { f0 } + // We can then clone the field directly instead of calling `clone()` on the + // new pattern. + // TODO: Figure out if that is actually needed and why rustc does it? + + for (size_t i = 0; i < variant.get_struct_fields ().size (); i++) + { + auto &field = variant.get_struct_fields ()[i]; + + // Just like for tuples, the pattern we're creating for each field is + // `self_` where `i` is the index of the field. It doesn't actually + // matter what we use, as long as it's ordered, unique, and that we can + // reuse it in the match case's return expression to clone the field. + auto pattern_str = "__self_" + std::to_string (i); + + field_patterns.emplace_back ( + std::unique_ptr (new StructPatternFieldIdentPat ( + field.get_field_name (), builder.identifier_pattern (pattern_str), {}, + loc))); + + cloned_fields.emplace_back ( + std::unique_ptr (new StructExprFieldIdentifierValue ( + field.get_field_name (), + clone_call (builder.ref (builder.identifier (pattern_str))), {}, + loc))); + } +#endif + + for (const auto &field : variant.get_struct_fields ()) + { + // We match on the struct's fields, and then recreate an instance of that + // struct, cloning each field + + field_patterns.emplace_back ( + std::unique_ptr (new StructPatternFieldIdent ( + field.get_field_name (), false /* is_ref? true? */, false, {}, loc))); + + cloned_fields.emplace_back ( + std::unique_ptr (new StructExprFieldIdentifierValue ( + field.get_field_name (), + clone_call (builder.ref ( + builder.identifier (field.get_field_name ().as_string ()))), + {}, loc))); + } + + auto pattern_elts = StructPatternElements (std::move (field_patterns)); + + auto pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, loc, pattern_elts)), + false, false, loc)); + auto expr = std::unique_ptr ( + new StructExprStructFields (variant_path, std::move (cloned_fields), loc)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + void DeriveClone::visit_enum (Enum &item) { - rust_sorry_at (item.get_locus (), "cannot derive %qs for these items yet", - "Clone"); + // Create an arm for each variant of the enum: + // - For enum item variants (simple identifiers), just create the same + // variant. + // - For struct and tuple variants, destructure the pattern and call clone for + // each field. + + auto cases = std::vector (); + + for (const auto &variant : item.get_variants ()) + { + switch (variant->get_enum_item_kind ()) + { + // Identifiers and discriminated variants are the same for a clone - we + // just return the same variant + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + cases.emplace_back (clone_enum_identifier (item, variant)); + break; + case EnumItem::Kind::Tuple: + cases.emplace_back ( + clone_enum_tuple (item, static_cast (*variant))); + break; + case EnumItem::Kind::Struct: + cases.emplace_back ( + clone_enum_struct (item, static_cast (*variant))); + break; + } + } + + // match self { ... } + auto match = builder.match (builder.identifier ("self"), std::move (cases)); + + expanded = clone_impl (clone_fn (std::move (match)), + item.get_identifier ().as_string (), + item.get_generic_params ()); } void DeriveClone::visit_union (Union &item) { // FIXME: Should be $crate::core::clone::AssertParamIsCopy (or similar) + // (Rust-GCC#3329) + + auto copy_path = TypePath (vec (builder.type_path_segment ("Copy")), loc); + auto sized_path = TypePath (vec (builder.type_path_segment ("Sized")), loc); + + auto copy_bound = std::unique_ptr ( + new TraitBound (copy_path, item.get_locus ())); + auto sized_bound = std::unique_ptr ( + new TraitBound (sized_path, item.get_locus (), false, true)); + + auto bounds = std::vector> (); + bounds.emplace_back (std::move (copy_bound)); + bounds.emplace_back (std::move (sized_bound)); + + // struct AssertParamIsCopy { _t: PhantomData } + auto assert_param_is_copy = "AssertParamIsCopy"; + auto t = std::unique_ptr ( + new TypeParam (Identifier ("T"), item.get_locus (), std::move (bounds))); + auto assert_param_is_copy_struct = builder.struct_struct ( + assert_param_is_copy, vec (std::move (t)), + {StructField ( + Identifier ("_t"), + builder.single_generic_type_path ( + LangItem::Kind::PHANTOM_DATA, + GenericArgs ( + {}, {GenericArg::create_type (builder.single_type_path ("T"))}, {})), + Visibility::create_private (), item.get_locus ())}); // auto arg = GenericArg::create_type (builder.single_type_path ("Self")); // AssertParamIsCopy:: auto type = std::unique_ptr ( - new TypePathSegmentGeneric (PathIdentSegment ("AssertParamIsCopy", loc), + new TypePathSegmentGeneric (PathIdentSegment (assert_param_is_copy, loc), false, GenericArgs ({}, {arg}, {}, loc), loc)); auto type_paths = std::vector> (); type_paths.emplace_back (std::move (type)); @@ -252,11 +456,12 @@ DeriveClone::visit_union (Union &item) auto full_path = std::unique_ptr (new TypePath ({std::move (type_paths)}, loc)); - auto stmts = std::vector> (); - stmts.emplace_back ( - builder.let (builder.wildcard (), std::move (full_path), nullptr)); auto tail_expr = builder.deref (builder.identifier ("self")); + auto stmts + = vec (std::move (assert_param_is_copy_struct), + builder.let (builder.wildcard (), std::move (full_path), nullptr)); + auto block = builder.block (std::move (stmts), std::move (tail_expr)); expanded = clone_impl (clone_fn (std::move (block)), diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index 043f9182efa..844b53f0472 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -63,6 +63,21 @@ class DeriveClone : DeriveVisitor clone_impl (std::unique_ptr &&clone_fn, std::string name, const std::vector> &type_generics); + /** + * Get the path to use for matching and creating a variant when matching on an + * enum. E.g. for the `Option` enum, with the `None` variant, this will create + * a path `Option::None` + */ + PathInExpression variant_match_path (Enum &item, const Identifier &variant); + + /** + * Implementation of clone for all possible variants of an enum + */ + MatchCase clone_enum_identifier (Enum &item, + const std::unique_ptr &variant); + MatchCase clone_enum_tuple (Enum &item, const EnumItemTuple &variant); + MatchCase clone_enum_struct (Enum &item, const EnumItemStruct &variant); + virtual void visit_struct (StructStruct &item); virtual void visit_tuple (TupleStruct &item); virtual void visit_enum (Enum &item); diff --git a/gcc/rust/expand/rust-derive-copy.cc b/gcc/rust/expand/rust-derive-copy.cc index 358a52e9481..1f52a08e7cc 100644 --- a/gcc/rust/expand/rust-derive-copy.cc +++ b/gcc/rust/expand/rust-derive-copy.cc @@ -18,6 +18,7 @@ #include "rust-derive-copy.h" #include "rust-ast-full.h" +#include "rust-hir-map.h" #include "rust-mapping-common.h" #include "rust-path.h" @@ -43,12 +44,7 @@ DeriveCopy::copy_impl ( std::string name, const std::vector> &type_generics) { - // `$crate::core::marker::Copy` instead - auto segments = std::vector> (); - segments.emplace_back (builder.type_path_segment ("Copy")); - - auto copy = TypePath (std::move (segments), loc); - // auto copy = TypePath (LangItem::Kind::COPY, loc); + auto copy = builder.type_path (LangItem::Kind::COPY); // we need to build up the generics for this impl block which will be just a // clone of the types specified ones diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 60b8952f152..f3ee08f4a03 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -218,19 +218,12 @@ Late::visit (AST::PathInExpression &expr) // in a function item` error here? // do we emit it in `get`? - rust_debug ("[ARTHUR]: %s", expr.as_simple_path ().as_string ().c_str ()); + auto resolved + = ctx.values.resolve_path (expr.get_segments ()).or_else ([&] () { + return ctx.types.resolve_path (expr.get_segments ()); + }); - tl::optional resolved = tl::nullopt; - - if (auto value = ctx.values.resolve_path (expr.get_segments ())) - { - resolved = value; - } - else if (auto type = ctx.types.resolve_path (expr.get_segments ())) - { - resolved = type; - } - else + if (!resolved) { rust_error_at (expr.get_locus (), "could not resolve path expression: %qs", @@ -244,6 +237,7 @@ Late::visit (AST::PathInExpression &expr) expr.as_string ().c_str ()); return; } + ctx.map_usage (Usage (expr.get_node_id ()), Definition (resolved->get_node_id ())); } diff --git a/gcc/testsuite/rust/compile/derive_clone_enum1.rs b/gcc/testsuite/rust/compile/derive_clone_enum1.rs new file mode 100644 index 00000000000..947dc5c694c --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum1.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum AllIdentifiers { + A, + B +} diff --git a/gcc/testsuite/rust/compile/derive_clone_enum2.rs b/gcc/testsuite/rust/compile/derive_clone_enum2.rs new file mode 100644 index 00000000000..c7a4ad5fd64 --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum2.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum TupleEnum { + A(i32), + B(i32, i32, i32) +} diff --git a/gcc/testsuite/rust/compile/derive_clone_enum3.rs b/gcc/testsuite/rust/compile/derive_clone_enum3.rs new file mode 100644 index 00000000000..92fd6eeeb2b --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum3.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum StructEnum { + A { i0: i32 }, + B { i0: i32, i1: i32, i2: i32 } +} diff --git a/gcc/testsuite/rust/compile/derive_macro1.rs b/gcc/testsuite/rust/compile/derive_macro1.rs index 779aad78e11..bc10d601bb8 100644 --- a/gcc/testsuite/rust/compile/derive_macro1.rs +++ b/gcc/testsuite/rust/compile/derive_macro1.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } diff --git a/gcc/testsuite/rust/compile/derive_macro3.rs b/gcc/testsuite/rust/compile/derive_macro3.rs index 1c7d4737bfe..ad40cae94b5 100644 --- a/gcc/testsuite/rust/compile/derive_macro3.rs +++ b/gcc/testsuite/rust/compile/derive_macro3.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } diff --git a/gcc/testsuite/rust/compile/derive_macro4.rs b/gcc/testsuite/rust/compile/derive_macro4.rs index 7802e8fd800..8bf1bcaf5f7 100644 --- a/gcc/testsuite/rust/compile/derive_macro4.rs +++ b/gcc/testsuite/rust/compile/derive_macro4.rs @@ -1,17 +1,17 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "copy"] pub trait Copy {} + +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } +#[lang = "phantom_data"] struct PhantomData; -pub struct AssertParamIsCopy { - _field: PhantomData, -} - #[derive(Clone)] // { dg-error "bounds not satisfied for U .Copy. is not satisfied" } union U { i: i32, diff --git a/gcc/testsuite/rust/compile/derive_macro6.rs b/gcc/testsuite/rust/compile/derive_macro6.rs index b7bf7a78acd..35327c03b54 100644 --- a/gcc/testsuite/rust/compile/derive_macro6.rs +++ b/gcc/testsuite/rust/compile/derive_macro6.rs @@ -2,6 +2,9 @@ pub trait Sized {} pub trait Copy {} + + +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } @@ -9,10 +12,6 @@ pub trait Clone { #[lang = "phantom_data"] pub struct PhantomData; -pub struct AssertParamIsCopy { - pub _field: PhantomData, -} - impl Copy for i32 {} impl Copy for i64 {} impl Copy for U {} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 0f482df2f00..60322f3276a 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -143,4 +143,12 @@ additional-trait-bounds2.rs auto_traits3.rs issue-3140.rs cmp1.rs +derive_clone_enum1.rs +derive_clone_enum2.rs +derive_clone_enum3.rs +derive_macro4.rs +derive_macro6.rs +issue-2987.rs +issue-3139-1.rs +issue-3139-3.rs # please don't delete the trailing newline diff --git a/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs b/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs new file mode 100644 index 00000000000..542ecd83db0 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs @@ -0,0 +1,51 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum MixAndMatch { + A, + B(i32), + C { inner: i32 } +} + +fn main() -> i32 { + let a = MixAndMatch::A; + let a_copy = a.clone(); + + // we want res to stay at zero - when we don't match on the right thing, increase it + + let mut res = match a_copy { + MixAndMatch::A => 0, + _ => 1, + }; + + let a = MixAndMatch::B(15); + let a_copy = a.clone(); + + match a_copy { + MixAndMatch::B(15) => {}, + _ => res += 1, + }; + + let a = MixAndMatch::C { inner: 15 }; + let a_copy = a.clone(); + + match a_copy { + MixAndMatch::C { inner } => { + if inner != 15 { + res += 1; + } + }, + _ => res += 1, + }; + + res +} diff --git a/gcc/testsuite/rust/execute/torture/derive_macro3.rs b/gcc/testsuite/rust/execute/torture/derive_macro3.rs index 7b3a089d751..4138a5bf7e4 100644 --- a/gcc/testsuite/rust/execute/torture/derive_macro3.rs +++ b/gcc/testsuite/rust/execute/torture/derive_macro3.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } diff --git a/gcc/testsuite/rust/execute/torture/derive_macro4.rs b/gcc/testsuite/rust/execute/torture/derive_macro4.rs index c355ac7905f..38c4808574a 100644 --- a/gcc/testsuite/rust/execute/torture/derive_macro4.rs +++ b/gcc/testsuite/rust/execute/torture/derive_macro4.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; }