`__new__` annotated as `Any` causes constructor call to be inferred as `Any`
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 516
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the Bug
When a class defines `__new__` with return type `Any`, `pyrefly` infers the constructor call as `Any` rather than the class type. This causes `no-any-return-explicit` when the constructor result is returned from a function annotated to return that class.
```
from typing import Any, reveal_type
class MyClass:
def __new__(cls) -> Any:
return super().__new__(cls)
def my_func() -> MyClass:
x = MyClass()
reveal_type(x)
reveal_type(MyClass)
return x # ERROR: Returning Any from function declared to return "MyClass"
```
I understand why this happens, but it feels surprising that a function declared to return `MyClass` reports an error when returning `MyClass()`. Should `pyrefly` treat a constructor call as the class type in this case, even if `__new__` is annotated as returning `Any`?
I saw this pattern with `jinja2` using `Template.__new__` ([here](https://github.com/pallets/jinja/blob/main/src/jinja2/environment.py#L1164)), which returns `Any`.
For comparison, `mypy` treats `MyClass()` as `MyClass` despite the `Any` return annotation on `__new__`:
```
$ mypy --strict example.py
example.py:9: note: Revealed type is "example.MyClass"
example.py:10: note: Revealed type is "def () -> example.MyClass"
```
This seems like one of those cases were `pyrefly` is more technically correct, but `mypy` provides a better user experience. I don't know the ramifications of such a change though.
### Sandbox Link
https://pyrefly.org/sandbox/?project=v2.lZQxD4IwEIX_ykUWHaQ7u6PRdCYxBBskQdrQouXfe722hKIhcT16j971e-_fyFyFjXfUeaL8TBzVizcaqu40MYC932TpUYlhf8iXh6MJntPN-cATlOpbXESoOB684Hyrvf1RC8fnL_R7C5DBifMLL4BTyQ2LNwUaPtoQ58Ep8SnAyNha7oJi6Va9wiCDqy9A2CgGIPLTjBizqJeXfYYJK-BhjNIFY7FdDg0TPbvLWrOkg4EjvnpVLYV3KgeSsNUou8GfGoQWhkqIsat4IHNhVdfWrTlWOPcSw01qPg
### (Only applicable for extension issues) IDE Information
_No response_
Contributor guide
Research direction
Reproduce the example in the linked Pyrefly sandbox and inspect the revealed types and return error. Trace the constructor-call inference for a class whose __new__ returns Any, then compare the result with the stated mypy behavior. Done means the intended constructor type is established and covered by a regression test without breaking relevant __new__ semantics.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100