| 291 | } |
| 292 | |
| 293 | fn _cmp_inner( |
| 294 | &self, |
| 295 | other: &Self, |
| 296 | op: PyComparisonOp, |
| 297 | vm: &VirtualMachine, |
| 298 | ) -> PyResult<Either<PyObjectRef, bool>> { |
| 299 | let swapped = op.swapped(); |
| 300 | let call_cmp = |obj: &Self, other: &Self, op| { |
| 301 | let Some(cmp) = obj.class().slots.richcompare.load() else { |
| 302 | return Ok(PyArithmeticValue::NotImplemented); |
| 303 | }; |
| 304 | let r = match cmp(obj, other, op, vm)? { |
| 305 | Either::A(obj) => PyArithmeticValue::from_object(vm, obj).map(Either::A), |
| 306 | Either::B(arithmetic) => arithmetic.map(Either::B), |
| 307 | }; |
| 308 | Ok(r) |
| 309 | }; |
| 310 | |
| 311 | let mut checked_reverse_op = false; |
| 312 | let is_strict_subclass = { |
| 313 | let self_class = self.class(); |
| 314 | let other_class = other.class(); |
| 315 | !self_class.is(other_class) && other_class.fast_issubclass(self_class) |
| 316 | }; |
| 317 | if is_strict_subclass { |
| 318 | let res = call_cmp(other, self, swapped)?; |
| 319 | checked_reverse_op = true; |
| 320 | if let PyArithmeticValue::Implemented(x) = res { |
| 321 | return Ok(x); |
| 322 | } |
| 323 | } |
| 324 | if let PyArithmeticValue::Implemented(x) = call_cmp(self, other, op)? { |
| 325 | return Ok(x); |
| 326 | } |
| 327 | if !checked_reverse_op { |
| 328 | let res = call_cmp(other, self, swapped)?; |
| 329 | if let PyArithmeticValue::Implemented(x) = res { |
| 330 | return Ok(x); |
| 331 | } |
| 332 | } |
| 333 | match op { |
| 334 | PyComparisonOp::Eq => Ok(Either::B(self.is(&other))), |
| 335 | PyComparisonOp::Ne => Ok(Either::B(!self.is(&other))), |
| 336 | _ => Err(vm.new_type_error(format!( |
| 337 | "'{}' not supported between instances of '{}' and '{}'", |
| 338 | op.operator_token(), |
| 339 | self.class().name(), |
| 340 | other.class().name() |
| 341 | ))), |
| 342 | } |
| 343 | } |
| 344 | #[inline(always)] |
| 345 | pub fn rich_compare_bool( |
| 346 | &self, |