Skip to content

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

Closed

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

Activity

  1. added
    C-compatA discrepancy between RustPython and CPython
    on Mar 17, 2026
  2. added a commit that references this issue on Apr 28, 2026
    6c498fc
  3. added a commit that references this issue on Sep 16, 2026
    ec8baa7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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