# Bug report The optimisation to LOAD_SUPER_ATTR introduced by #104270 appears to have introduced a backwards incompatibility. The following code will reproduce the problem: ``` class MyInstance: def __new__(cls, ptr, name, bases, attrs): self = super().__new__(cls, name, bases, attrs) print(f"{MyInstance=} {self=} {type(self)=}, {super(MyInstance, type(self))=}") super(MyInstance, type(self)).__setattr__(self, "ptr", ptr) return self def __setattr__(self, name, value): raise Exception() class MyClass(MyInstance, type): def __new__(cls, name): self = super().__new__(cls, id(name), name, (MyInstance,), {}) return self class1 = MyClass("Class1") print(f"{class1.ptr=}") class2 = MyClass("Class2") print(f"{class2.ptr=}") ``` Under 3.12.0a7 (and previous stable Python versions going back to at least 3.7), this will succeed, outputting: ``` MyInstance=<class '__main__.MyInstance'> self=<class '__main__.Class1'> type(self)=<class '__main__.MyClass'>, super()=<super: <class 'MyInstance'>, <MyClass object>> class1.ptr=4364457392 MyInstance=<class '__main__.MyInstance'> self=<class '__main__.Class2'> type(self)=<class '__main__.MyClass'>, super()=<super: <class 'MyInstance'>, <MyClass object>> class2.ptr=4365761904 ``` Under 3.12.0b1, it raises an error: ``` MyInstance=<class '__main__.MyInstance'> self=<class '__main__.Class1'> type(self)=<class '__main__.MyClass'>, super()=<super: <class 'MyInstance'>, <MyClass object>> class1.ptr=4370144336 MyInstance=<class '__main__.MyInstance'> self=<class '__main__.Class2'> type(self)=<class '__main__.MyClass'>, super()=<super: <class 'MyInstance'>, <MyClass object>> Traceback (most recent call last): File "/Users/rkm/beeware/rubicon/objc/repro.py", line 24, in <module> class2 = MyClass("Class2") ^^^^^^^^^^^^^^^^^ File "/Users/rkm/beeware/rubicon/objc/repro.py", line 16, in __new__ self = super().__new__(cls, id(name), name, (MyInstance,), {}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/rkm/beeware/rubicon/objc/repro.py", line 7, in __new__ super().__setattr__(self, "ptr", ptr) TypeError: expected 2 arguments, got 3 ``` That is - the first `MyClass` instance can be instantiated; however, the second instance fails in mid-construction when invoking `__setattr__`. The state of the objects prior to the `__setattr__` invocation appear to be identical, but the `__setattr__` method behaves differently on the second invocation. Git bisect has narrowed the cause down to #104270 (CC @carljm, @markshannon). The reproduction case also fails if the call to `super`: ``` super(MyInstance, type(self)).__setattr__(self, "ptr", ptr) ``` is replaced with the simpler: ``` super().__setattr__(self, "ptr", ptr) ``` ## Background This test case has been extracted from [rubicon-objc](https://github.com/beeware/rubicon-objc), causing beeware/rubicon-objc#313. Rubicon is a wrapper around the Objective C runtime used by macOS and iOS; `MyInstance` is an analog of `ObjCInstance`, and `MyClass` is a an analog of `ObjCClass`. `ObjCInstance` has an implementation of `__setattr__` to redirect attribute access to the underlying ObjC calls. However, during construction, `ObjCInstance` needs to store a `ptr` of the underlying ObjC instance. This isn't a valid ObjC attribute, so `super()` is used to access the underlying `__setattr__` implementation to set the attribute. # Your environment - CPython versions tested on: 3.7.9, 3.10.11, 3.12.0a7, 3.12.0b1 - Operating system and architecture: macOS ARM64 <!-- gh-linked-prs --> ### Linked PRs * gh-105094 * gh-105117 <!-- /gh-linked-prs -->