-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix (ish) hanging tests in test_list.py
#7382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,6 @@ | |
| class::PyClassImpl, | ||
| convert::ToPyObject, | ||
| function::{ArgSize, FuncArgs, OptionalArg, PyComparisonValue}, | ||
| iter::PyExactSizeIterator, | ||
| protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods}, | ||
| recursion::ReprGuard, | ||
| sequence::{MutObjectSequenceOp, OptionalRangeArgs, SequenceExt, SequenceMutExt}, | ||
|
|
@@ -547,11 +546,77 @@ | |
| return Ok(res.into()); | ||
| } | ||
| let other = class_or_notimplemented!(Self, other); | ||
| let a = &*zelf.borrow_vec(); | ||
| let b = &*other.borrow_vec(); | ||
| a.iter() | ||
| .richcompare(b.iter(), op, vm) | ||
| .map(PyComparisonValue::Implemented) | ||
|
|
||
| let mut zlen = zelf.__len__(); | ||
| let mut olen = other.__len__(); | ||
| if matches!(op, PyComparisonOp::Eq | PyComparisonOp::Ne) && (zlen != olen) { | ||
| // Shortcut: if the lengths differ, the lists differ | ||
| return Ok(PyComparisonValue::Implemented(matches!( | ||
| op, | ||
| PyComparisonOp::Ne | ||
| ))); | ||
| } | ||
|
|
||
| let mut zelements = zelf.borrow_vec().to_vec(); | ||
| let mut oelements = other.borrow_vec().to_vec(); | ||
|
|
||
| // Search for the first index where items are different. | ||
| let mut i = 0; | ||
| while i < zlen && i < olen { | ||
| if zelements.len() != zlen { | ||
| // Comparison mutated the list; refetch it. | ||
| zelements = zelf.borrow_vec().to_vec(); | ||
| } | ||
|
|
||
| if oelements.len() != olen { | ||
| // Comparison mutated the list; refetch it. | ||
| oelements = other.borrow_vec().to_vec(); | ||
| } | ||
|
|
||
| let zitem = &zelements[i]; | ||
| let oitem = &oelements[i]; | ||
|
|
||
| if !vm.bool_eq(zitem, oitem)? { | ||
|
Check warning on line 579 in crates/vm/src/builtins/list.rs
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the correct comparator in both phases. Line 579 should keep the identity fast path via 🛠️ Minimal fix- if !vm.bool_eq(zitem, oitem)? {
+ if !vm.identical_or_equal(zitem, oitem)? {
break;
}
@@
- let res = vm.identical_or_equal(zitem, oitem)?;
+ let res = zitem.rich_compare_bool(oitem, op, vm)?;
Ok(PyComparisonValue::Implemented(res))Also applies to: 613-619 🤖 Prompt for AI Agents |
||
| break; | ||
| } | ||
|
|
||
| // Refetch list sizes as calling the comparison may mutate the list. | ||
| zlen = zelf.__len__(); | ||
| olen = other.__len__(); | ||
|
|
||
| i += 1; | ||
| } | ||
|
|
||
| zlen = zelf.__len__(); | ||
| olen = other.__len__(); | ||
| if i >= zlen || i >= olen { | ||
| // No more items to compare -- compare sizes | ||
| let res = match op { | ||
| PyComparisonOp::Eq => zlen == olen, | ||
| PyComparisonOp::Ne => zlen != olen, | ||
| PyComparisonOp::Lt => zlen < olen, | ||
| PyComparisonOp::Le => zlen <= olen, | ||
| PyComparisonOp::Gt => zlen > olen, | ||
| PyComparisonOp::Ge => zlen >= olen, | ||
| }; | ||
|
|
||
| return Ok(PyComparisonValue::Implemented(res)); | ||
| }; | ||
|
|
||
| // We have an item that differs -- shortcuts for EQ/NE. | ||
| match op { | ||
| PyComparisonOp::Eq => return Ok(PyComparisonValue::Implemented(false)), | ||
| PyComparisonOp::Ne => return Ok(PyComparisonValue::Implemented(true)), | ||
| _ => {} | ||
| } | ||
|
|
||
| // Compare the final item again using the proper operator. | ||
| zelements = zelf.borrow_vec().to_vec(); | ||
| oelements = other.borrow_vec().to_vec(); | ||
| let zitem = &zelements[i]; | ||
| let oitem = &oelements[i]; | ||
| let res = vm.identical_or_equal(zitem, oitem)?; | ||
|
Check warning on line 618 in crates/vm/src/builtins/list.rs
|
||
| Ok(PyComparisonValue::Implemented(res)) | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Length-preserving mutations still compare stale items.
The refresh logic only re-clones when
len()changes. If an element comparison mutateslist[i + 1]in place, the next iteration still reads the oldzelements/oelementssnapshots, so equality and ordering can be decided on objects that are no longer in either list. If this path is meant to be mutation-aware, reload the current items each iteration instead of gating refreshes on length changes.🤖 Prompt for AI Agents