Skip to content

str() discards str subclass type returned by __repr__ #7450

@jseop-lim

Description

@jseop-lim

Description

str() on an object whose __repr__ returns a str subclass instance incorrectly returns a plain str, discarding the subclass type. CPython preserves the subclass type as-is. This is a CPython compatibility issue.

Root Cause

PyStr::py_new calls input.str(vm) which correctly resolves to the __repr__ return value (a str subclass instance), but then extracts only the raw string data via Self::from(s.as_wtf8().to_owned()) and creates a new plain PyStr, discarding the subclass type.

CPython reference: unicodeobject.c#L15575-L15596

// Key branch: only convert when type is a str subclass
if (unicode != NULL && type != &PyUnicode_Type) {
    Py_SETREF(unicode, unicode_subtype_new(type, unicode));
}
return unicode;   // when type is exactly str → return PyObject_Str result as-is

When type == &PyUnicode_Type (plain str() call), unicode_new_impl returns the PyObject_Str result without conversion, preserving the subclass type.

Reproduction

class MyStr(str):
    pass

class Foo:
    def __repr__(self):
        return MyStr('hello')

result = str(Foo())
print(result)
print(type(result))

Output

RustPython:

hello
<class 'str'>

CPython:

hello
<class '__main__.MyStr'>

Environment

  • RustPython d248a04 (Python 3.14.0)
  • CPython 3.14.3
  • OS: Debian 12

Metadata

Metadata

Labels

C-compatA discrepancy between RustPython and CPython

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions