| 418 | |
| 419 | impl Comparable for PyUnion { |
| 420 | fn cmp( |
| 421 | zelf: &Py<Self>, |
| 422 | other: &PyObject, |
| 423 | op: PyComparisonOp, |
| 424 | vm: &VirtualMachine, |
| 425 | ) -> PyResult<PyComparisonValue> { |
| 426 | op.eq_only(|| { |
| 427 | let other = class_or_notimplemented!(Self, other); |
| 428 | |
| 429 | // Check if lengths are equal |
| 430 | if zelf.args.len() != other.args.len() { |
| 431 | return Ok(PyComparisonValue::Implemented(false)); |
| 432 | } |
| 433 | |
| 434 | // Fast path: if both unions have all hashable args, compare frozensets directly |
| 435 | // Always use Eq here since eq_only handles Ne by negating the result |
| 436 | if zelf.unhashable_args.is_none() |
| 437 | && other.unhashable_args.is_none() |
| 438 | && let (Some(a), Some(b)) = (&zelf.hashable_args, &other.hashable_args) |
| 439 | { |
| 440 | let eq = a |
| 441 | .as_object() |
| 442 | .rich_compare_bool(b.as_object(), PyComparisonOp::Eq, vm)?; |
| 443 | return Ok(PyComparisonValue::Implemented(eq)); |
| 444 | } |
| 445 | |
| 446 | // Slow path: O(n^2) nested loop comparison for unhashable elements |
| 447 | // Check if all elements in zelf.args are in other.args |
| 448 | for arg_a in &*zelf.args { |
| 449 | let mut found = false; |
| 450 | for arg_b in &*other.args { |
| 451 | match arg_a.rich_compare_bool(arg_b, PyComparisonOp::Eq, vm) { |
| 452 | Ok(true) => { |
| 453 | found = true; |
| 454 | break; |
| 455 | } |
| 456 | Ok(false) => continue, |
| 457 | Err(e) => return Err(e), // Propagate comparison errors |
| 458 | } |
| 459 | } |
| 460 | if !found { |
| 461 | return Ok(PyComparisonValue::Implemented(false)); |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | // Check if all elements in other.args are in zelf.args (for symmetry) |
| 466 | for arg_b in &*other.args { |
| 467 | let mut found = false; |
| 468 | for arg_a in &*zelf.args { |
| 469 | match arg_b.rich_compare_bool(arg_a, PyComparisonOp::Eq, vm) { |
| 470 | Ok(true) => { |
| 471 | found = true; |
| 472 | break; |
| 473 | } |
| 474 | Ok(false) => continue, |
| 475 | Err(e) => return Err(e), // Propagate comparison errors |
| 476 | } |
| 477 | } |