`bad-override` ignores a custom `__get__` overload when checking method overrides
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 519
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the Bug
### Summary
When a subclass overrides a method with a decorator that returns a custom
descriptor object (a class implementing `__get__`, correctly overloaded for
the bound vs. unbound access cases), pyrefly's `bad-override` check compares
the *raw, unbound* attribute types of the base and derived methods instead of
resolving `__get__` on each side first. It reports an incompatible override
even when the descriptor's `__get__` is fully and correctly typed, and even
though `reveal_type` on an instance access (e.g. `Derived().method`) shows
pyrefly *does* resolve `__get__` correctly everywhere else — just not inside
this specific check.
### Notes
- We ran into this from JAX's `jax.jit`, which decorates functions and
returns a `JitWrapped[**P, R]` object with correctly-typed `__get__`
overloads for exactly this purpose (binding away `self` when accessed
through an instance). Any method decorated with `@jax.jit` inside a class
body currently trips `bad-override`, even when the wrapper is a fully
correct descriptor. (https://github.com/jax-ml/jax/pull/14688)
- Confirmed this is specific to the override check, not general `__get__`
resolution: `reveal_type(Derived().method)` correctly reports
`(...) -> None` (matching the base's bound `() -> None`), so pyrefly's
attribute-access logic already resolves `__get__` correctly — it's just
not consulted by `bad-override`'s comparison.
### Sandbox Link
https://pyrefly.org/sandbox/?project=v2.pZXBCoJAEIZfZamDIeHeF4LoCaSrdRDdTAIVtXr9_t11HDUSpZO6uv_Mzsz3u8Iy2TycpZEDmZb0QOomqfMKdhL5frgX5-sIswQSPWY-Zh6EhoG54tF_4HBuxd3Z6TkrEQQB8XXkoKyaaWaXZlrZsUOSb_i4MifRY4L2Qlp9c5YuxMoADr8FIahwEaLYknC43_qd7qGn_bIxqSLCVA6EUImcgaQ6KWHpmlqwuxWKd9klqzho1rBVHff81lFHLT7FvQlM3I5p53xoLGqMX7oze8lijpTmAq1v1rYidAuiG1v8ZQBp9oQi4EP0LVqrxb1tq0ZJSdvLOpO6kGmZNHK0QwpjK_Erzm2ZxnKitN7QQPYfyD3HuDeHuGcIxxez1H4A
### (Only applicable for extension issues) IDE Information
_No response_
Contributor guide
Research direction
Start at the bad-override check and compare its behavior with the existing __get__ resolution used for reveal_type on Derived().method. Reproduce the issue with the linked sandbox and a custom descriptor like the JitWrapped case; done means a correctly overloaded descriptor no longer produces an incompatible-override diagnostic while genuine mismatches still do.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100