Skip to content

Conversation

p-sawicki
Copy link
Collaborator

#19739 introduced support for compiling __new__ methods in native classes. Native classes differ internally from regular python types which results in TypeErrors being raised when object.__new__(cls) is called when cls is a native class.

To avoid making this call, super().__new__(cls) is transformed into a call to an internal setup function. I forgot to replicate this for calls to equivalent object.__new__(cls) calls so this PR fixes that. This introduced a regression because before my changes, __new__ methods with object.__new__(cls) were effectively ignored at runtime, and after my changes they started raising TypeErrors.

Note that these calls are left as-is outside of __new__ methods so it's still possible to trigger the TypeError but that is not a regression as this was the case before. For example this code:

class Test:
    pass

t = object.__new__(Test)

results in TypeError: object.__new__(Test) is not safe, use Test.__new__(). This differs from interpreted python but the error message is actually correct in that using Test.__new__(Test) instead works.

@BobTheBuidler
Copy link
Contributor

you can add _64bit to the end of your test name to tell the 32-bit runner to skip it

ie testObjectDunderNew_64bit

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates! A few more minor things.

if isinstance(lvalue, (TupleExpr, ListExpr)):
lvalues += lvalue.items
else:
lvalues.append(lvalue)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There could be a nested expression, e.g. [a, [b, c]] = ..., so this needs to be recursive.

# Disallowed because it could break the transformation of object.__new__ calls
# inside __new__ methods.
builder.error(
f"Assignment to argument {cls_arg} in __new__ method unsupported", stmt.line
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use double quotes around Python names for consistency, i.e. '... "{cls_arg}" in "__new__" method ...'.

not_raised = RaisesException(1)
assert not_raised.val == 1

with assertRaises(TypeError, "object.__new__(str) is not safe, use str.__new__()"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we test anywhere that happens if there is str.__new__(cls) or str.__new__(str) or str.__new__(int)? Add run tests (or irbuild if they generate compile errors) for these if they don't exist (both within __new__ and outside).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, added the tests. turned out that we still need to check if translate_object_new was called for object.__new__() specifically because str.__new__() also triggered the transformation.

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good now!

@p-sawicki p-sawicki merged commit fa3566a into python:master Sep 22, 2025
13 checks passed
@p-sawicki p-sawicki deleted the fix-object-dunder-new branch September 22, 2025 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants