`explicit-any` is reported for `numpy.typing.NDArray` use sites even though `Any` comes from NumPy
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 516
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the Bug
## Summary
My company is interested in using Pyrefly's `explicit-any` error kind to catch first-party explicit `Any` usages, but currently Pyrefly reports `explicit-any` on third-party type aliases our first party code uses like `NDArray[np.float32]` from `numpy.typing`, even though our first party code does not write `Any` explicitly.
The `Any` appears to come from NumPy's typing internals or alias expansion. This makes common NumPy annotations noisy in first-party code.
For now we are disabling `explicit-any` due to this issue, but otherwise we try to use the `"all"` Pyrefly `preset` to configure all available kinds as errors.
Would you consider changing Pyrefly to handle this similar to Mypy which I understand only reports `explicit-any` for first-party types and annotations that explicitly use `Any` but does not attribute explicit `Any` from third-party aliases to first-party use sites?
## Minimal Pyrefly Reproduction
`pyrefly.toml`:
```toml
preset = "all"
python-version = "3.12"
python-platform = "linux"
```
`repro.py`:
```python
import numpy as np
import numpy.typing as npt
def repro(x: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:
return x
```
Run:
```bash
uv run --isolated --no-project --python python3.12 \
--with pyrefly==1.1.1 \
--with numpy==2.5.1 \
pyrefly check \
--config pyrefly.toml \
--color=never \
--summary=none \
--progress-bar no \
repro.py
```
## Actual Output
```text
ERROR Explicit `Any` is not allowed [explicit-any]
--> repro.py:5:14
|
5 | def repro(x: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:
| ^^^^^^^^^^^^^^^^^^^^^^^
|
ERROR Explicit `Any` is not allowed [explicit-any]
--> repro.py:5:42
|
5 | def repro(x: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:
| ^^^^^^^^^^^^^^^^^^^^^^^
|
```
## Expected Behavior
I would expect Pyrefly not to report `explicit-any` at the first-party use site when the first-party source did not explicitly write `Any`.
In this case, the explicit `Any` is coming from NumPy's own type aliases or stubs.
If this behavior is intentional, it would be useful to have a targeted way to suppress `explicit-any` from configured third-party modules such as `numpy.typing`, without disabling `explicit-any` globally and without replacing those imports with `Any`.
## Comparison With Mypy
Mypy accepts the repro under strict mode plus explicit-Any checking:
`mypy.ini`:
```ini
[mypy]
strict = True
disallow_any_explicit = True
```
`repro.py`:
```python
import numpy as np
import numpy.typing as npt
def repro(x: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:
return x
```
Run:
```shell
uv run --isolated --no-project --python python3.12 \
--with mypy \
--with numpy==2.5.1 \
mypy --config-file mypy.ini repro.py
```
```text
Success: no issues found in 1 source file
```
If `no_silence_site_packages = True` is enabled, Mypy reports many NumPy-internal errors, which suggests Mypy normally avoids projecting library-internal explicit `Any` into the user file.
Meanwhile if we do use explicit `Any` in first-party code, that gets flagged as an error as we desire:
`first_party_any_control.py`:
```python
from typing import Any
def repro(x: Any) -> Any:
return x
```
Run:
```shell
uv run --isolated --no-project --python python3.12 \
--with mypy \
--with numpy==2.5.1 \
mypy --config-file mypy.ini first_party_any_control.py
```
Outputs:
```text
first_party_any_control.py:4: error: Explicit "Any" is not allowed [explicit-any]
Found 1 error in 1 file (checked 1 source file)
```
## Workaround Tried
`replace-imports-with-any = ["numpy.typing"]` avoids the diagnostic, but it also discards useful NumPy typing precision.
Disabling `explicit-any` globally is too broad for projects that want to use it to block usages of explicit `Any` in first-party code.
## Environment
- Pyrefly: `1.1.1`
- Python: `3.12`
- NumPy: `2.5.1`
- OS: Linux
### Sandbox Link
Note the Pyrefly sandbox can't import third party code like numpy, so this example is a little contrived given the `numpy.py` we use is probably being checked by the sandbox as first-party code:
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAE6ArjWXRC7pQC50ByAIgEFKlVKQA0dMFFyouAZgBMAHXSrMMMHUoxi1ABT5EfISLEBtabIWKAugEo6AWgB8J4aNKWZcpbcSqdEHaMFyMlOh0%2BCDiIGQ60qSEXLRQFADEdAAKpAlQpHRoWHj4dADGuOiQAObhchCVhKqZAMowMHQAFlxcxHCIAPQD8Zr5hJzVAzDoA5i4ZXADFVUQtaJcDTNSnHSoAG6o0KjYsOWVNXUblXS4xFfocE3oZFydlU57MJRwm3QAvHRlCB5IQAIwqECqPTwUL-QEgVBQKBAmIgJgsJJkChgaj0LikYgQdDVNgcbh0QToCR0ADi0y%2BEDKkgAKgSYIIoBBUHAWWyAGqoSiqVQtTqoYgwZlw1kSgWUfRA0XiyVA%2ByqfgyyXS-mChUgDVs5mqkVlRGCqUAzVyvUtU1Qc3G9C2s2UZkAfQq2tlusVdvNHtwQMkFQOlC56C4f2ZlEYMDVanQZXtcDgdEw%2BIl%2Bjp6AZZXMzvtrocAUiwWI3LgwsTydTWEFniz9LDeaVEuZkgNbeLgTLFarSYrUh8NhLwTo5ZTVcyzNwIWInNNXA6rzkdAA7h05ugAOQ8DMwJxlTowMoAazorwglEw48F%2BLOGjonNPHXRZGa49yo1IxlW6E4MDmDA%2BDzoyEBcE4GCkLYqgCB4YjGJqHJcqmAJ1mYXiUtS6ZsvmfqugGti2EEIAAL6xKgZQbJ8ABi0AwBQRQ4AQJDkKRQA
### (Only applicable for extension issues) IDE Information
_No response_
Contributor guide
Research direction
Start by running the command in the issue against repro.py with pyrefly.toml and confirm the explicit-any locations. Trace how Pyrefly attributes Any expanded from numpy.typing at those first-party annotations, then add or update coverage for the reproduction and verify that explicit Any written in first-party code still reports while the NDArray use sites do not.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python, rust
- Domain
- developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 62/100