Change:
I tried this code: I expected to see this happen: code fails to compile. Instead, this happened: code compiles, and assertion fails. Changing order of enum variants to make go first fixes the issue: : It's reproducible in in Stable, Beta and Nightly. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I have played around a bit with the example and got to compile an even bigger class of bad programs: You can reproduce this in the . As you can see, the compiler is tricked into thinking that implements . This works with sum and product types, as long as: is the first field (or variant) and are "wrapped" with the same type, i.e , or . I have little experience with internals. Maybe someone more experienced could direct us to where this magic happens?
Expanding the macro yields a looks like it only asserts ness for the first field - whoops! claim
Gonna hand it over to you as discussed on zulip release
claim
On 1.63.0 this failed to compile, as expected (): label regression-from-stable-to-stable
this was recently introduced when was doing derive optimizations.
I'll take a look today, thanks for the report.
Don't worry, we've found the issue already, just wanted to let you know.
See for the fix.
WG-prioritization assigning priority a posteriori () mostly to help tracking the fix progress. label -I-prioritize +P-high

Discussion:
} pub fn is_simple_path(&self) -> Option<Symbol> { <del> if let TyKind::Path(None, Path { segments, .. }) = &self && segments.len() == 1 { Some(segments[0].ident.name) </del> <ins> if let TyKind::Path(None, Path { segments, .. }) = &self && let [segment] = &segments[..] && segment.args.is_none() { Some(segment.ident.name) </ins> } else { None }

P, Q, R(u32), <del> S { d1: u32, d2: u32 }, </del> <ins> S { d1: Option<u32>, d2: Option<i32> }, </ins> } // An enum with no fieldless variants. Note that `Default` cannot be derived

Q, R(u32), S { <del> d1: u32, d2: u32, </del> <ins> d1: Option<u32>, d2: Option<i32>, </ins> }, } #[automatically_derived]

#[inline] fn clone(&self) -> Mixed { let _: ::core::clone::AssertParamIsClone<u32>; <ins> let _: ::core::clone::AssertParamIsClone<Option<u32>>; let _: ::core::clone::AssertParamIsClone<Option<i32>>; </ins> *self } }

#[no_coverage] fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq<u32>; <ins> let _: ::core::cmp::AssertParamIsEq<Option<u32>>; let _: ::core::cmp::AssertParamIsEq<Option<i32>>; </ins> } } #[automatically_derived]

<ins> // 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); } </ins>

<ins> 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 | LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { |                               ^^ required by this bound in `AssertParamIsEq` = 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`. </ins>