Skip to content

[Bug]: graalpy injects self when calling standard library function through class instance attribute (instance.func(...)) #1009

Description

@gdchinacat

Describe the bug

Setting a class attribute to one of the standard library operator functions (operator.eq) and calling it through an instance of the class behaves differently in GraalPy than in cpython.

Operating system

Linux

CPU architecture

x86_64

GraalPy version

GraalPy 3.11.7 (Oracle GraalVM Native 24.2.2)

JDK version

No response

Context configuration

import operator

class C:
    operator = operator.add

assert C().operator(1, 2) == 3

Steps to reproduce

Run the code snippet using cpython and graalpy, observe the different behavior (see expected behavior)

Expected behavior

$ uv run --python cpython src/graalpy_class_function_bug.py 
$ uv run --python graalpy src/graalpy_class_function_bug.py 
Traceback (most recent call last):
  File "/home/lonnieh/eclipse-workspace/playground/src/graalpy_class_function_bug.py", line 9, in <module>
    assert C().operator(1, 2) == 3
TypeError: add() takes 2 positional arguments but 3 were given

Executing the snippet using graalpy should function the same as in cpython, but it raises TypeError that cpython does not.

Stack trace

Traceback (most recent call last):
  File "/home/lonnieh/eclipse-workspace/playground/src/graalpy_class_function_bug.py", line 9, in <module>
    assert C().operator(1, 2) == 3
TypeError: add() takes 2 positional arguments but 3 were given

Additional context

The primary concern is the different behavior between graalpy and cpython. There is an easy and obvious workaround. Arguably, GraalPy behavior is more correct (calling a function on a class instance should inject self), but the python reference implementation disagrees.
In a weird coincidence I just so happened to try running my project that does this on the same day someone posted to discuss.python.org asking if this behavior should be deprecated (ie start the process of making cpython behave the same way GraalPy already does). https://discuss.python.org/t/deprecate-c-function-acts-like-static-method-when-accessed-on-class-behaviour/108038 It sounds as though this has been considered by core devs previously and deemed to cause too many problems to be worth fixing.
The project I ran into this in when evaluating GraalPy is https://github.com/gdchinacat/reactions/blob/main/src/reactions/predicate_types.py#L165

This is a toy project am just playing around with. I was curious if GraalPy would execute it more efficiently than cpython. Unfortunately, performance is significantly worse under GraalPy than cpython. I am not looking for a fix and am filing this mostly to ensure the issue is known.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions