mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Normalize round() result to an exact int (#8511)
int.__round__ returned the receiver unchanged on the no-rounding path, so round() on an int subclass handed back an instance of that subclass: round(True) was True, not 1. CPython routes both no-op paths (ndigits is None, and ndigits >= 0) through long_long(), which reuses the reference only when the value is an exact int and otherwise copies it into a fresh one. Return zelf.__int__(vm).into_pyref(), which goes through into_exact_or() and is the same normalization the neighbouring __trunc__, __floor__ and __ceil__ already perform. Assisted-by: Claude Code:claude-opus-5
This commit is contained in:
1 parent
2a793fcdd1
commit
2e05364117
2 files changed
+21
-1
No files matched your search
@@ -487,7 +487,9 @@ impl PyInt {
|
||||
return vm.ctx.new_int(rounded);
|
||||
}
|
||||
}
|
||||
zelf
|
||||
// No rounding to do, but an int subclass must still be normalized to an
|
||||
// exact int, the way CPython's long_long() does.
|
||||
zelf.__int__(vm).into_pyref()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -93,3 +93,21 @@ assert math.copysign(1.0, round(0.0, 2)) == 1.0
|
||||
assert round(1.0, 1000) == 1.0
|
||||
assert round(1.0, -1000) == 0.0
|
||||
assert round(1.7976931348623157e308, 0) == 1.7976931348623157e308
|
||||
|
||||
|
||||
# round() normalizes an int subclass to an exact int, like CPython's long_long().
|
||||
assert round(True) == 1
|
||||
assert type(round(True)) is int
|
||||
assert type(round(True, 0)) is int
|
||||
assert type(round(False)) is int
|
||||
|
||||
|
||||
class MyInt(int):
|
||||
pass
|
||||
|
||||
|
||||
assert round(MyInt(5)) == 5
|
||||
assert type(round(MyInt(5))) is int
|
||||
assert type(round(MyInt(5), 2)) is int
|
||||
# A negative ndigits already produced a fresh exact int.
|
||||
assert type(round(MyInt(15), -1)) is int
|
||||
Reference in new issue
Block a user