Files
Jeong, YunWon e053f7d5b6 vm: drop trailing space from RecursionError text (#8992)
* vm: drop trailing space from RecursionError text

Format Python-limit and native-stack RecursionError messages
through one helper so empty context is not a trailing space
or an empty string.

Assisted-by: Grok 4.6

* test: deepen nested hash snippets for release stack frames

The cold RecursionError helper thins with_recursion's hot frame,
so 100_000 nested hashes no longer trip the native stack guard
in release.

Assisted-by: Grok 4.6

* vm: let RecursionError callers own the where-clause space

The helper concatenates an empty suffix or one that already
starts with a space. Call sites supply that space.

Assisted-by: Grok 4.6
2026-10-08 00:58:39 +09:00

77 lines
1.8 KiB
Python

import sys
from testutils import assert_raises
class A:
pass
assert type(hash(None)) is int
assert type(hash(object())) is int
assert type(hash(A())) is int
assert type(hash(1)) is int
assert type(hash(1.1)) is int
assert type(hash("")) is int
class Evil:
def __hash__(self):
return 1 << 63
assert hash(Evil()) == 4
with assert_raises(TypeError):
hash({})
with assert_raises(TypeError):
hash(set())
with assert_raises(TypeError):
hash([])
# Hashing a deeply nested tuple must not run off the native stack: the hash
# slot dispatch is what recurses, so that is where the depth is checked.
if sys.implementation.name == "rustpython":
# Deep enough to reach the native stack guard in release; CPython, which
# also runs this snippet, dies on the same value.
deep_tuple = ()
for _ in range(500_000):
deep_tuple = (deep_tuple,)
with assert_raises(RecursionError):
hash(deep_tuple)
# a dict key and a set member are hashed on insertion, same dispatch
with assert_raises(RecursionError):
{deep_tuple: 1}
with assert_raises(RecursionError):
{deep_tuple}
def test_unhashable_names_the_type_as_written():
# The message names the type the way `tp_name` does, so a type defined in a
# module carries the module with it.
import array
import collections
for value, name in [
(array.array("B", b"a"), "array.array"),
(collections.deque(), "collections.deque"),
([], "list"),
(bytearray(), "bytearray"),
(Unhashable(), "Unhashable"),
]:
try:
hash(value)
raise AssertionError(f"hashed {name}")
except TypeError as e:
assert str(e) == f"unhashable type: '{name}'", e
class Unhashable:
__hash__ = None
test_unhashable_names_the_type_as_written()