Skip to content

Commit afc78e1

Browse files
authored
Rollup merge of rust-lang#66566 - robamler:issue-66476, r=rkruppe
Document pitfall with `impl PartialEq<B> for A` Fixes rust-lang#66476 by turning the violating example into an explicit counterexample.
2 parents 8cba0a9 + 5028fd8 commit afc78e1

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

src/libcore/cmp.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,23 @@ use self::Ordering::*;
135135
/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
136136
/// we allow `BookFormat`s to be compared with `Book`s.
137137
///
138-
/// You can also combine these implementations to let the `==` operator work with
139-
/// two different types:
140-
///
141-
/// ```
138+
/// A comparison like the one above, which ignores some fields of the struct,
139+
/// can be dangerous. It can easily lead to an unintended violation of the
140+
/// requirements for a partial equivalence relation. For example, if we kept
141+
/// the above implementation of `PartialEq<Book>` for `BookFormat` and added an
142+
/// implementation of `PartialEq<Book>` for `Book` (either via a `#[derive]` or
143+
/// via the manual implementation from the first example) then the result would
144+
/// violate transitivity:
145+
///
146+
/// ```should_panic
142147
/// #[derive(PartialEq)]
143148
/// enum BookFormat {
144149
/// Paperback,
145150
/// Hardback,
146151
/// Ebook,
147152
/// }
148153
///
154+
/// #[derive(PartialEq)]
149155
/// struct Book {
150156
/// isbn: i32,
151157
/// format: BookFormat,
@@ -163,18 +169,16 @@ use self::Ordering::*;
163169
/// }
164170
/// }
165171
///
166-
/// impl PartialEq for Book {
167-
/// fn eq(&self, other: &Book) -> bool {
168-
/// self.isbn == other.isbn
169-
/// }
170-
/// }
172+
/// fn main() {
173+
/// let b1 = Book { isbn: 1, format: BookFormat::Paperback };
174+
/// let b2 = Book { isbn: 2, format: BookFormat::Paperback };
171175
///
172-
/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
173-
/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
176+
/// assert!(b1 == BookFormat::Paperback);
177+
/// assert!(BookFormat::Paperback == b2);
174178
///
175-
/// assert!(b1 == BookFormat::Paperback);
176-
/// assert!(BookFormat::Ebook != b1);
177-
/// assert!(b1 == b2);
179+
/// // The following should hold by transitivity but doesn't.
180+
/// assert!(b1 == b2); // <-- PANICS
181+
/// }
178182
/// ```
179183
///
180184
/// # Examples

0 commit comments

Comments
 (0)