Describe the bug
slice.__repr__ formats its three members with Java's String.valueOf instead of Python repr(). Any member that is a tuple, list, or string prints its internal Java representation, so slice(()) gives slice(None, tuple(EmptySequenceStorage[]), None) where CPython gives slice(None, (), None). With a string member the output is not even well formed.
Operating system
Linux
CPU architecture
ARM64
GraalPy version
25.2.4 (Python 3.12.8); also reproduced on 25.0.2
JDK version
No response
Context configuration
No response
Steps to reproduce
print(slice(()))
print(slice((1,)))
print(slice([]))
print(slice(""))
GraalPy 25.2.4:
slice(None, tuple(EmptySequenceStorage[]), None)
slice(None, tuple(IntSequenceStorage[1]), None)
slice(None, list(EmptySequenceStorage[]), None)
slice(None, , None)
Expected behavior
CPython 3.12.13:
slice(None, (), None)
slice(None, (1,), None)
slice(None, [], None)
slice(None, '', None)
Stack trace
Additional context
int and None members are unaffected, since their Java toString() happens to match their Python repr, which is why the common slice(1, 2, 3) case looks fine. Calling repr() on the same tuple directly still gives (); it changes only once the tuple sits inside a slice.
Root Cause
The tp_repr slot at SliceBuiltins.java#L121-L129 delegates to the Java debug toString():
@Specialization
@TruffleBoundary
public static TruffleString repr(PSlice self) {
return toTruffleStringUncached(self.toString());
}
PSlice.java#L49-L58 appends each member to a StringBuilder, so every member goes through Java String.valueOf rather than Python repr(). Whatever that member's debug toString() produces is what shows up: PTuple.java#L57-L61 formats as tuple(<storage>), EmptySequenceStorage.java#L65-L69 as EmptySequenceStorage[], and ArrayBasedSequenceStorage.java#L69-L82 as the storage class name plus its elements. A TruffleString member stringifies to its bare content, which is why slice("") prints slice(None, , None).
CPython formats every member with %R, i.e. PyObject_Repr, in Objects/sliceobject.c#L373-L377, installed as tp_repr at #L688:
static PyObject *
slice_repr(PySliceObject *r)
{
return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
}
The eval(repr(x)) == x convention described in object.__repr__ does not hold for the GraalPy output.
Fix Suggestion
Apply PyObjectReprAsTruffleStringNode to getStart() / getStop() / getStep() and assemble the result with SimpleTruffleStringFormatNode, matching CPython's slice(%R, %R, %R). RangeBuiltins.java#L331-L347 already does this for range, whose CPython repr formats its three members the same way. One difference from range: a slice member can be any object with a user-defined __repr__, so the repr node needs the real frame rather than null.
Describe the bug
slice.__repr__formats its three members with Java'sString.valueOfinstead of Pythonrepr(). Any member that is a tuple, list, or string prints its internal Java representation, soslice(())givesslice(None, tuple(EmptySequenceStorage[]), None)where CPython givesslice(None, (), None). With a string member the output is not even well formed.Operating system
Linux
CPU architecture
ARM64
GraalPy version
25.2.4 (Python 3.12.8); also reproduced on 25.0.2
JDK version
No response
Context configuration
No response
Steps to reproduce
GraalPy 25.2.4:
Expected behavior
CPython 3.12.13:
Stack trace
Additional context
intandNonemembers are unaffected, since their JavatoString()happens to match their Python repr, which is why the commonslice(1, 2, 3)case looks fine. Callingrepr()on the same tuple directly still gives(); it changes only once the tuple sits inside a slice.Root Cause
The
tp_reprslot atSliceBuiltins.java#L121-L129delegates to the Java debugtoString():PSlice.java#L49-L58appends each member to aStringBuilder, so every member goes through JavaString.valueOfrather than Pythonrepr(). Whatever that member's debugtoString()produces is what shows up:PTuple.java#L57-L61formats astuple(<storage>),EmptySequenceStorage.java#L65-L69asEmptySequenceStorage[], andArrayBasedSequenceStorage.java#L69-L82as the storage class name plus its elements. ATruffleStringmember stringifies to its bare content, which is whyslice("")printsslice(None, , None).CPython formats every member with
%R, i.e.PyObject_Repr, inObjects/sliceobject.c#L373-L377, installed astp_reprat#L688:The
eval(repr(x)) == xconvention described inobject.__repr__does not hold for the GraalPy output.Fix Suggestion
Apply
PyObjectReprAsTruffleStringNodetogetStart()/getStop()/getStep()and assemble the result withSimpleTruffleStringFormatNode, matching CPython'sslice(%R, %R, %R).RangeBuiltins.java#L331-L347already does this forrange, whose CPython repr formats its three members the same way. One difference fromrange: a slice member can be any object with a user-defined__repr__, so the repr node needs the real frame rather thannull.