diff --git a/guide/pyclass-parameters.md b/guide/pyclass-parameters.md
index 1756e8dfb35..a3a4e1f0c7d 100644
--- a/guide/pyclass-parameters.md
+++ b/guide/pyclass-parameters.md
@@ -15,6 +15,7 @@
| `mapping` | Inform PyO3 that this class is a [`Mapping`][params-mapping], and so leave its implementation of sequence C-API slots empty. |
| `module = "module_name"` | Python code will see the class as being defined in this module. Defaults to `builtins`. |
| `name = "python_name"` | Sets the name that Python sees this class as. Defaults to the name of the Rust struct. |
+| `ord` | Implements `__lt__`, `__gt__`, `__le__`, & `__ge__` using the `PartialOrd` implementation of the underlying Rust datatype. *Requires `eq`* |
| `rename_all = "renaming_rule"` | Applies renaming rules to every getters and setters of a struct, or every variants of an enum. Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". |
| `sequence` | Inform PyO3 that this class is a [`Sequence`][params-sequence], and so leave its C-API mapping length slot empty. |
| `set_all` | Generates setters for all fields of the pyclass. |
diff --git a/guide/src/class.md b/guide/src/class.md
index b72cae34e25..2bcfe75911e 100644
--- a/guide/src/class.md
+++ b/guide/src/class.md
@@ -1160,6 +1160,32 @@ Python::with_gil(|py| {
})
```
+Ordering of enum variants is optionally added using `#[pyo3(ord)]`.
+*Note: Implementation of the `PartialOrd` trait is required when passing the `ord` argument. If not implemented, a compile time error is raised.*
+
+```rust
+# use pyo3::prelude::*;
+#[pyclass(eq, ord)]
+#[derive(PartialEq, PartialOrd)]
+enum MyEnum{
+ A,
+ B,
+ C,
+}
+
+Python::with_gil(|py| {
+ let cls = py.get_type_bound::();
+ let a = Py::new(py, MyEnum::A).unwrap();
+ let b = Py::new(py, MyEnum::B).unwrap();
+ let c = Py::new(py, MyEnum::C).unwrap();
+ pyo3::py_run!(py, cls a b c, r#"
+ assert (a < b) == True
+ assert (c <= b) == False
+ assert (c > a) == True
+ "#)
+})
+```
+
You may not use enums as a base class or let enums inherit from other classes.
```rust,compile_fail
diff --git a/guide/src/class/object.md b/guide/src/class/object.md
index 3b775c2b438..c0d25cd0597 100644
--- a/guide/src/class/object.md
+++ b/guide/src/class/object.md
@@ -249,6 +249,16 @@ To implement `__eq__` using the Rust [`PartialEq`] trait implementation, the `eq
struct Number(i32);
```
+To implement `__lt__`, `__le__`, `__gt__`, & `__ge__` using the Rust `PartialOrd` trait implementation, the `ord` option can be used. *Note: Requires `eq`.*
+
+```rust
+# use pyo3::prelude::*;
+#
+#[pyclass(eq, ord)]
+#[derive(PartialEq, PartialOrd)]
+struct Number(i32);
+```
+
### Truthyness
We'll consider `Number` to be `True` if it is nonzero:
diff --git a/newsfragments/4202.added.md b/newsfragments/4202.added.md
new file mode 100644
index 00000000000..d15b6ce810c
--- /dev/null
+++ b/newsfragments/4202.added.md
@@ -0,0 +1 @@
+Add `#[pyclass(ord)]` to implement ordering based on `PartialOrd`.
\ No newline at end of file
diff --git a/pyo3-macros-backend/src/attributes.rs b/pyo3-macros-backend/src/attributes.rs
index 52479552b34..02af17b618b 100644
--- a/pyo3-macros-backend/src/attributes.rs
+++ b/pyo3-macros-backend/src/attributes.rs
@@ -29,6 +29,7 @@ pub mod kw {
syn::custom_keyword!(mapping);
syn::custom_keyword!(module);
syn::custom_keyword!(name);
+ syn::custom_keyword!(ord);
syn::custom_keyword!(pass_module);
syn::custom_keyword!(rename_all);
syn::custom_keyword!(sequence);
diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs
index 1e7f29d84c1..16d9beb50bd 100644
--- a/pyo3-macros-backend/src/pyclass.rs
+++ b/pyo3-macros-backend/src/pyclass.rs
@@ -70,6 +70,7 @@ pub struct PyClassPyO3Options {
pub mapping: Option,
pub module: Option,
pub name: Option,
+ pub ord: Option,
pub rename_all: Option,
pub sequence: Option,
pub set_all: Option,
@@ -91,6 +92,7 @@ enum PyClassPyO3Option {
Mapping(kw::mapping),
Module(ModuleAttribute),
Name(NameAttribute),
+ Ord(kw::ord),
RenameAll(RenameAllAttribute),
Sequence(kw::sequence),
SetAll(kw::set_all),
@@ -126,6 +128,8 @@ impl Parse for PyClassPyO3Option {
input.parse().map(PyClassPyO3Option::Module)
} else if lookahead.peek(kw::name) {
input.parse().map(PyClassPyO3Option::Name)
+ } else if lookahead.peek(attributes::kw::ord) {
+ input.parse().map(PyClassPyO3Option::Ord)
} else if lookahead.peek(kw::rename_all) {
input.parse().map(PyClassPyO3Option::RenameAll)
} else if lookahead.peek(attributes::kw::sequence) {
@@ -189,6 +193,7 @@ impl PyClassPyO3Options {
PyClassPyO3Option::Mapping(mapping) => set_option!(mapping),
PyClassPyO3Option::Module(module) => set_option!(module),
PyClassPyO3Option::Name(name) => set_option!(name),
+ PyClassPyO3Option::Ord(ord) => set_option!(ord),
PyClassPyO3Option::RenameAll(rename_all) => set_option!(rename_all),
PyClassPyO3Option::Sequence(sequence) => set_option!(sequence),
PyClassPyO3Option::SetAll(set_all) => set_option!(set_all),
@@ -1665,7 +1670,10 @@ fn impl_pytypeinfo(
}
}
-fn pyclass_richcmp_arms(options: &PyClassPyO3Options, ctx: &Ctx) -> TokenStream {
+fn pyclass_richcmp_arms(
+ options: &PyClassPyO3Options,
+ ctx: &Ctx,
+) -> std::result::Result {
let Ctx { pyo3_path } = ctx;
let eq_arms = options
@@ -1684,9 +1692,34 @@ fn pyclass_richcmp_arms(options: &PyClassPyO3Options, ctx: &Ctx) -> TokenStream
})
.unwrap_or_default();
- // TODO: `ord` can be integrated here (#4202)
- #[allow(clippy::let_and_return)]
- eq_arms
+ if let Some(ord) = options.ord {
+ ensure_spanned!(options.eq.is_some(), ord.span() => "The `ord` option requires the `eq` option.");
+ }
+
+ let ord_arms = options
+ .ord
+ .map(|ord| {
+ quote_spanned! { ord.span() =>
+ #pyo3_path::pyclass::CompareOp::Gt => {
+ ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val > other, py))
+ },
+ #pyo3_path::pyclass::CompareOp::Lt => {
+ ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val < other, py))
+ },
+ #pyo3_path::pyclass::CompareOp::Le => {
+ ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val <= other, py))
+ },
+ #pyo3_path::pyclass::CompareOp::Ge => {
+ ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val >= other, py))
+ },
+ }
+ })
+ .unwrap_or_else(|| quote! { _ => ::std::result::Result::Ok(py.NotImplemented()) });
+
+ Ok(quote! {
+ #eq_arms
+ #ord_arms
+ })
}
fn pyclass_richcmp_simple_enum(
@@ -1723,7 +1756,7 @@ fn pyclass_richcmp_simple_enum(
return Ok((None, None));
}
- let arms = pyclass_richcmp_arms(&options, ctx);
+ let arms = pyclass_richcmp_arms(&options, ctx)?;
let eq = options.eq.map(|eq| {
quote_spanned! { eq.span() =>
@@ -1732,7 +1765,6 @@ fn pyclass_richcmp_simple_enum(
let other = &*other.borrow();
return match op {
#arms
- _ => ::std::result::Result::Ok(py.NotImplemented())
}
}
}
@@ -1746,7 +1778,6 @@ fn pyclass_richcmp_simple_enum(
}) {
return match op {
#arms
- _ => ::std::result::Result::Ok(py.NotImplemented())
}
}
}
@@ -1786,7 +1817,7 @@ fn pyclass_richcmp(
bail_spanned!(eq_int.span() => "`eq_int` can only be used on simple enums.")
}
- let arms = pyclass_richcmp_arms(options, ctx);
+ let arms = pyclass_richcmp_arms(options, ctx)?;
if options.eq.is_some() {
let mut richcmp_impl = parse_quote! {
fn __pyo3__generated____richcmp__(
@@ -1799,7 +1830,6 @@ fn pyclass_richcmp(
let other = &*#pyo3_path::types::PyAnyMethods::downcast::(other)?.borrow();
match op {
#arms
- _ => ::std::result::Result::Ok(py.NotImplemented())
}
}
};
diff --git a/tests/test_class_comparisons.rs b/tests/test_class_comparisons.rs
new file mode 100644
index 00000000000..75bd6251aac
--- /dev/null
+++ b/tests/test_class_comparisons.rs
@@ -0,0 +1,287 @@
+#![cfg(feature = "macros")]
+
+use pyo3::prelude::*;
+
+#[path = "../src/tests/common.rs"]
+mod common;
+
+#[pyclass(eq)]
+#[derive(Debug, Clone, PartialEq)]
+pub enum MyEnum {
+ Variant,
+ OtherVariant,
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
+pub enum MyEnumOrd {
+ Variant,
+ OtherVariant,
+}
+
+#[test]
+fn test_enum_eq_enum() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, MyEnum::Variant).unwrap();
+ let var2 = Py::new(py, MyEnum::Variant).unwrap();
+ let other_var = Py::new(py, MyEnum::OtherVariant).unwrap();
+ py_assert!(py, var1 var2, "var1 == var2");
+ py_assert!(py, var1 other_var, "var1 != other_var");
+ py_assert!(py, var1 var2, "(var1 != var2) == False");
+ })
+}
+
+#[test]
+fn test_enum_eq_incomparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, MyEnum::Variant).unwrap();
+ py_assert!(py, var1, "(var1 == 'foo') == False");
+ py_assert!(py, var1, "(var1 != 'foo') == True");
+ })
+}
+
+#[test]
+fn test_enum_ord_comparable_opt_in_only() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, MyEnum::Variant).unwrap();
+ let var2 = Py::new(py, MyEnum::OtherVariant).unwrap();
+ // ordering on simple enums if opt in only, thus raising an error below
+ py_expect_exception!(py, var1 var2, "(var1 > var2) == False", PyTypeError);
+ })
+}
+
+#[test]
+fn test_simple_enum_ord_comparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, MyEnumOrd::Variant).unwrap();
+ let var2 = Py::new(py, MyEnumOrd::OtherVariant).unwrap();
+ let var3 = Py::new(py, MyEnumOrd::OtherVariant).unwrap();
+ py_assert!(py, var1 var2, "(var1 > var2) == False");
+ py_assert!(py, var1 var2, "(var1 < var2) == True");
+ py_assert!(py, var1 var2, "(var1 >= var2) == False");
+ py_assert!(py, var2 var3, "(var3 >= var2) == True");
+ py_assert!(py, var1 var2, "(var1 <= var2) == True");
+ })
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
+pub enum MyComplexEnumOrd {
+ Variant(i32),
+ OtherVariant(String),
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
+pub enum MyComplexEnumOrd2 {
+ Variant { msg: String, idx: u32 },
+ OtherVariant { name: String, idx: u32 },
+}
+
+#[test]
+fn test_complex_enum_ord_comparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, MyComplexEnumOrd::Variant(-2)).unwrap();
+ let var2 = Py::new(py, MyComplexEnumOrd::Variant(5)).unwrap();
+ let var3 = Py::new(py, MyComplexEnumOrd::OtherVariant("a".to_string())).unwrap();
+ let var4 = Py::new(py, MyComplexEnumOrd::OtherVariant("b".to_string())).unwrap();
+ py_assert!(py, var1 var2, "(var1 > var2) == False");
+ py_assert!(py, var1 var2, "(var1 < var2) == True");
+ py_assert!(py, var1 var2, "(var1 >= var2) == False");
+ py_assert!(py, var1 var2, "(var1 <= var2) == True");
+
+ py_assert!(py, var1 var3, "(var1 >= var3) == False");
+ py_assert!(py, var1 var3, "(var1 <= var3) == True");
+
+ py_assert!(py, var3 var4, "(var3 >= var4) == False");
+ py_assert!(py, var3 var4, "(var3 <= var4) == True");
+
+ let var5 = Py::new(
+ py,
+ MyComplexEnumOrd2::Variant {
+ msg: "hello".to_string(),
+ idx: 1,
+ },
+ )
+ .unwrap();
+ let var6 = Py::new(
+ py,
+ MyComplexEnumOrd2::Variant {
+ msg: "hello".to_string(),
+ idx: 1,
+ },
+ )
+ .unwrap();
+ let var7 = Py::new(
+ py,
+ MyComplexEnumOrd2::Variant {
+ msg: "goodbye".to_string(),
+ idx: 7,
+ },
+ )
+ .unwrap();
+ let var8 = Py::new(
+ py,
+ MyComplexEnumOrd2::Variant {
+ msg: "about".to_string(),
+ idx: 0,
+ },
+ )
+ .unwrap();
+ let var9 = Py::new(
+ py,
+ MyComplexEnumOrd2::OtherVariant {
+ name: "albert".to_string(),
+ idx: 1,
+ },
+ )
+ .unwrap();
+
+ py_assert!(py, var5 var6, "(var5 == var6) == True");
+ py_assert!(py, var5 var6, "(var5 <= var6) == True");
+ py_assert!(py, var6 var7, "(var6 <= var7) == False");
+ py_assert!(py, var6 var7, "(var6 >= var7) == True");
+ py_assert!(py, var5 var8, "(var5 > var8) == True");
+ py_assert!(py, var8 var9, "(var9 > var8) == True");
+ })
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
+pub struct Point {
+ x: i32,
+ y: i32,
+ z: i32,
+}
+
+#[test]
+fn test_struct_numeric_ord_comparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(py, Point { x: 10, y: 2, z: 3 }).unwrap();
+ let var2 = Py::new(py, Point { x: 2, y: 2, z: 3 }).unwrap();
+ let var3 = Py::new(py, Point { x: 1, y: 22, z: 4 }).unwrap();
+ let var4 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap();
+ let var5 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap();
+ py_assert!(py, var1 var2, "(var1 > var2) == True");
+ py_assert!(py, var1 var2, "(var1 <= var2) == False");
+ py_assert!(py, var2 var3, "(var3 < var2) == True");
+ py_assert!(py, var3 var4, "(var3 > var4) == True");
+ py_assert!(py, var4 var5, "(var4 == var5) == True");
+ py_assert!(py, var3 var5, "(var3 != var5) == True");
+ })
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
+pub struct Person {
+ surname: String,
+ given_name: String,
+}
+
+#[test]
+fn test_struct_string_ord_comparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(
+ py,
+ Person {
+ surname: "zzz".to_string(),
+ given_name: "bob".to_string(),
+ },
+ )
+ .unwrap();
+ let var2 = Py::new(
+ py,
+ Person {
+ surname: "aaa".to_string(),
+ given_name: "sally".to_string(),
+ },
+ )
+ .unwrap();
+ let var3 = Py::new(
+ py,
+ Person {
+ surname: "eee".to_string(),
+ given_name: "qqq".to_string(),
+ },
+ )
+ .unwrap();
+ let var4 = Py::new(
+ py,
+ Person {
+ surname: "ddd".to_string(),
+ given_name: "aaa".to_string(),
+ },
+ )
+ .unwrap();
+
+ py_assert!(py, var1 var2, "(var1 > var2) == True");
+ py_assert!(py, var1 var2, "(var1 <= var2) == False");
+ py_assert!(py, var1 var3, "(var1 >= var3) == True");
+ py_assert!(py, var2 var3, "(var2 >= var3) == False");
+ py_assert!(py, var3 var4, "(var3 >= var4) == True");
+ py_assert!(py, var3 var4, "(var3 != var4) == True");
+ })
+}
+
+#[pyclass(eq, ord)]
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct Record {
+ name: String,
+ title: String,
+ idx: u32,
+}
+
+impl PartialOrd for Record {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ Some(self.idx.partial_cmp(&other.idx).unwrap())
+ }
+}
+
+#[test]
+fn test_struct_custom_ord_comparable() {
+ Python::with_gil(|py| {
+ let var1 = Py::new(
+ py,
+ Record {
+ name: "zzz".to_string(),
+ title: "bbb".to_string(),
+ idx: 9,
+ },
+ )
+ .unwrap();
+ let var2 = Py::new(
+ py,
+ Record {
+ name: "ddd".to_string(),
+ title: "aaa".to_string(),
+ idx: 1,
+ },
+ )
+ .unwrap();
+ let var3 = Py::new(
+ py,
+ Record {
+ name: "vvv".to_string(),
+ title: "ggg".to_string(),
+ idx: 19,
+ },
+ )
+ .unwrap();
+ let var4 = Py::new(
+ py,
+ Record {
+ name: "vvv".to_string(),
+ title: "ggg".to_string(),
+ idx: 19,
+ },
+ )
+ .unwrap();
+
+ py_assert!(py, var1 var2, "(var1 > var2) == True");
+ py_assert!(py, var1 var2, "(var1 <= var2) == False");
+ py_assert!(py, var1 var3, "(var1 >= var3) == False");
+ py_assert!(py, var2 var3, "(var2 >= var3) == False");
+ py_assert!(py, var3 var4, "(var3 == var4) == True");
+ py_assert!(py, var2 var4, "(var2 != var4) == True");
+ })
+}
diff --git a/tests/test_enum.rs b/tests/test_enum.rs
index 4b72143539f..96a07c3fe41 100644
--- a/tests/test_enum.rs
+++ b/tests/test_enum.rs
@@ -52,27 +52,6 @@ fn test_enum_arg() {
})
}
-#[test]
-fn test_enum_eq_enum() {
- Python::with_gil(|py| {
- let var1 = Py::new(py, MyEnum::Variant).unwrap();
- let var2 = Py::new(py, MyEnum::Variant).unwrap();
- let other_var = Py::new(py, MyEnum::OtherVariant).unwrap();
- py_assert!(py, var1 var2, "var1 == var2");
- py_assert!(py, var1 other_var, "var1 != other_var");
- py_assert!(py, var1 var2, "(var1 != var2) == False");
- })
-}
-
-#[test]
-fn test_enum_eq_incomparable() {
- Python::with_gil(|py| {
- let var1 = Py::new(py, MyEnum::Variant).unwrap();
- py_assert!(py, var1, "(var1 == 'foo') == False");
- py_assert!(py, var1, "(var1 != 'foo') == True");
- })
-}
-
#[pyclass(eq, eq_int)]
#[derive(Debug, PartialEq, Eq, Clone)]
enum CustomDiscriminant {
diff --git a/tests/ui/invalid_pyclass_args.rs b/tests/ui/invalid_pyclass_args.rs
index 24842eb484a..f74fa49d8de 100644
--- a/tests/ui/invalid_pyclass_args.rs
+++ b/tests/ui/invalid_pyclass_args.rs
@@ -71,4 +71,9 @@ impl HashOptAndManualHash {
}
}
+#[pyclass(ord)]
+struct InvalidOrderedStruct {
+ inner: i32
+}
+
fn main() {}
diff --git a/tests/ui/invalid_pyclass_args.stderr b/tests/ui/invalid_pyclass_args.stderr
index 8f1b671dfd9..23d3c3bbc64 100644
--- a/tests/ui/invalid_pyclass_args.stderr
+++ b/tests/ui/invalid_pyclass_args.stderr
@@ -1,4 +1,4 @@
-error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `mapping`, `module`, `name`, `rename_all`, `sequence`, `set_all`, `subclass`, `unsendable`, `weakref`
+error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `subclass`, `unsendable`, `weakref`
--> tests/ui/invalid_pyclass_args.rs:3:11
|
3 | #[pyclass(extend=pyo3::types::PyDict)]
@@ -46,7 +46,7 @@ error: expected string literal
24 | #[pyclass(module = my_module)]
| ^^^^^^^^^
-error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `mapping`, `module`, `name`, `rename_all`, `sequence`, `set_all`, `subclass`, `unsendable`, `weakref`
+error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `subclass`, `unsendable`, `weakref`
--> tests/ui/invalid_pyclass_args.rs:27:11
|
27 | #[pyclass(weakrev)]
@@ -76,6 +76,12 @@ error: The `hash` option requires the `eq` option.
59 | #[pyclass(hash)]
| ^^^^
+error: The `ord` option requires the `eq` option.
+ --> tests/ui/invalid_pyclass_args.rs:74:11
+ |
+74 | #[pyclass(ord)]
+ | ^^^
+
error[E0592]: duplicate definitions with name `__pymethod___richcmp____`
--> tests/ui/invalid_pyclass_args.rs:36:1
|
diff --git a/tests/ui/invalid_pyclass_enum.rs b/tests/ui/invalid_pyclass_enum.rs
index 73bc992571a..c490f9291e3 100644
--- a/tests/ui/invalid_pyclass_enum.rs
+++ b/tests/ui/invalid_pyclass_enum.rs
@@ -80,4 +80,17 @@ enum ComplexHashOptRequiresEq {
B { msg: String },
}
+#[pyclass(ord)]
+enum InvalidOrderedComplexEnum {
+ VariantA (i32),
+ VariantB { msg: String }
+}
+
+#[pyclass(eq,ord)]
+#[derive(PartialEq)]
+enum InvalidOrderedComplexEnum2 {
+ VariantA (i32),
+ VariantB { msg: String }
+}
+
fn main() {}
diff --git a/tests/ui/invalid_pyclass_enum.stderr b/tests/ui/invalid_pyclass_enum.stderr
index cfa3922ef62..98ca2d77bfa 100644
--- a/tests/ui/invalid_pyclass_enum.stderr
+++ b/tests/ui/invalid_pyclass_enum.stderr
@@ -60,6 +60,12 @@ error: The `hash` option requires the `eq` option.
76 | #[pyclass(hash)]
| ^^^^
+error: The `ord` option requires the `eq` option.
+ --> tests/ui/invalid_pyclass_enum.rs:83:11
+ |
+83 | #[pyclass(ord)]
+ | ^^^
+
error[E0369]: binary operation `==` cannot be applied to type `&SimpleEqOptRequiresPartialEq`
--> tests/ui/invalid_pyclass_enum.rs:31:11
|
@@ -151,3 +157,71 @@ help: consider annotating `ComplexHashOptRequiresHash` with `#[derive(Hash)]`
64 + #[derive(Hash)]
65 | enum ComplexHashOptRequiresHash {
|
+
+error[E0369]: binary operation `>` cannot be applied to type `&InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:89:14
+ |
+89 | #[pyclass(eq,ord)]
+ | ^^^
+ |
+note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:91:1
+ |
+91 | enum InvalidOrderedComplexEnum2 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`
+help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`
+ |
+91 + #[derive(PartialEq, PartialOrd)]
+92 | enum InvalidOrderedComplexEnum2 {
+ |
+
+error[E0369]: binary operation `<` cannot be applied to type `&InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:89:14
+ |
+89 | #[pyclass(eq,ord)]
+ | ^^^
+ |
+note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:91:1
+ |
+91 | enum InvalidOrderedComplexEnum2 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`
+help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`
+ |
+91 + #[derive(PartialEq, PartialOrd)]
+92 | enum InvalidOrderedComplexEnum2 {
+ |
+
+error[E0369]: binary operation `<=` cannot be applied to type `&InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:89:14
+ |
+89 | #[pyclass(eq,ord)]
+ | ^^^
+ |
+note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:91:1
+ |
+91 | enum InvalidOrderedComplexEnum2 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`
+help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`
+ |
+91 + #[derive(PartialEq, PartialOrd)]
+92 | enum InvalidOrderedComplexEnum2 {
+ |
+
+error[E0369]: binary operation `>=` cannot be applied to type `&InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:89:14
+ |
+89 | #[pyclass(eq,ord)]
+ | ^^^
+ |
+note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`
+ --> tests/ui/invalid_pyclass_enum.rs:91:1
+ |
+91 | enum InvalidOrderedComplexEnum2 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`
+help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`
+ |
+91 + #[derive(PartialEq, PartialOrd)]
+92 | enum InvalidOrderedComplexEnum2 {
+ |