Skip to content

[mypyc] Fix crash on a property with another decorator - #22157

Merged
JukkaL merged 1 commit into
python:masterfrom
rheard:fix-mypyc-1238
Oct 14, 2026
Merged

JukkaL merged 1 commit into
python:masterfrom
rheard:fix-mypyc-1238

Conversation

@rheard

@rheard rheard commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Fixes mypyc/mypyc#1238.

mypy only rejects decorators on top of @property, so it accepts a property like this:

class C:
    @property
    @functools.lru_cache(maxsize=None)
    def p(self) -> int: ...

In a native class, prepare_method_def() left the getter out of method_decls, like any decorated method, but still set is_prop_getter and property_types. Reading c.p in compiled code then generated a native GetAttr with no getter behind it, and the compiler crashed in emit_method_call with KeyError: "'C' has no attribute 'p'". If nothing compiled read the property, the module compiled, but the method was missing from the type's method table, so the decorator was called with the property's getset_descriptor and its result replaced the property. With lru_cache the import failed (TypeError: the first argument must be callable).

A getter with other decorators is now handled like other decorated methods. handle_ext_method() applies the decorators, wraps the result with builtins.property and sets it on the class. Non-native classes already did this. The property isn't a native one, so compiled code reads it with a generic attribute lookup and coerces the result to the type mypy inferred, which is the decorated function's return type. @functools.cached_property over another decorator takes the same path.

A setter for such a property would need the native setter exposed as a Python callable, so for now it's reported as an error instead of crashing:

error: Property setter not supported when the getter has other decorators

@property over @abstractmethod, @override or @final isn't affected, since mypy removes those from the decorator list.

A decorated property that overrides a native property still fails like a decorated method that overrides a native method (mypyc/mypyc#767). This PR doesn't change that.

@JukkaL JukkaL left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good, thanks!

@JukkaL
JukkaL merged commit 46e199d into python:master Oct 14, 2026
18 checks passed
JukkaL pushed a commit that referenced this pull request Oct 15, 2026
Fixes mypyc/mypyc#1244.

mypyc crashed when a method of a native class overrode a decorated
method and the native signatures differed, for example when the override
narrows the return type, or when both methods are `async def` with the
same annotations:

```python
class Base:
    @Traced
    def get(self) -> object:
        return None

class Sub(Base):
    def get(self) -> int:
        return 1
```

```
  File "mypyc/irbuild/vtable.py", line 78, in specialize_parent_vtable
    defining_cls.glue_methods[(entry.cls, entry.name)],
KeyError: (ClassIR(name=Base, ...), 'get')
```

The function below the decorator is stored in `ClassIR.methods`, so
`compute_vtable()` gave it a vtable entry. `specialize_parent_vtable()`
then treated an override with a different signature like an override of
a native method and looked up a glue method. There is none: a decorated
method isn't in `method_decls`, so `handle_ext_method()` doesn't
generate glue for overrides of it.

A decorated method doesn't need a vtable entry at all. It isn't declared
as a native method, so compiled code only calls it through the Python
API. Since #22157 that also holds for a property with another decorator.
`compute_vtable()` now skips methods without a declaration. This
generalizes the check added in #22121, which skipped only the
undecorated function of a decorated override.

The only other code that used those entries was the `__del__` lookup in
`generate_class()`. It now uses `ClassIR.get_method()`, so a decorated
`__del__` still gets a finalizer, and still runs through the decorator.
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.

Compiler crash on a property that has another decorator below @property

2 participants