diff options
Diffstat (limited to 'tests/ui/deriving')
52 files changed, 3112 insertions, 0 deletions
diff --git a/tests/ui/deriving/auxiliary/derive-no-std.rs b/tests/ui/deriving/auxiliary/derive-no-std.rs new file mode 100644 index 000000000..3893dc1be --- /dev/null +++ b/tests/ui/deriving/auxiliary/derive-no-std.rs @@ -0,0 +1,29 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +// Issue #16803 + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Default, Copy)] +pub struct Foo { + pub x: u32, +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub enum Bar { + Qux, + Quux(u32), +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub enum Void {} +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct Empty; +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct AlsoEmpty {} diff --git a/tests/ui/deriving/derive-no-std.rs b/tests/ui/deriving/derive-no-std.rs new file mode 100644 index 000000000..74c73b99c --- /dev/null +++ b/tests/ui/deriving/derive-no-std.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:derive-no-std.rs + +extern crate derive_no_std; +use derive_no_std::*; + +fn main() { + let f = Foo { x: 0 }; + assert_eq!(f.clone(), Foo::default()); + + assert!(Bar::Qux < Bar::Quux(42)); +} diff --git a/tests/ui/deriving/derive-partialord-correctness.rs b/tests/ui/deriving/derive-partialord-correctness.rs new file mode 100644 index 000000000..36763eda1 --- /dev/null +++ b/tests/ui/deriving/derive-partialord-correctness.rs @@ -0,0 +1,9 @@ +// run-pass +// Original issue: #49650 + +#[derive(PartialOrd, PartialEq)] +struct FloatWrapper(f64); + +fn main() { + assert!((0.0 / 0.0 >= 0.0) == (FloatWrapper(0.0 / 0.0) >= FloatWrapper(0.0))) +} diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs new file mode 100644 index 000000000..ba7809413 --- /dev/null +++ b/tests/ui/deriving/deriving-all-codegen.rs @@ -0,0 +1,106 @@ +// check-pass +// compile-flags: -Zunpretty=expanded +// edition:2021 +// +// This test checks the code generated for all[*] the builtin derivable traits +// on a variety of structs and enums. It protects against accidental changes to +// the generated code, and makes deliberate changes to the generated code +// easier to review. +// +// [*] It excludes `Copy` in some cases, because that changes the code +// generated for `Clone`. +// +// [*] It excludes `RustcEncodable` and `RustDecodable`, which are obsolete and +// also require the `rustc_serialize` crate. + +#![crate_type = "lib"] +#![allow(dead_code)] +#![allow(deprecated)] + +// Empty struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Empty; + +// A basic struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Point { + x: u32, + y: u32, +} + +// A large struct. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Big { + b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8: u32, +} + +// A struct with an unsized field. Some derives are not usable in this case. +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Unsized([u32]); + +// A packed tuple struct that impls `Copy`. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct PackedCopy(u32); + +// A packed tuple struct that does not impl `Copy`. Note that the alignment of +// the field must be 1 for this code to be valid. Otherwise it triggers an +// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not +// derive Copy (error E0133)" at MIR building time. This is a weird case and +// it's possible that this struct is not supposed to work, but for now it does. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct PackedNonCopy(u8); + +// An empty enum. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Enum0 {} + +// A single-variant enum. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Enum1 { + Single { x: u32 } +} + +// A C-like, fieldless enum with a single variant. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fieldless1 { + #[default] + A, +} + +// A C-like, fieldless enum. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fieldless { + #[default] + A, + B, + C, +} + +// An enum with multiple fieldless and fielded variants. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Mixed { + #[default] + P, + Q, + R(u32), + S { d1: Option<u32>, d2: Option<i32> }, +} + +// An enum with no fieldless variants. Note that `Default` cannot be derived +// for this enum. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fielded { + X(u32), + Y(bool), + Z(Option<i32>), +} + +// A union. Most builtin traits are not derivable for unions. +#[derive(Clone, Copy)] +pub union Union { + pub b: bool, + pub u: u32, + pub i: i32, +} diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout new file mode 100644 index 000000000..e6ee11a78 --- /dev/null +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -0,0 +1,1074 @@ +#![feature(prelude_import)] +// check-pass +// compile-flags: -Zunpretty=expanded +// edition:2021 +// +// This test checks the code generated for all[*] the builtin derivable traits +// on a variety of structs and enums. It protects against accidental changes to +// the generated code, and makes deliberate changes to the generated code +// easier to review. +// +// [*] It excludes `Copy` in some cases, because that changes the code +// generated for `Clone`. +// +// [*] It excludes `RustcEncodable` and `RustDecodable`, which are obsolete and +// also require the `rustc_serialize` crate. + +#![crate_type = "lib"] +#![allow(dead_code)] +#![allow(deprecated)] +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; + +// Empty struct. +struct Empty; +#[automatically_derived] +impl ::core::clone::Clone for Empty { + #[inline] + fn clone(&self) -> Empty { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Empty { } +#[automatically_derived] +impl ::core::fmt::Debug for Empty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, "Empty") + } +} +#[automatically_derived] +impl ::core::default::Default for Empty { + #[inline] + fn default() -> Empty { Empty {} } +} +#[automatically_derived] +impl ::core::hash::Hash for Empty { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Empty { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Empty { + #[inline] + fn eq(&self, other: &Empty) -> bool { true } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Empty { } +#[automatically_derived] +impl ::core::cmp::Eq for Empty { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Empty { + #[inline] + fn partial_cmp(&self, other: &Empty) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Empty { + #[inline] + fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering { + ::core::cmp::Ordering::Equal + } +} + +// A basic struct. +struct Point { + x: u32, + y: u32, +} +#[automatically_derived] +impl ::core::clone::Clone for Point { + #[inline] + fn clone(&self) -> Point { + let _: ::core::clone::AssertParamIsClone<u32>; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Point { } +#[automatically_derived] +impl ::core::fmt::Debug for Point { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", + &&self.x, "y", &&self.y) + } +} +#[automatically_derived] +impl ::core::default::Default for Point { + #[inline] + fn default() -> Point { + Point { + x: ::core::default::Default::default(), + y: ::core::default::Default::default(), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Point { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.x, state); + ::core::hash::Hash::hash(&self.y, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Point { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Point { + #[inline] + fn eq(&self, other: &Point) -> bool { + self.x == other.x && self.y == other.y + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Point { } +#[automatically_derived] +impl ::core::cmp::Eq for Point { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Point { + #[inline] + fn partial_cmp(&self, other: &Point) + -> ::core::option::Option<::core::cmp::Ordering> { + match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Point { + #[inline] + fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { + match ::core::cmp::Ord::cmp(&self.x, &other.x) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(&self.y, &other.y), + cmp => cmp, + } + } +} + +// A large struct. +struct Big { + b1: u32, + b2: u32, + b3: u32, + b4: u32, + b5: u32, + b6: u32, + b7: u32, + b8: u32, +} +#[automatically_derived] +impl ::core::clone::Clone for Big { + #[inline] + fn clone(&self) -> Big { + Big { + b1: ::core::clone::Clone::clone(&self.b1), + b2: ::core::clone::Clone::clone(&self.b2), + b3: ::core::clone::Clone::clone(&self.b3), + b4: ::core::clone::Clone::clone(&self.b4), + b5: ::core::clone::Clone::clone(&self.b5), + b6: ::core::clone::Clone::clone(&self.b6), + b7: ::core::clone::Clone::clone(&self.b7), + b8: ::core::clone::Clone::clone(&self.b8), + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Big { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + let names: &'static _ = + &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; + let values: &[&dyn ::core::fmt::Debug] = + &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5, + &&self.b6, &&self.b7, &&self.b8]; + ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", names, + values) + } +} +#[automatically_derived] +impl ::core::default::Default for Big { + #[inline] + fn default() -> Big { + Big { + b1: ::core::default::Default::default(), + b2: ::core::default::Default::default(), + b3: ::core::default::Default::default(), + b4: ::core::default::Default::default(), + b5: ::core::default::Default::default(), + b6: ::core::default::Default::default(), + b7: ::core::default::Default::default(), + b8: ::core::default::Default::default(), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Big { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.b1, state); + ::core::hash::Hash::hash(&self.b2, state); + ::core::hash::Hash::hash(&self.b3, state); + ::core::hash::Hash::hash(&self.b4, state); + ::core::hash::Hash::hash(&self.b5, state); + ::core::hash::Hash::hash(&self.b6, state); + ::core::hash::Hash::hash(&self.b7, state); + ::core::hash::Hash::hash(&self.b8, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Big { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Big { + #[inline] + fn eq(&self, other: &Big) -> bool { + self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3 && + self.b4 == other.b4 && self.b5 == other.b5 && + self.b6 == other.b6 && self.b7 == other.b7 && + self.b8 == other.b8 + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Big { } +#[automatically_derived] +impl ::core::cmp::Eq for Big { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Big { + #[inline] + fn partial_cmp(&self, other: &Big) + -> ::core::option::Option<::core::cmp::Ordering> { + match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.b2, + &other.b2) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b3, + &other.b3) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b4, + &other.b4) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b5, + &other.b5) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b6, + &other.b6) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b7, + &other.b7) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + ::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8), + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Big { + #[inline] + fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { + match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b3, &other.b3) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b4, &other.b4) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b5, &other.b5) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b6, &other.b6) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b7, &other.b7) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(&self.b8, &other.b8), + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + } + } +} + +// A struct with an unsized field. Some derives are not usable in this case. +struct Unsized([u32]); +#[automatically_derived] +impl ::core::fmt::Debug for Unsized { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", + &&self.0) + } +} +#[automatically_derived] +impl ::core::hash::Hash for Unsized { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.0, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Unsized { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Unsized { + #[inline] + fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Unsized { } +#[automatically_derived] +impl ::core::cmp::Eq for Unsized { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<[u32]>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Unsized { + #[inline] + fn partial_cmp(&self, other: &Unsized) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Unsized { + #[inline] + fn cmp(&self, other: &Unsized) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +// A packed tuple struct that impls `Copy`. +#[repr(packed)] +struct PackedCopy(u32); +#[automatically_derived] +impl ::core::clone::Clone for PackedCopy { + #[inline] + fn clone(&self) -> PackedCopy { + let _: ::core::clone::AssertParamIsClone<u32>; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for PackedCopy { } +#[automatically_derived] +impl ::core::fmt::Debug for PackedCopy { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedCopy", + &&{ self.0 }) + } +} +#[automatically_derived] +impl ::core::default::Default for PackedCopy { + #[inline] + fn default() -> PackedCopy { + PackedCopy(::core::default::Default::default()) + } +} +#[automatically_derived] +impl ::core::hash::Hash for PackedCopy { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&{ self.0 }, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedCopy { } +#[automatically_derived] +impl ::core::cmp::PartialEq for PackedCopy { + #[inline] + fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedCopy { } +#[automatically_derived] +impl ::core::cmp::Eq for PackedCopy { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for PackedCopy { + #[inline] + fn partial_cmp(&self, other: &PackedCopy) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for PackedCopy { + #[inline] + fn cmp(&self, other: &PackedCopy) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 }) + } +} + +// A packed tuple struct that does not impl `Copy`. Note that the alignment of +// the field must be 1 for this code to be valid. Otherwise it triggers an +// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not +// derive Copy (error E0133)" at MIR building time. This is a weird case and +// it's possible that this struct is not supposed to work, but for now it does. +#[repr(packed)] +struct PackedNonCopy(u8); +#[automatically_derived] +impl ::core::clone::Clone for PackedNonCopy { + #[inline] + fn clone(&self) -> PackedNonCopy { + PackedNonCopy(::core::clone::Clone::clone(&self.0)) + } +} +#[automatically_derived] +impl ::core::fmt::Debug for PackedNonCopy { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedNonCopy", + &&self.0) + } +} +#[automatically_derived] +impl ::core::default::Default for PackedNonCopy { + #[inline] + fn default() -> PackedNonCopy { + PackedNonCopy(::core::default::Default::default()) + } +} +#[automatically_derived] +impl ::core::hash::Hash for PackedNonCopy { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.0, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedNonCopy { } +#[automatically_derived] +impl ::core::cmp::PartialEq for PackedNonCopy { + #[inline] + fn eq(&self, other: &PackedNonCopy) -> bool { self.0 == other.0 } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedNonCopy { } +#[automatically_derived] +impl ::core::cmp::Eq for PackedNonCopy { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u8>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for PackedNonCopy { + #[inline] + fn partial_cmp(&self, other: &PackedNonCopy) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for PackedNonCopy { + #[inline] + fn cmp(&self, other: &PackedNonCopy) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +// An empty enum. +enum Enum0 {} +#[automatically_derived] +impl ::core::clone::Clone for Enum0 { + #[inline] + fn clone(&self) -> Enum0 { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Enum0 { } +#[automatically_derived] +impl ::core::fmt::Debug for Enum0 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Enum0 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum0 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Enum0 { + #[inline] + fn eq(&self, other: &Enum0) -> bool { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum0 { } +#[automatically_derived] +impl ::core::cmp::Eq for Enum0 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Enum0 { + #[inline] + fn partial_cmp(&self, other: &Enum0) + -> ::core::option::Option<::core::cmp::Ordering> { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Enum0 { + #[inline] + fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering { + unsafe { ::core::intrinsics::unreachable() } + } +} + +// A single-variant enum. +enum Enum1 { + Single { + x: u32, + }, +} +#[automatically_derived] +impl ::core::clone::Clone for Enum1 { + #[inline] + fn clone(&self) -> Enum1 { + match self { + Enum1::Single { x: __self_0 } => + Enum1::Single { x: ::core::clone::Clone::clone(__self_0) }, + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Enum1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Enum1::Single { x: __self_0 } => + ::core::fmt::Formatter::debug_struct_field1_finish(f, + "Single", "x", &__self_0), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Enum1 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + match self { + Enum1::Single { x: __self_0 } => + ::core::hash::Hash::hash(__self_0, state), + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum1 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Enum1 { + #[inline] + fn eq(&self, other: &Enum1) -> bool { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + *__self_0 == *__arg1_0, + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum1 { } +#[automatically_derived] +impl ::core::cmp::Eq for Enum1 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Enum1 { + #[inline] + fn partial_cmp(&self, other: &Enum1) + -> ::core::option::Option<::core::cmp::Ordering> { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Enum1 { + #[inline] + fn cmp(&self, other: &Enum1) -> ::core::cmp::Ordering { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + } + } +} + +// A C-like, fieldless enum with a single variant. +enum Fieldless1 { + + #[default] + A, +} +#[automatically_derived] +impl ::core::clone::Clone for Fieldless1 { + #[inline] + fn clone(&self) -> Fieldless1 { Fieldless1::A } +} +#[automatically_derived] +impl ::core::fmt::Debug for Fieldless1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, "A") + } +} +#[automatically_derived] +impl ::core::default::Default for Fieldless1 { + #[inline] + fn default() -> Fieldless1 { Self::A } +} +#[automatically_derived] +impl ::core::hash::Hash for Fieldless1 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless1 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fieldless1 { + #[inline] + fn eq(&self, other: &Fieldless1) -> bool { true } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless1 { } +#[automatically_derived] +impl ::core::cmp::Eq for Fieldless1 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fieldless1 { + #[inline] + fn partial_cmp(&self, other: &Fieldless1) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fieldless1 { + #[inline] + fn cmp(&self, other: &Fieldless1) -> ::core::cmp::Ordering { + ::core::cmp::Ordering::Equal + } +} + +// A C-like, fieldless enum. +enum Fieldless { + + #[default] + A, + B, + C, +} +#[automatically_derived] +impl ::core::clone::Clone for Fieldless { + #[inline] + fn clone(&self) -> Fieldless { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Fieldless { } +#[automatically_derived] +impl ::core::fmt::Debug for Fieldless { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, + match self { + Fieldless::A => "A", + Fieldless::B => "B", + Fieldless::C => "C", + }) + } +} +#[automatically_derived] +impl ::core::default::Default for Fieldless { + #[inline] + fn default() -> Fieldless { Self::A } +} +#[automatically_derived] +impl ::core::hash::Hash for Fieldless { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fieldless { + #[inline] + fn eq(&self, other: &Fieldless) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless { } +#[automatically_derived] +impl ::core::cmp::Eq for Fieldless { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fieldless { + #[inline] + fn partial_cmp(&self, other: &Fieldless) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fieldless { + #[inline] + fn cmp(&self, other: &Fieldless) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) + } +} + +// An enum with multiple fieldless and fielded variants. +enum Mixed { + + #[default] + P, + Q, + R(u32), + S { + d1: Option<u32>, + d2: Option<i32>, + }, +} +#[automatically_derived] +impl ::core::clone::Clone for Mixed { + #[inline] + fn clone(&self) -> Mixed { + let _: ::core::clone::AssertParamIsClone<u32>; + let _: ::core::clone::AssertParamIsClone<Option<u32>>; + let _: ::core::clone::AssertParamIsClone<Option<i32>>; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Mixed { } +#[automatically_derived] +impl ::core::fmt::Debug for Mixed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), + Mixed::Q => ::core::fmt::Formatter::write_str(f, "Q"), + Mixed::R(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", + &__self_0), + Mixed::S { d1: __self_0, d2: __self_1 } => + ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", + "d1", &__self_0, "d2", &__self_1), + } + } +} +#[automatically_derived] +impl ::core::default::Default for Mixed { + #[inline] + fn default() -> Mixed { Self::P } +} +#[automatically_derived] +impl ::core::hash::Hash for Mixed { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state); + match self { + Mixed::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Mixed::S { d1: __self_0, d2: __self_1 } => { + ::core::hash::Hash::hash(__self_0, state); + ::core::hash::Hash::hash(__self_1, state) + } + _ => {} + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Mixed { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Mixed { + #[inline] + fn eq(&self, other: &Mixed) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag && + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + *__self_0 == *__arg1_0, + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + *__self_0 == *__arg1_0 && *__self_1 == *__arg1_1, + _ => true, + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Mixed { } +#[automatically_derived] +impl ::core::cmp::Eq for Mixed { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + let _: ::core::cmp::AssertParamIsEq<Option<u32>>; + let _: ::core::cmp::AssertParamIsEq<Option<i32>>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Mixed { + #[inline] + fn partial_cmp(&self, other: &Mixed) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::PartialOrd::partial_cmp(__self_0, + __arg1_0) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1), + cmp => cmp, + }, + _ => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Mixed { + #[inline] + fn cmp(&self, other: &Mixed) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) { + ::core::cmp::Ordering::Equal => + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(__self_1, __arg1_1), + cmp => cmp, + }, + _ => ::core::cmp::Ordering::Equal, + }, + cmp => cmp, + } + } +} + +// An enum with no fieldless variants. Note that `Default` cannot be derived +// for this enum. +enum Fielded { X(u32), Y(bool), Z(Option<i32>), } +#[automatically_derived] +impl ::core::clone::Clone for Fielded { + #[inline] + fn clone(&self) -> Fielded { + match self { + Fielded::X(__self_0) => + Fielded::X(::core::clone::Clone::clone(__self_0)), + Fielded::Y(__self_0) => + Fielded::Y(::core::clone::Clone::clone(__self_0)), + Fielded::Z(__self_0) => + Fielded::Z(::core::clone::Clone::clone(__self_0)), + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Fielded { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Fielded::X(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", + &__self_0), + Fielded::Y(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", + &__self_0), + Fielded::Z(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", + &__self_0), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Fielded { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state); + match self { + Fielded::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Fielded::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Fielded::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fielded { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fielded { + #[inline] + fn eq(&self, other: &Fielded) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag && + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + *__self_0 == *__arg1_0, + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + *__self_0 == *__arg1_0, + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + *__self_0 == *__arg1_0, + _ => unsafe { ::core::intrinsics::unreachable() } + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fielded { } +#[automatically_derived] +impl ::core::cmp::Eq for Fielded { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<u32>; + let _: ::core::cmp::AssertParamIsEq<bool>; + let _: ::core::cmp::AssertParamIsEq<Option<i32>>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fielded { + #[inline] + fn partial_cmp(&self, other: &Fielded) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + _ => unsafe { ::core::intrinsics::unreachable() } + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fielded { + #[inline] + fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) { + ::core::cmp::Ordering::Equal => + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + _ => unsafe { ::core::intrinsics::unreachable() } + }, + cmp => cmp, + } + } +} + +// A union. Most builtin traits are not derivable for unions. +pub union Union { + pub b: bool, + pub u: u32, + pub i: i32, +} +#[automatically_derived] +impl ::core::clone::Clone for Union { + #[inline] + fn clone(&self) -> Union { + let _: ::core::clone::AssertParamIsCopy<Self>; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Union { } diff --git a/tests/ui/deriving/deriving-associated-types.rs b/tests/ui/deriving/deriving-associated-types.rs new file mode 100644 index 000000000..4b1cbe80c --- /dev/null +++ b/tests/ui/deriving/deriving-associated-types.rs @@ -0,0 +1,199 @@ +// run-pass +pub trait DeclaredTrait { + type Type; +} + +impl DeclaredTrait for i32 { + type Type = i32; +} + +pub trait WhereTrait { + type Type; +} + +impl WhereTrait for i32 { + type Type = i32; +} + +// Make sure we don't add a bound that just shares a name with an associated +// type. +pub mod module { + pub type Type = i32; +} + +#[derive(PartialEq, Debug)] +struct PrivateStruct<T>(T); + +#[derive(PartialEq, Debug)] +struct TupleStruct<A, B: DeclaredTrait, C>( + module::Type, + Option<module::Type>, + A, + PrivateStruct<A>, + B, + B::Type, + Option<B::Type>, + <B as DeclaredTrait>::Type, + Option<<B as DeclaredTrait>::Type>, + C, + C::Type, + Option<C::Type>, + <C as WhereTrait>::Type, + Option<<C as WhereTrait>::Type>, + <i32 as DeclaredTrait>::Type, +) where C: WhereTrait; + +#[derive(PartialEq, Debug)] +pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait { + m1: module::Type, + m2: Option<module::Type>, + a1: A, + a2: PrivateStruct<A>, + b: B, + b1: B::Type, + b2: Option<B::Type>, + b3: <B as DeclaredTrait>::Type, + b4: Option<<B as DeclaredTrait>::Type>, + c: C, + c1: C::Type, + c2: Option<C::Type>, + c3: <C as WhereTrait>::Type, + c4: Option<<C as WhereTrait>::Type>, + d: <i32 as DeclaredTrait>::Type, +} + +#[derive(PartialEq, Debug)] +enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait { + Unit, + Seq( + module::Type, + Option<module::Type>, + A, + PrivateStruct<A>, + B, + B::Type, + Option<B::Type>, + <B as DeclaredTrait>::Type, + Option<<B as DeclaredTrait>::Type>, + C, + C::Type, + Option<C::Type>, + <C as WhereTrait>::Type, + Option<<C as WhereTrait>::Type>, + <i32 as DeclaredTrait>::Type, + ), + Map { + m1: module::Type, + m2: Option<module::Type>, + a1: A, + a2: PrivateStruct<A>, + b: B, + b1: B::Type, + b2: Option<B::Type>, + b3: <B as DeclaredTrait>::Type, + b4: Option<<B as DeclaredTrait>::Type>, + c: C, + c1: C::Type, + c2: Option<C::Type>, + c3: <C as WhereTrait>::Type, + c4: Option<<C as WhereTrait>::Type>, + d: <i32 as DeclaredTrait>::Type, + }, +} + +fn main() { + let e: TupleStruct< + i32, + i32, + i32, + > = TupleStruct( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Struct< + i32, + i32, + i32, + > = Struct { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); + + let e = Enum::Unit::<i32, i32, i32>; + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Seq( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Map { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); +} diff --git a/tests/ui/deriving/deriving-bounds.rs b/tests/ui/deriving/deriving-bounds.rs new file mode 100644 index 000000000..f0b921d0e --- /dev/null +++ b/tests/ui/deriving/deriving-bounds.rs @@ -0,0 +1,5 @@ +// run-pass +#[derive(Copy, Clone)] +struct Test; + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-array.rs b/tests/ui/deriving/deriving-clone-array.rs new file mode 100644 index 000000000..4569749df --- /dev/null +++ b/tests/ui/deriving/deriving-clone-array.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +// test for issue #30244 + +#[derive(Copy, Clone)] +struct Array { + arr: [[u8; 256]; 4] +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-enum.rs b/tests/ui/deriving/deriving-clone-enum.rs new file mode 100644 index 000000000..09e749740 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-enum.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +enum E { + A, + B(()), + C +} + +pub fn main() { + let _ = E::A.clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-enum.rs b/tests/ui/deriving/deriving-clone-generic-enum.rs new file mode 100644 index 000000000..a344d7fc4 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-enum.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +enum E<T,U> { + A(T), + B(T,U), + C +} + +pub fn main() { + let _ = E::A::<isize, isize>(1).clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-struct.rs b/tests/ui/deriving/deriving-clone-generic-struct.rs new file mode 100644 index 000000000..4374d1594 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-struct.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S<T> { + foo: (), + bar: (), + baz: T, +} + +pub fn main() { + let _ = S { foo: (), bar: (), baz: 1 }.clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs b/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs new file mode 100644 index 000000000..3480ccc10 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +#[allow(unused_tuple_struct_fields)] +struct S<T>(T, ()); + +pub fn main() { + let _ = S(1, ()).clone(); +} diff --git a/tests/ui/deriving/deriving-clone-struct.rs b/tests/ui/deriving/deriving-clone-struct.rs new file mode 100644 index 000000000..b93cbe5f8 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-struct.rs @@ -0,0 +1,28 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S { + _int: isize, + _i8: i8, + _i16: i16, + _i32: i32, + _i64: i64, + + _uint: usize, + _u8: u8, + _u16: u16, + _u32: u32, + _u64: u64, + + _f32: f32, + _f64: f64, + + _bool: bool, + _char: char, + _nil: () +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-tuple-struct.rs b/tests/ui/deriving/deriving-clone-tuple-struct.rs new file mode 100644 index 000000000..7ad3f0347 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-tuple-struct.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S((), ()); + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-cmp-generic-enum.rs b/tests/ui/deriving/deriving-cmp-generic-enum.rs new file mode 100644 index 000000000..88da4bd06 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-enum.rs @@ -0,0 +1,44 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum E<T> { + E0, + E1(T), + E2(T,T) +} + +pub fn main() { + let e0 = E::E0; + let e11 = E::E1(1); + let e12 = E::E1(2); + let e21 = E::E2(1, 1); + let e22 = E::E2(1, 2); + + // in order for both PartialOrd and Ord + let es = [e0, e11, e12, e21, e22]; + + for (i, e1) in es.iter().enumerate() { + for (j, e2) in es.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*e1 == *e2, eq); + assert_eq!(*e1 != *e2, !eq); + + // PartialOrd + assert_eq!(*e1 < *e2, lt); + assert_eq!(*e1 > *e2, gt); + + assert_eq!(*e1 <= *e2, le); + assert_eq!(*e1 >= *e2, ge); + + // Ord + assert_eq!(e1.cmp(e2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs b/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs new file mode 100644 index 000000000..eeaf2ff7e --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs @@ -0,0 +1,48 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum ES<T> { + ES1 { x: T }, + ES2 { x: T, y: T } +} + + +pub fn main() { + let (es11, es12, es21, es22) = (ES::ES1 { + x: 1 + }, ES::ES1 { + x: 2 + }, ES::ES2 { + x: 1, + y: 1 + }, ES::ES2 { + x: 1, + y: 2 + }); + + // in order for both PartialOrd and Ord + let ess = [es11, es12, es21, es22]; + + for (i, es1) in ess.iter().enumerate() { + for (j, es2) in ess.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let (lt, le) = (i < j, i <= j); + let (gt, ge) = (i > j, i >= j); + + // PartialEq + assert_eq!(*es1 == *es2, eq); + assert_eq!(*es1 != *es2, !eq); + + // PartialOrd + assert_eq!(*es1 < *es2, lt); + assert_eq!(*es1 > *es2, gt); + + assert_eq!(*es1 <= *es2, le); + assert_eq!(*es1 >= *es2, ge); + + // Ord + assert_eq!(es1.cmp(es2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-struct.rs b/tests/ui/deriving/deriving-cmp-generic-struct.rs new file mode 100644 index 000000000..538caf439 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-struct.rs @@ -0,0 +1,40 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct S<T> { + x: T, + y: T +} + +pub fn main() { + let s1 = S {x: 1, y: 1}; + let s2 = S {x: 1, y: 2}; + + // in order for both PartialOrd and Ord + let ss = [s1, s2]; + + for (i, s1) in ss.iter().enumerate() { + for (j, s2) in ss.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*s1 == *s2, eq); + assert_eq!(*s1 != *s2, !eq); + + // PartialOrd + assert_eq!(*s1 < *s2, lt); + assert_eq!(*s1 > *s2, gt); + + assert_eq!(*s1 <= *s2, le); + assert_eq!(*s1 >= *s2, ge); + + // Ord + assert_eq!(s1.cmp(s2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs b/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs new file mode 100644 index 000000000..79f58d456 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs @@ -0,0 +1,38 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct TS<T>(T,T); + + +pub fn main() { + let ts1 = TS(1, 1); + let ts2 = TS(1, 2); + + // in order for both PartialOrd and Ord + let tss = [ts1, ts2]; + + for (i, ts1) in tss.iter().enumerate() { + for (j, ts2) in tss.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*ts1 == *ts2, eq); + assert_eq!(*ts1 != *ts2, !eq); + + // PartialOrd + assert_eq!(*ts1 < *ts2, lt); + assert_eq!(*ts1 > *ts2, gt); + + assert_eq!(*ts1 <= *ts2, le); + assert_eq!(*ts1 >= *ts2, ge); + + // Ord + assert_eq!(ts1.cmp(ts2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-shortcircuit.rs b/tests/ui/deriving/deriving-cmp-shortcircuit.rs new file mode 100644 index 000000000..140373e95 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-shortcircuit.rs @@ -0,0 +1,37 @@ +// run-pass +// check that the derived impls for the comparison traits shortcircuit +// where possible, by having a type that panics when compared as the +// second element, so this passes iff the instances shortcircuit. + + +use std::cmp::Ordering; + +pub struct FailCmp; +impl PartialEq for FailCmp { + fn eq(&self, _: &FailCmp) -> bool { panic!("eq") } +} + +impl PartialOrd for FailCmp { + fn partial_cmp(&self, _: &FailCmp) -> Option<Ordering> { panic!("partial_cmp") } +} + +impl Eq for FailCmp {} + +impl Ord for FailCmp { + fn cmp(&self, _: &FailCmp) -> Ordering { panic!("cmp") } +} + +#[derive(PartialEq,PartialOrd,Eq,Ord)] +struct ShortCircuit { + x: isize, + y: FailCmp +} + +pub fn main() { + let a = ShortCircuit { x: 1, y: FailCmp }; + let b = ShortCircuit { x: 2, y: FailCmp }; + + assert!(a != b); + assert!(a < b); + assert_eq!(a.cmp(&b), ::std::cmp::Ordering::Less); +} diff --git a/tests/ui/deriving/deriving-copyclone.rs b/tests/ui/deriving/deriving-copyclone.rs new file mode 100644 index 000000000..f8403b1fe --- /dev/null +++ b/tests/ui/deriving/deriving-copyclone.rs @@ -0,0 +1,38 @@ +// run-pass +//! Test that #[derive(Copy, Clone)] produces a shallow copy +//! even when a member violates RFC 1521 + +use std::sync::atomic::{AtomicBool, Ordering}; + +/// A struct that pretends to be Copy, but actually does something +/// in its Clone impl +#[derive(Copy)] +struct Liar; + +/// Static cooperating with the rogue Clone impl +static CLONED: AtomicBool = AtomicBool::new(false); + +impl Clone for Liar { + fn clone(&self) -> Self { + // this makes Clone vs Copy observable + CLONED.store(true, Ordering::SeqCst); + + *self + } +} + +/// This struct is actually Copy... at least, it thinks it is! +#[derive(Copy, Clone)] +struct Innocent(#[allow(unused_tuple_struct_fields)] Liar); + +impl Innocent { + fn new() -> Self { + Innocent(Liar) + } +} + +fn main() { + let _ = Innocent::new().clone(); + // if Innocent was byte-for-byte copied, CLONED will still be false + assert!(!CLONED.load(Ordering::SeqCst)); +} diff --git a/tests/ui/deriving/deriving-default-box.rs b/tests/ui/deriving/deriving-default-box.rs new file mode 100644 index 000000000..b71e11496 --- /dev/null +++ b/tests/ui/deriving/deriving-default-box.rs @@ -0,0 +1,13 @@ +// run-pass +use std::default::Default; + +#[derive(Default)] +struct A { + foo: Box<[bool]>, +} + +pub fn main() { + let a: A = Default::default(); + let b: Box<[_]> = Box::<[bool; 0]>::new([]); + assert_eq!(a.foo, b); +} diff --git a/tests/ui/deriving/deriving-default-enum.rs b/tests/ui/deriving/deriving-default-enum.rs new file mode 100644 index 000000000..1c7a501ed --- /dev/null +++ b/tests/ui/deriving/deriving-default-enum.rs @@ -0,0 +1,27 @@ +// run-pass + +// nb: does not impl Default +#[derive(Debug, PartialEq)] +struct NotDefault; + +#[derive(Debug, Default, PartialEq)] +enum Foo { + #[default] + Alpha, + #[allow(dead_code)] + Beta(NotDefault), +} + +// #[default] on a generic enum does not add `Default` bounds to the type params. +#[derive(Default)] +enum MyOption<T> { + #[default] + None, + #[allow(dead_code)] + Some(T), +} + +fn main() { + assert_eq!(Foo::default(), Foo::Alpha); + assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None)); +} diff --git a/tests/ui/deriving/deriving-enum-single-variant.rs b/tests/ui/deriving/deriving-enum-single-variant.rs new file mode 100644 index 000000000..1c5979c07 --- /dev/null +++ b/tests/ui/deriving/deriving-enum-single-variant.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +pub type task_id = isize; + +#[derive(PartialEq)] +pub enum Task { + TaskHandle(task_id) +} + +pub fn main() { } diff --git a/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs b/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs new file mode 100644 index 000000000..5b4b09836 --- /dev/null +++ b/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs @@ -0,0 +1,15 @@ +// run-pass +#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)] +struct Foo(Box<[u8]>); + +pub fn main() { + let a = Foo(Box::new([0, 1, 2])); + let b = Foo(Box::new([0, 1, 2])); + assert_eq!(a, b); + println!("{}", a != b); + println!("{}", a < b); + println!("{}", a <= b); + println!("{}", a == b); + println!("{}", a > b); + println!("{}", a >= b); +} diff --git a/tests/ui/deriving/deriving-hash.rs b/tests/ui/deriving/deriving-hash.rs new file mode 100644 index 000000000..16738ec4a --- /dev/null +++ b/tests/ui/deriving/deriving-hash.rs @@ -0,0 +1,96 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(deprecated)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(overflowing_literals)] + +use std::hash::{Hash, SipHasher, Hasher}; +use std::mem::size_of; + +#[derive(Hash)] +struct Person { + id: usize, + name: String, + phone: usize, +} + +// test for hygiene name collisions +#[derive(Hash)] struct __H__H; +#[derive(Hash)] enum Collision<__H> { __H { __H__H: __H } } + +#[derive(Hash)] +enum E { A=1, B } + +fn hash<T: Hash>(t: &T) -> u64 { + let mut s = SipHasher::new(); + t.hash(&mut s); + s.finish() +} + +struct FakeHasher<'a>(&'a mut Vec<u8>); +impl<'a> Hasher for FakeHasher<'a> { + fn finish(&self) -> u64 { + unimplemented!() + } + + fn write(&mut self, bytes: &[u8]) { + self.0.extend(bytes); + } +} + +fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) { + a.hash(&mut FakeHasher(v)); +} + +struct OnlyOneByteHasher; +impl Hasher for OnlyOneByteHasher { + fn finish(&self) -> u64 { + unreachable!() + } + + fn write(&mut self, bytes: &[u8]) { + assert_eq!(bytes.len(), 1); + } +} + +fn main() { + let person1 = Person { + id: 5, + name: "Janet".to_string(), + phone: 555_666_7777 + }; + let person2 = Person { + id: 5, + name: "Bob".to_string(), + phone: 555_666_7777 + }; + assert_eq!(hash(&person1), hash(&person1)); + assert!(hash(&person1) != hash(&person2)); + + // test #21714 + let mut va = vec![]; + let mut vb = vec![]; + fake_hash(&mut va, E::A); + fake_hash(&mut vb, E::B); + assert!(va != vb); + + // issue #39137: single variant enum hash should not hash discriminant + #[derive(Hash)] + enum SingleVariantEnum { + A(u8), + } + let mut v = vec![]; + fake_hash(&mut v, SingleVariantEnum::A(17)); + assert_eq!(vec![17], v); + + // issue #39137 + #[repr(u8)] + #[derive(Hash)] + enum E { + A, + B, + } + E::A.hash(&mut OnlyOneByteHasher); +} diff --git a/tests/ui/deriving/deriving-in-fn.rs b/tests/ui/deriving/deriving-in-fn.rs new file mode 100644 index 000000000..07f91d059 --- /dev/null +++ b/tests/ui/deriving/deriving-in-fn.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(dead_code)] + +pub fn main() { + #[derive(Debug)] + struct Foo { + foo: isize, + } + + let f = Foo { foo: 10 }; + format!("{:?}", f); +} diff --git a/tests/ui/deriving/deriving-in-macro.rs b/tests/ui/deriving/deriving-in-macro.rs new file mode 100644 index 000000000..46e8e3783 --- /dev/null +++ b/tests/ui/deriving/deriving-in-macro.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +macro_rules! define_vec { + () => ( + mod foo { + #[derive(PartialEq)] + pub struct bar; + } + ) +} + +define_vec![]; + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-meta-multiple.rs b/tests/ui/deriving/deriving-meta-multiple.rs new file mode 100644 index 000000000..ad255be8d --- /dev/null +++ b/tests/ui/deriving/deriving-meta-multiple.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 +#![allow(deprecated)] + +use std::hash::{Hash, SipHasher}; + +// testing multiple separate deriving attributes +#[derive(PartialEq)] +#[derive(Clone)] +#[derive(Hash)] +struct Foo { + bar: usize, + baz: isize +} + +fn hash<T: Hash>(_t: &T) {} + +pub fn main() { + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for PartialEq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + hash(&a); // check for Hash impl w/o testing its correctness +} diff --git a/tests/ui/deriving/deriving-meta.rs b/tests/ui/deriving/deriving-meta.rs new file mode 100644 index 000000000..f2ff4f535 --- /dev/null +++ b/tests/ui/deriving/deriving-meta.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 +#![allow(deprecated)] + +use std::hash::{Hash, SipHasher}; + +#[derive(PartialEq, Clone, Hash)] +struct Foo { + bar: usize, + baz: isize +} + +fn hash<T: Hash>(_t: &T) {} + +pub fn main() { + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for PartialEq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + hash(&a); // check for Hash impl w/o testing its correctness +} diff --git a/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs b/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs new file mode 100644 index 000000000..e01b5a26f --- /dev/null +++ b/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs @@ -0,0 +1,16 @@ +// run-pass +use std::cmp::Ordering::{Less,Equal,Greater}; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct A<'a> { + x: &'a isize +} +pub fn main() { + let (a, b) = (A { x: &1 }, A { x: &2 }); + + assert_eq!(a.cmp(&a), Equal); + assert_eq!(b.cmp(&b), Equal); + + assert_eq!(a.cmp(&b), Less); + assert_eq!(b.cmp(&a), Greater); +} diff --git a/tests/ui/deriving/deriving-show-2.rs b/tests/ui/deriving/deriving-show-2.rs new file mode 100644 index 000000000..13d124ed4 --- /dev/null +++ b/tests/ui/deriving/deriving-show-2.rs @@ -0,0 +1,54 @@ +// run-pass +#![allow(dead_code)] +use std::fmt; + +#[derive(Debug)] +enum A {} +#[derive(Debug)] +enum B { B1, B2, B3 } +#[derive(Debug)] +enum C { C1(isize), C2(B), C3(String) } +#[derive(Debug)] +enum D { D1{ a: isize } } +#[derive(Debug)] +struct E; +#[derive(Debug)] +struct F(isize); +#[derive(Debug)] +struct G(isize, isize); +#[derive(Debug)] +struct H { a: isize } +#[derive(Debug)] +struct I { a: isize, b: isize } +#[derive(Debug)] +struct J(Custom); + +struct Custom; +impl fmt::Debug for Custom { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "yay") + } +} + +trait ToDebug { + fn to_show(&self) -> String; +} + +impl<T: fmt::Debug> ToDebug for T { + fn to_show(&self) -> String { + format!("{:?}", self) + } +} + +pub fn main() { + assert_eq!(B::B1.to_show(), "B1".to_string()); + assert_eq!(B::B2.to_show(), "B2".to_string()); + assert_eq!(C::C1(3).to_show(), "C1(3)".to_string()); + assert_eq!(C::C2(B::B2).to_show(), "C2(B2)".to_string()); + assert_eq!(D::D1{ a: 2 }.to_show(), "D1 { a: 2 }".to_string()); + assert_eq!(E.to_show(), "E".to_string()); + assert_eq!(F(3).to_show(), "F(3)".to_string()); + assert_eq!(G(3, 4).to_show(), "G(3, 4)".to_string()); + assert_eq!(I{ a: 2, b: 4 }.to_show(), "I { a: 2, b: 4 }".to_string()); + assert_eq!(J(Custom).to_show(), "J(yay)".to_string()); +} diff --git a/tests/ui/deriving/deriving-show.rs b/tests/ui/deriving/deriving-show.rs new file mode 100644 index 000000000..eb3a8948f --- /dev/null +++ b/tests/ui/deriving/deriving-show.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +#[derive(Debug)] +struct Unit; + +#[derive(Debug)] +struct Tuple(isize, usize); + +#[derive(Debug)] +struct Struct { x: isize, y: usize } + +#[derive(Debug)] +enum Enum { + Nullary, + Variant(isize, usize), + StructVariant { x: isize, y : usize } +} + +#[derive(Debug)] +struct Pointers(*const dyn Send, *mut dyn Sync); + +macro_rules! t { + ($x:expr, $expected:expr) => { + assert_eq!(format!("{:?}", $x), $expected.to_string()) + } +} + +pub fn main() { + t!(Unit, "Unit"); + t!(Tuple(1, 2), "Tuple(1, 2)"); + t!(Struct { x: 1, y: 2 }, "Struct { x: 1, y: 2 }"); + t!(Enum::Nullary, "Nullary"); + t!(Enum::Variant(1, 2), "Variant(1, 2)"); + t!(Enum::StructVariant { x: 1, y: 2 }, "StructVariant { x: 1, y: 2 }"); +} diff --git a/tests/ui/deriving/deriving-via-extension-c-enum.rs b/tests/ui/deriving/deriving-via-extension-c-enum.rs new file mode 100644 index 000000000..7fa1a69d7 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-c-enum.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum Foo { + Bar, + Baz, + Boo +} + +pub fn main() { + let a = Foo::Bar; + let b = Foo::Bar; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-enum.rs b/tests/ui/deriving/deriving-via-extension-enum.rs new file mode 100644 index 000000000..6b58fd966 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-enum.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum Foo { + Bar(isize, isize), + Baz(f64, f64) +} + +pub fn main() { + let a = Foo::Bar(1, 2); + let b = Foo::Bar(1, 2); + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-hash-enum.rs b/tests/ui/deriving/deriving-via-extension-hash-enum.rs new file mode 100644 index 000000000..2d1ca05f4 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-hash-enum.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#[derive(Hash)] +enum Foo { + Bar(isize, char), + Baz(char, isize) +} + +#[derive(Hash)] +enum A { + B, + C, + D, + E +} + +pub fn main(){} diff --git a/tests/ui/deriving/deriving-via-extension-hash-struct.rs b/tests/ui/deriving/deriving-via-extension-hash-struct.rs new file mode 100644 index 000000000..c4037dc27 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-hash-struct.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Hash)] +struct Foo { + x: isize, + y: isize, + z: isize +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-via-extension-struct-empty.rs b/tests/ui/deriving/deriving-via-extension-struct-empty.rs new file mode 100644 index 000000000..9fb250e84 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-empty.rs @@ -0,0 +1,8 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo; + +pub fn main() { + assert_eq!(Foo, Foo); + assert!(!(Foo != Foo)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs b/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs new file mode 100644 index 000000000..b6e6f136c --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum S { + X { x: isize, y: isize }, + Y +} + +pub fn main() { + let x = S::X { x: 1, y: 2 }; + assert_eq!(x, x); + assert!(!(x != x)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct-tuple.rs b/tests/ui/deriving/deriving-via-extension-struct-tuple.rs new file mode 100644 index 000000000..e84906c96 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-tuple.rs @@ -0,0 +1,17 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo(isize, isize, String); + +pub fn main() { + let a1 = Foo(5, 6, "abc".to_string()); + let a2 = Foo(5, 6, "abc".to_string()); + let b = Foo(5, 7, "def".to_string()); + + assert_eq!(a1, a1); + assert_eq!(a2, a1); + assert!(!(a1 == b)); + + assert!(a1 != b); + assert!(!(a1 != a1)); + assert!(!(a2 != a1)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct.rs b/tests/ui/deriving/deriving-via-extension-struct.rs new file mode 100644 index 000000000..f4d8b16a0 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct.rs @@ -0,0 +1,16 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo { + x: isize, + y: isize, + z: isize, +} + +pub fn main() { + let a = Foo { x: 1, y: 2, z: 3 }; + let b = Foo { x: 1, y: 2, z: 3 }; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-type-params.rs b/tests/ui/deriving/deriving-via-extension-type-params.rs new file mode 100644 index 000000000..a5dec8ee1 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-type-params.rs @@ -0,0 +1,16 @@ +// run-pass +#[derive(PartialEq, Hash, Debug)] +struct Foo<T> { + x: isize, + y: T, + z: isize +} + +pub fn main() { + let a = Foo { x: 1, y: 2.0f64, z: 3 }; + let b = Foo { x: 1, y: 2.0f64, z: 3 }; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-with-helper.rs b/tests/ui/deriving/deriving-with-helper.rs new file mode 100644 index 000000000..1c30b0b6f --- /dev/null +++ b/tests/ui/deriving/deriving-with-helper.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(decl_macro)] +#![feature(lang_items)] +#![feature(no_core)] +#![feature(rustc_attrs)] + +#![no_core] + +#[rustc_builtin_macro] +macro derive() {} + +#[rustc_builtin_macro(Default, attributes(default))] +macro Default() {} + +mod default { + pub trait Default { + fn default() -> Self; + } + + impl Default for u8 { + fn default() -> u8 { + 0 + } + } +} + +#[lang = "sized"] +trait Sized {} + +#[derive(Default)] +enum S { + #[default] // OK + Foo, +} diff --git a/tests/ui/deriving/deriving-with-repr-packed.rs b/tests/ui/deriving/deriving-with-repr-packed.rs new file mode 100644 index 000000000..8ce444be1 --- /dev/null +++ b/tests/ui/deriving/deriving-with-repr-packed.rs @@ -0,0 +1,36 @@ +// run-pass +// check that derive on a packed struct does not call field +// methods with a misaligned field. + +use std::mem; + +#[derive(Copy, Clone)] +struct Aligned(usize); + +#[inline(never)] +fn check_align(ptr: *const Aligned) { + assert_eq!(ptr as usize % mem::align_of::<Aligned>(), + 0); +} + +impl PartialEq for Aligned { + fn eq(&self, other: &Self) -> bool { + check_align(self); + check_align(other); + self.0 == other.0 + } +} + +#[repr(packed)] +#[derive(Copy, Clone, PartialEq)] +struct Packed(Aligned, Aligned); + +#[derive(PartialEq)] +#[repr(C)] +struct Dealigned<T>(u8, T); + +fn main() { + let d1 = Dealigned(0, Packed(Aligned(1), Aligned(2))); + let ck = d1 == d1; + assert!(ck); +} diff --git a/tests/ui/deriving/issue-103157.rs b/tests/ui/deriving/issue-103157.rs new file mode 100644 index 000000000..52b4c7898 --- /dev/null +++ b/tests/ui/deriving/issue-103157.rs @@ -0,0 +1,12 @@ +// check-fail + +#[derive(PartialEq, Eq)] +pub enum Value { + Boolean(Option<bool>), + Float(Option<f64>), //~ ERROR the trait bound `f64: Eq` is not satisfied +} + +fn main() { + let a = Value::Float(Some(f64::NAN)); + assert!(a == a); +} diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr new file mode 100644 index 000000000..b18e1e509 --- /dev/null +++ b/tests/ui/deriving/issue-103157.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `f64: Eq` is not satisfied + --> $DIR/issue-103157.rs:6:11 + | +LL | #[derive(PartialEq, Eq)] + | -- in this derive macro expansion +... +LL | Float(Option<f64>), + | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` + | + = help: the following other types implement trait `Eq`: + i128 + i16 + i32 + i64 + i8 + isize + u128 + u16 + and 4 others + = note: required for `Option<f64>` to implement `Eq` +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/deriving/issue-105101.rs b/tests/ui/deriving/issue-105101.rs new file mode 100644 index 000000000..1a377feb9 --- /dev/null +++ b/tests/ui/deriving/issue-105101.rs @@ -0,0 +1,9 @@ +// compile-flags: --crate-type=lib + +#[derive(Default)] //~ ERROR multiple declared defaults +enum E { + #[default] + A, + #[default] + A, //~ ERROR defined multiple times +} diff --git a/tests/ui/deriving/issue-105101.stderr b/tests/ui/deriving/issue-105101.stderr new file mode 100644 index 000000000..0f6f67043 --- /dev/null +++ b/tests/ui/deriving/issue-105101.stderr @@ -0,0 +1,29 @@ +error: multiple declared defaults + --> $DIR/issue-105101.rs:3:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | A, + | - first default +LL | #[default] +LL | A, + | - additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-105101.rs:8:5 + | +LL | A, + | - previous definition of the type `A` here +LL | #[default] +LL | A, + | ^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this enum + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/deriving/issue-19358.rs b/tests/ui/deriving/issue-19358.rs new file mode 100644 index 000000000..3970a4155 --- /dev/null +++ b/tests/ui/deriving/issue-19358.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(dead_code)] + +trait Trait { fn dummy(&self) { } } + +#[derive(Debug)] +struct Foo<T: Trait> { + foo: T, +} + +#[derive(Debug)] +struct Bar<T> where T: Trait { + bar: T, +} + +impl Trait for isize {} + +fn main() { + let a = Foo { foo: 12 }; + let b = Bar { bar: 12 }; + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/deriving/issue-3935.rs b/tests/ui/deriving/issue-3935.rs new file mode 100644 index 000000000..e98d68e0e --- /dev/null +++ b/tests/ui/deriving/issue-3935.rs @@ -0,0 +1,13 @@ +// run-pass + +#[derive(PartialEq)] +struct Bike { + name: String, +} + +pub fn main() { + let town_bike = Bike { name: "schwinn".to_string() }; + let my_bike = Bike { name: "surly".to_string() }; + + assert!(town_bike != my_bike); +} diff --git a/tests/ui/deriving/issue-58319.rs b/tests/ui/deriving/issue-58319.rs new file mode 100644 index 000000000..8041bd5bb --- /dev/null +++ b/tests/ui/deriving/issue-58319.rs @@ -0,0 +1,622 @@ +// run-pass +fn main() {} +#[derive(Clone)] +pub struct Little; +#[derive(Clone)] +#[allow(unused_tuple_struct_fields)] +pub struct Big( + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, +); diff --git a/tests/ui/deriving/issue-6341.rs b/tests/ui/deriving/issue-6341.rs new file mode 100644 index 000000000..1be1394df --- /dev/null +++ b/tests/ui/deriving/issue-6341.rs @@ -0,0 +1,11 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#[derive(PartialEq)] +struct A { x: usize } + +impl Drop for A { + fn drop(&mut self) {} +} + +pub fn main() {} diff --git a/tests/ui/deriving/issue-89188-gat-hrtb.rs b/tests/ui/deriving/issue-89188-gat-hrtb.rs new file mode 100644 index 000000000..e8118f0c6 --- /dev/null +++ b/tests/ui/deriving/issue-89188-gat-hrtb.rs @@ -0,0 +1,37 @@ +// check-pass + +trait CallWithShim: Sized { + type Shim<'s> + where + Self: 's; +} + +#[derive(Clone)] +struct ShimMethod<T: CallWithShim + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); + +trait CallWithShim2: Sized { + type Shim<T>; +} + +struct S<'s>(&'s ()); + +#[derive(Clone)] +struct ShimMethod2<T: CallWithShim2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<S<'s>>)); + +trait Trait<'s, 't, 'u> {} + +#[derive(Clone)] +struct ShimMethod3<T: CallWithShim2 + 'static>( + pub &'static dyn for<'s> Fn( + &'s mut T::Shim<dyn for<'t> Fn(&'s mut T::Shim<dyn for<'u> Trait<'s, 't, 'u>>)>, + ), +); + +trait Trait2 { + type As; +} + +#[derive(Clone)] +struct ShimMethod4<T: Trait2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::As)); + +pub fn main() {} |