mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Document (and test) a problem with Clone/Copy deriving.
This commit is contained in:
@@ -384,6 +384,7 @@ fn resolve_derives(
|
||||
// is applied, so they have to be produced by the container's expansion rather
|
||||
// than by individual derives.
|
||||
// - Derives in the container need to know whether one of them is a built-in `Copy`.
|
||||
// (But see the comment mentioning #124794 below.)
|
||||
// Temporarily take the data to avoid borrow checker conflicts.
|
||||
let mut derive_data = mem::take(&mut self.derive_data);
|
||||
let entry = derive_data.entry(expn_id).or_insert_with(|| DeriveData {
|
||||
@@ -440,7 +441,13 @@ fn resolve_derives(
|
||||
.collect();
|
||||
self.helper_attrs.insert(expn_id, helper_attrs);
|
||||
// Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive
|
||||
// has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`.
|
||||
// has `Copy`, to support `#[derive(Copy, Clone)]`, `#[derive(Clone, Copy)]`, or
|
||||
// `#[derive(Copy)] #[derive(Clone)]`. We do this because the code generated for
|
||||
// `derive(Clone)` changes if `derive(Copy)` is also present.
|
||||
//
|
||||
// FIXME(#124794): unfortunately this doesn't work with `#[derive(Clone)] #[derive(Copy)]`.
|
||||
// When the `Clone` impl is generated the `#[derive(Copy)]` hasn't been processed and
|
||||
// `has_derive_copy` hasn't been set yet.
|
||||
if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) {
|
||||
self.containers_deriving_copy.insert(expn_id);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct Empty;
|
||||
|
||||
// A basic struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A basic struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct Point {
|
||||
@@ -32,7 +32,7 @@ struct Point {
|
||||
y: u32,
|
||||
}
|
||||
|
||||
// A basic packed struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A basic packed struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[repr(packed)]
|
||||
@@ -49,7 +49,7 @@ struct SingleField {
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
// A large struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A large struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct Big {
|
||||
@@ -79,25 +79,25 @@ struct Reorder {
|
||||
b10: &'static *const bool,
|
||||
}
|
||||
|
||||
// A struct that doesn't impl `Copy`, which means it gets the non-simple
|
||||
// A struct that doesn't impl `Copy`, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
#[derive(Clone)]
|
||||
struct NonCopy(u32);
|
||||
|
||||
// A packed struct that doesn't impl `Copy`, which means it gets the non-simple
|
||||
// A packed struct that doesn't impl `Copy`, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
#[derive(Clone)]
|
||||
#[repr(packed)]
|
||||
struct PackedNonCopy(u32);
|
||||
|
||||
// A struct that impls `Copy` manually, which means it gets the non-simple
|
||||
// A struct that impls `Copy` manually, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
#[derive(Clone)]
|
||||
struct ManualCopy(u32);
|
||||
impl Copy for ManualCopy {}
|
||||
|
||||
// A packed struct that impls `Copy` manually, which means it gets the
|
||||
// non-simple `clone` implemention that clones the fields individually.
|
||||
// non-trivial `clone` implemention that clones the fields individually.
|
||||
#[derive(Clone)]
|
||||
#[repr(packed)]
|
||||
struct PackedManualCopy(u32);
|
||||
@@ -218,3 +218,20 @@ pub union Union {
|
||||
pub u: u32,
|
||||
pub i: i32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct FooCopyClone(i32);
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct FooCloneCopy(i32);
|
||||
|
||||
#[derive(Copy)]
|
||||
#[derive(Clone)]
|
||||
struct FooCopyAndClone(i32);
|
||||
|
||||
// FIXME(#124794): the previous three structs all have a trivial `Copy`-aware
|
||||
// `clone`. But this one doesn't because when the `clone` is generated the
|
||||
// `derive(Copy)` hasn't yet been seen.
|
||||
#[derive(Clone)]
|
||||
#[derive(Copy)]
|
||||
struct FooCloneAndCopy(i32);
|
||||
|
||||
@@ -84,7 +84,7 @@ impl ::core::cmp::Ord for Empty {
|
||||
}
|
||||
}
|
||||
|
||||
// A basic struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A basic struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
struct Point {
|
||||
x: u32,
|
||||
@@ -171,7 +171,7 @@ impl ::core::cmp::Ord for Point {
|
||||
}
|
||||
}
|
||||
|
||||
// A basic packed struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A basic packed struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
#[repr(packed)]
|
||||
struct PackedPoint {
|
||||
@@ -409,7 +409,7 @@ impl ::core::cmp::Ord for SingleField {
|
||||
}
|
||||
}
|
||||
|
||||
// A large struct. Note: because this derives `Copy`, it gets the simple
|
||||
// A large struct. Note: because this derives `Copy`, it gets the trivial
|
||||
// `clone` implemention that just does `*self`.
|
||||
struct Big {
|
||||
b1: u32,
|
||||
@@ -676,7 +676,7 @@ impl ::core::cmp::PartialOrd for Reorder {
|
||||
}
|
||||
}
|
||||
|
||||
// A struct that doesn't impl `Copy`, which means it gets the non-simple
|
||||
// A struct that doesn't impl `Copy`, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
struct NonCopy(u32);
|
||||
#[automatically_derived]
|
||||
@@ -687,7 +687,7 @@ impl ::core::clone::Clone for NonCopy {
|
||||
}
|
||||
}
|
||||
|
||||
// A packed struct that doesn't impl `Copy`, which means it gets the non-simple
|
||||
// A packed struct that doesn't impl `Copy`, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
#[repr(packed)]
|
||||
struct PackedNonCopy(u32);
|
||||
@@ -699,7 +699,7 @@ impl ::core::clone::Clone for PackedNonCopy {
|
||||
}
|
||||
}
|
||||
|
||||
// A struct that impls `Copy` manually, which means it gets the non-simple
|
||||
// A struct that impls `Copy` manually, which means it gets the non-trivial
|
||||
// `clone` implemention that clones the fields individually.
|
||||
struct ManualCopy(u32);
|
||||
#[automatically_derived]
|
||||
@@ -712,7 +712,7 @@ impl ::core::clone::Clone for ManualCopy {
|
||||
impl Copy for ManualCopy {}
|
||||
|
||||
// A packed struct that impls `Copy` manually, which means it gets the
|
||||
// non-simple `clone` implemention that clones the fields individually.
|
||||
// non-trivial `clone` implemention that clones the fields individually.
|
||||
#[repr(packed)]
|
||||
struct PackedManualCopy(u32);
|
||||
#[automatically_derived]
|
||||
@@ -1791,3 +1791,62 @@ impl ::core::clone::Clone for Union {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for Union { }
|
||||
|
||||
struct FooCopyClone(i32);
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for FooCopyClone { }
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
unsafe impl ::core::clone::TrivialClone for FooCopyClone { }
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for FooCopyClone {
|
||||
#[inline]
|
||||
fn clone(&self) -> FooCopyClone {
|
||||
let _: ::core::clone::AssertParamIsClone<i32>;
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
struct FooCloneCopy(i32);
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
unsafe impl ::core::clone::TrivialClone for FooCloneCopy { }
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for FooCloneCopy {
|
||||
#[inline]
|
||||
fn clone(&self) -> FooCloneCopy {
|
||||
let _: ::core::clone::AssertParamIsClone<i32>;
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for FooCloneCopy { }
|
||||
|
||||
struct FooCopyAndClone(i32);
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
unsafe impl ::core::clone::TrivialClone for FooCopyAndClone { }
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for FooCopyAndClone {
|
||||
#[inline]
|
||||
fn clone(&self) -> FooCopyAndClone {
|
||||
let _: ::core::clone::AssertParamIsClone<i32>;
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for FooCopyAndClone { }
|
||||
|
||||
// FIXME(#124794): the previous three structs all have a trivial `Copy`-aware
|
||||
// `clone`. But this one doesn't because when the `clone` is generated the
|
||||
// `derive(Copy)` hasn't yet been seen.
|
||||
struct FooCloneAndCopy(i32);
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for FooCloneAndCopy { }
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for FooCloneAndCopy {
|
||||
#[inline]
|
||||
fn clone(&self) -> FooCloneAndCopy {
|
||||
FooCloneAndCopy(::core::clone::Clone::clone(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user