Skip to content

Commit 6343332

Browse files
authored
Fixed int.real, int.numerator etc. returns wrong value when it's int type. (RustPython#3715)
1 parent b4b1e26 commit 6343332

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

extra_tests/snippets/builtin_int.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,25 @@ def __int__(self):
324324
assert 1 is 1 # noqa
325325
x = 6
326326
assert 5 is (x-1) # noqa
327+
328+
329+
# test issue3687
330+
import math
331+
big_int = 1000000
332+
small_int = 3
333+
assert big_int.real is big_int
334+
assert big_int.numerator is big_int
335+
assert math.trunc(big_int) is big_int
336+
assert math.floor(big_int) is big_int
337+
assert math.ceil(big_int) is big_int
338+
assert small_int.real is small_int
339+
assert small_int.numerator is small_int
340+
assert math.trunc(small_int) is small_int
341+
assert math.floor(small_int) is small_int
342+
assert math.ceil(small_int) is small_int
343+
344+
# test subclassing int
345+
class SubInt(int): pass
346+
subint = int.__new__(SubInt, 11)
347+
assert subint.real is not subint
348+
assert type(subint.real) is int

vm/src/builtins/int.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -561,18 +561,18 @@ impl PyInt {
561561
}
562562

563563
#[pymethod(magic)]
564-
fn trunc(zelf: PyRef<Self>) -> PyRef<Self> {
565-
zelf
564+
fn trunc(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
565+
Self::clone_if_subclass(zelf, vm)
566566
}
567567

568568
#[pymethod(magic)]
569-
fn floor(zelf: PyRef<Self>) -> PyRef<Self> {
570-
zelf
569+
fn floor(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
570+
Self::clone_if_subclass(zelf, vm)
571571
}
572572

573573
#[pymethod(magic)]
574-
fn ceil(zelf: PyRef<Self>) -> PyRef<Self> {
575-
zelf
574+
fn ceil(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
575+
Self::clone_if_subclass(zelf, vm)
576576
}
577577

578578
#[pymethod(magic)]
@@ -618,8 +618,8 @@ impl PyInt {
618618
}
619619

620620
#[pymethod]
621-
fn conjugate(zelf: PyRef<Self>) -> PyRef<Self> {
622-
zelf
621+
fn conjugate(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
622+
Self::clone_if_subclass(zelf, vm)
623623
}
624624

625625
#[pyclassmethod]
@@ -688,10 +688,18 @@ impl PyInt {
688688
Ok(bytes.into())
689689
}
690690

691+
#[inline]
692+
fn clone_if_subclass(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
693+
if zelf.class().is(&vm.ctx.types.int_type) {
694+
return zelf;
695+
}
696+
697+
vm.ctx.new_bigint(&zelf.value)
698+
}
699+
691700
#[pyproperty]
692-
fn real(&self, vm: &VirtualMachine) -> PyRef<Self> {
693-
// subclasses must return int here
694-
vm.ctx.new_bigint(&self.value)
701+
fn real(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
702+
Self::clone_if_subclass(zelf, vm)
695703
}
696704

697705
#[pyproperty]
@@ -700,8 +708,8 @@ impl PyInt {
700708
}
701709

702710
#[pyproperty]
703-
fn numerator(zelf: PyRef<Self>) -> PyRef<Self> {
704-
zelf
711+
fn numerator(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
712+
Self::clone_if_subclass(zelf, vm)
705713
}
706714

707715
#[pyproperty]

0 commit comments

Comments
 (0)