facebook / facebook/pyrefly

Pyrefly confuses class name and locally defined methods, emitting false-positive `not-a-type`

Open
#1,900 3 comments 0 reactions 0 assignees View on GitHub
needs-discussion overloads
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

## Summary

Pyrefly confuses method name and class name, and gives a false-positive `not-a-type`.

## Reproduction

Consider the following stub file (ng_typehint.pyi)

```ng_typehint.py
class A: ...

class B:
def A(self, name: str) -> A: ...
def take_a(self, a: A) -> str: ...
def return_a(self) -> A: ...
```

Pyright successfully typechecks with this module:

```sh
$ uvx pyright ng_typehint.pyi
0 errors, 0 warnings, 0 informations
```
On the other hand, pyrefly won't type check on this:

```sh
$ uvx pyrefly check ng_typehint.pyi
ERROR Expected a type form, got instance of `(self: Self@B, name: str) -> A` [not-a-type]
--> ng_typehint.pyi:5:25
|
5 | def take_a(self, a: A) -> str: ...
| ^
|
ERROR Expected a type form, got instance of `(self: Self@B, name: str) -> A` [not-a-type]
--> ng_typehint.pyi:6:27
|
6 | def return_a(self) -> A: ...
| ^
|
INFO 2 errors
```

## Discussion

As the first glance, the stub code might seem to have code-smell issue - but this pattern of aliasing can completely make sense because there are legitimate case to provide the smart constructors methods with the same name as the original class.
More concretely, we are developing some EDSL library in Python like this:

```py
class Type: ...

class Variable:
# Cannot be initialized without resorting to interpreter.
@property
def name(self) -> str: ...
def type(self) -> Type: ...

class Interpreter:
def Variable(self, name: str, type: Type) -> Variable:
...

def IntegerVariable(self, name: str) -> Variable: ...
```

... And actually pyright allows such a definition, and our library have been providing such feature for a long time.
So renaming smart constructors can break the entire API just to convince type checker sounds inapplicable.

### Sandbox Link

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeSIAxlKnHAAQCCi9hbAOup9bQwEKJO9YfUwwwTABRwYUMABp66VAFsYLOABcATgEp6AWgB8TFm0JCRYiZtQBrGAH1U02QvqoWjfcfpbtZhzoIqLi9NowmgCu2ujOrnI%2BJsysQSDyIFGa0HAk5IggAMT0AKrZUBCapPRgUeiU2bjocJyc1jW42iqomo7oUSrYMNqS%2BCwQ6JpJfjqCwSIR0bE17CAAcgNDAfTA%2BAC%2Bq5zpIGQRYFCkhJq4KlAUxQAKpGcXfhg4BPSUTZAA5jE9CBNCzoYoAZRgMHoAAtNJpiHBEAB6JGncQXQidX5ImDoJGYXCUOBI77oP4Axp4jraDwAN1Q0FQ2FgXx%2BEH%2B2kBTXouGIlNynDImmhTQMtOGcCBwQAvPRVgBmQgARgATId0CA9hlUA0IOKAGLQGAUNBYPBEMiaoA

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.