X Tutup
Skip to content

Commit 3f79cb5

Browse files
committed
Merge remote-tracking branch 'upstream/main' into skip-flaky-mp-tests
2 parents 33523fa + 9a0511b commit 3f79cb5

File tree

25 files changed

+2522
-1270
lines changed

25 files changed

+2522
-1270
lines changed

.cspell.dict/cpython.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ CONVFUNC
4343
convparam
4444
copyslot
4545
cpucount
46+
datastack
4647
defaultdict
4748
denom
4849
deopt
@@ -118,13 +119,15 @@ mult
118119
multibytecodec
119120
nameobj
120121
nameop
122+
ncells
121123
nconsts
122124
newargs
123125
newfree
124126
NEWLOCALS
125127
newsemlockobject
126128
nfrees
127129
nkwargs
130+
nlocalsplus
128131
nkwelts
129132
Nondescriptor
130133
noninteger
@@ -192,6 +195,7 @@ testconsole
192195
ticketer
193196
tmptype
194197
tok_oldval
198+
tstate
195199
tvars
196200
typeobject
197201
typeparam

Lib/test/mapping_tests.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# tests common to dict and UserDict
22
import unittest
33
import collections
4-
import sys
4+
from test import support
55

66

77
class BasicTestMappingProtocol(unittest.TestCase):
@@ -70,8 +70,8 @@ def test_read(self):
7070
if not d: self.fail("Full mapping must compare to True")
7171
# keys(), items(), iterkeys() ...
7272
def check_iterandlist(iter, lst, ref):
73-
self.assertTrue(hasattr(iter, '__next__'))
74-
self.assertTrue(hasattr(iter, '__iter__'))
73+
self.assertHasAttr(iter, '__next__')
74+
self.assertHasAttr(iter, '__iter__')
7575
x = list(iter)
7676
self.assertTrue(set(x)==set(lst)==set(ref))
7777
check_iterandlist(iter(d.keys()), list(d.keys()),
@@ -448,7 +448,7 @@ def __new__(cls):
448448
class Exc(Exception): pass
449449

450450
class baddict1(self.type2test):
451-
def __init__(self):
451+
def __init__(self, *args, **kwargs):
452452
raise Exc()
453453

454454
self.assertRaises(Exc, baddict1.fromkeys, [1])
@@ -595,12 +595,14 @@ def test_mutatingiteration(self):
595595
d = self._empty_mapping()
596596
d[1] = 1
597597
try:
598+
count = 0
598599
for i in d:
599600
d[i+1] = 1
601+
if count >= 1:
602+
self.fail("changing dict size during iteration doesn't raise Error")
603+
count += 1
600604
except RuntimeError:
601605
pass
602-
else:
603-
self.fail("changing dict size during iteration doesn't raise Error")
604606

605607
def test_repr(self):
606608
d = self._empty_mapping()
@@ -620,9 +622,12 @@ def __repr__(self):
620622
d = self._full_mapping({1: BadRepr()})
621623
self.assertRaises(Exc, repr, d)
622624

625+
@support.skip_wasi_stack_overflow()
626+
@support.skip_emscripten_stack_overflow()
627+
@support.skip_if_sanitizer("requires deep stack", ub=True)
623628
def test_repr_deep(self):
624629
d = self._empty_mapping()
625-
for i in range(sys.getrecursionlimit() + 100):
630+
for i in range(support.exceeds_recursion_limit()):
626631
d0 = d
627632
d = self._empty_mapping()
628633
d[1] = d0

Lib/test/test_collections.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def __contains__(self, key):
262262
d = c.new_child(b=20, c=30)
263263
self.assertEqual(d.maps, [{'b': 20, 'c': 30}, {'a': 1, 'b': 2}])
264264

265-
@unittest.expectedFailure # TODO: RUSTPYTHON
265+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <class 'test.test_collections.TestChainMap.test_union_operators.<locals>.Subclass'> is not <class 'collections.ChainMap'>
266266
def test_union_operators(self):
267267
cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
268268
cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
@@ -2029,7 +2029,7 @@ def insert(self, index, value):
20292029
self.assertEqual(len(mss), len(mss2))
20302030
self.assertEqual(list(mss), list(mss2))
20312031

2032-
@unittest.expectedFailure # TODO: RUSTPYTHON
2032+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: TypeError not raised
20332033
def test_illegal_patma_flags(self):
20342034
with self.assertRaises(TypeError):
20352035
class Both(Collection):

Lib/test/test_deque.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ def test_gc_doesnt_blowup(self):
726726
d.append(1)
727727
gc.collect()
728728

729-
@unittest.expectedFailure # TODO: RUSTPYTHON
729+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False is not true : Cycle was not collected
730730
def test_container_iterator(self):
731731
# Bug #3680: tp_traverse was not implemented for deque iterator objects
732732
class C(object):
@@ -817,7 +817,7 @@ def test_basics(self):
817817
d.clear()
818818
self.assertEqual(len(d), 0)
819819

820-
@unittest.expectedFailure # TODO: RUSTPYTHON
820+
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'Deque' object has no attribute 'x'
821821
def test_copy_pickle(self):
822822
for cls in Deque, DequeWithSlots:
823823
for d in cls('abc'), cls('abcde', maxlen=4):
@@ -842,7 +842,7 @@ def test_copy_pickle(self):
842842
self.assertEqual(e.z, d.z)
843843
self.assertNotHasAttr(e, 'y')
844844

845-
@unittest.expectedFailure # TODO: RUSTPYTHON
845+
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'Deque' object has no attribute 'x'
846846
def test_pickle_recursive(self):
847847
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
848848
for d in Deque('abc'), Deque('abc', 3):

Lib/test/test_pickle.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,6 @@ def dumps(self, arg, proto=None, **kwargs):
8585
f.seek(0)
8686
return bytes(f.read())
8787

88-
@unittest.expectedFailure # TODO: RUSTPYTHON
89-
def test_bad_newobj_args(self):
90-
return super().test_bad_newobj_args()
91-
9288
@unittest.expectedFailure # TODO: RUSTPYTHON
9389
def test_buffer_callback_error(self):
9490
return super().test_buffer_callback_error()

crates/common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ license.workspace = true
1111
[features]
1212
default = ["std"]
1313
std = []
14-
threading = ["parking_lot"]
14+
threading = ["parking_lot", "std"]
1515
wasm_js = ["getrandom/wasm_js"]
1616

1717
[dependencies]

crates/common/src/linked_list.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ impl<L: Link> LinkedList<L, L::Target> {
157157
let ptr = L::as_raw(&val);
158158
assert_ne!(self.head, Some(ptr));
159159
unsafe {
160+
// Verify the node is not already in a list (pointers must be clean)
161+
debug_assert!(
162+
L::pointers(ptr).as_ref().get_prev().is_none(),
163+
"push_front: node already has prev pointer (double-insert?)"
164+
);
165+
debug_assert!(
166+
L::pointers(ptr).as_ref().get_next().is_none(),
167+
"push_front: node already has next pointer (double-insert?)"
168+
);
160169
L::pointers(ptr).as_mut().set_next(self.head);
161170
L::pointers(ptr).as_mut().set_prev(None);
162171

@@ -192,6 +201,20 @@ impl<L: Link> LinkedList<L, L::Target> {
192201
// }
193202
// }
194203

204+
/// Removes the first element from the list and returns it, or None if empty.
205+
pub fn pop_front(&mut self) -> Option<L::Handle> {
206+
let head = self.head?;
207+
unsafe {
208+
self.head = L::pointers(head).as_ref().get_next();
209+
if let Some(new_head) = self.head {
210+
L::pointers(new_head).as_mut().set_prev(None);
211+
}
212+
L::pointers(head).as_mut().set_next(None);
213+
L::pointers(head).as_mut().set_prev(None);
214+
Some(L::from_raw(head))
215+
}
216+
}
217+
195218
/// Returns whether the linked list does not contain any node
196219
pub const fn is_empty(&self) -> bool {
197220
self.head.is_none()
@@ -212,7 +235,11 @@ impl<L: Link> LinkedList<L, L::Target> {
212235
pub unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> {
213236
unsafe {
214237
if let Some(prev) = L::pointers(node).as_ref().get_prev() {
215-
debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node));
238+
debug_assert_eq!(
239+
L::pointers(prev).as_ref().get_next(),
240+
Some(node),
241+
"linked list corruption: prev->next != node (prev={prev:p}, node={node:p})"
242+
);
216243
L::pointers(prev)
217244
.as_mut()
218245
.set_next(L::pointers(node).as_ref().get_next());
@@ -225,7 +252,11 @@ impl<L: Link> LinkedList<L, L::Target> {
225252
}
226253

227254
if let Some(next) = L::pointers(node).as_ref().get_next() {
228-
debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node));
255+
debug_assert_eq!(
256+
L::pointers(next).as_ref().get_prev(),
257+
Some(node),
258+
"linked list corruption: next->prev != node (next={next:p}, node={node:p})"
259+
);
229260
L::pointers(next)
230261
.as_mut()
231262
.set_prev(L::pointers(node).as_ref().get_prev());

crates/common/src/lock.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,28 @@ cfg_if::cfg_if! {
1010
if #[cfg(feature = "threading")] {
1111
pub use parking_lot::{RawMutex, RawRwLock, RawThreadId};
1212

13-
pub use std::sync::{LazyLock, OnceLock as OnceCell};
13+
pub use std::sync::OnceLock as OnceCell;
1414
pub use core::cell::LazyCell;
1515
} else {
1616
mod cell_lock;
1717
pub use cell_lock::{RawCellMutex as RawMutex, RawCellRwLock as RawRwLock, SingleThreadId as RawThreadId};
1818

1919
pub use core::cell::{LazyCell, OnceCell};
20+
}
21+
}
2022

21-
/// `core::cell::LazyCell` with `Sync` for use in `static` items.
22-
/// SAFETY: Without threading, there can be no concurrent access.
23+
// LazyLock: uses std::sync::LazyLock when std is available (even without
24+
// threading, because Rust test runner uses parallel threads).
25+
// Without std, uses a LazyCell wrapper (truly single-threaded only).
26+
cfg_if::cfg_if! {
27+
if #[cfg(any(feature = "threading", feature = "std"))] {
28+
pub use std::sync::LazyLock;
29+
} else {
2330
pub struct LazyLock<T, F = fn() -> T>(core::cell::LazyCell<T, F>);
24-
// SAFETY: Without threading, there can be no concurrent access.
31+
// SAFETY: This branch is only active when both "std" and "threading"
32+
// features are absent — i.e., truly single-threaded no_std environments
33+
// (e.g., embedded or bare-metal WASM). Without std, the Rust runtime
34+
// cannot spawn threads, so Sync is trivially satisfied.
2535
unsafe impl<T, F> Sync for LazyLock<T, F> {}
2636

2737
impl<T, F: FnOnce() -> T> LazyLock<T, F> {

0 commit comments

Comments
 (0)
X Tutup