Pyrefly v1.4: Fewer false positives

Pyrefly v1.4 is out. Highlights:
- Fewer false positives, from fixes to import resolution, gradual types, and overloads.
- Tensor shapes for libraries: a new compatibility syntax, and JAX shape stubs on PyPI.
- The VS Code extension uses the Pyrefly in your environment, so your editor and CLI run the same version.
- uv workspace members are now type checked.
- Layered configuration and BasedPyright migration.
This release includes 1,191 commits from 66 contributors. To get started, run:
pip install --upgrade pyrefly==1.4.0
For the full list of changes, see the v1.4.0 release notes.
Fewer false positives
A false positive is an error reported on code that is correct. Each one forces you to stop, investigate, and suppress it. False positives were the most common category of feedback after v1.3, so they were the focus of this release. They can be hard to track down because they often depend on a specific project layout or library. Many of the fixes below started as a bug report with a small reproduction.
Thank you to everyone in the community who filed an issue, trimmed a failing project down to a few lines, tested a pre-release, or sent a pull request. You made this release possible, so please keep the reports coming!
We test each change against a corpus of open-source projects with mypy_primer, so we can confirm that a fix removes the errors it targets without introducing new ones.
Import resolution
An unresolved import leaves every name it provides untyped, which causes follow-on errors.
- Test packages in
src/layouts. When Pyrefly infers asrc/layout, it also searches the project root at a lower priority, sotests.helpersandconftestresolve. sys.pathordering. Pyrefly follows Python's first-match rule: an earlier.pyfile wins over a package from a later search root.- Re-export cycles. Pyrefly falls back to stubs when source files re-export from each other in a cycle.
Unknown base classes
A base class from a conditional import can have a union type such as Loader | Unknown. Pyrefly used to reject it with invalid-inheritance. It now uses the known class and records that the class has a dynamic base.
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
class MyLoader(Loader): # v1.3: Invalid base class: `Loader | Unknown`
... # v1.4: OK
Gradual types and overloads
no-any-returnno longer reports a function whose declared return type already containsAny.- Methods whose type is a union with
Any, or whose decorator returnsT | Any, bindselfcorrectly. - Assignments to an overloaded type are accepted when the value fits any branch, and overloaded tuples unpack position by position.
- Overloaded arguments to generic functions use a new overload table.
incompatible-overload-residualis renamed toincompatible-overload-argument; the old name remains as a deprecated alias.
Tensor shapes
- Compatibility syntax.
shape_extensions.Shapedandshape_extensions.shape_varslet a library annotate with shape types without requiring its users to run Pyrefly. - JAX shape stubs on PyPI as
jax-pyrefly-stubs, the first stable release to include them. - Experimental
jaxtypingsupport, behind an opt-in configuration option. - Broader coverage across Torch, NumPy, and JAX, including
jax.lax.scan,Tensor.T, andtorch.is_tensornarrowing.
Tensor shape support remains experimental. See the tensor shapes documentation for current APIs and examples.
Editor and project setup
- VS Code uses your environment's Pyrefly. The extension launches the Pyrefly installed in your active environment and falls back to its bundled binary if there isn't one. Set
pyrefly.pyreflyExecutabletobundledto keep the old behavior. - uv workspace members are type checked. Pyrefly previously treated editable workspace sources as installed packages and skipped them. Errors in those packages can now appear.
- Layered configuration.
extendslets a config file build on another, so a monorepo can share one base config. - BasedPyright migration. Pyrefly reads
[tool.basedpyright]inpyproject.tomland applies the matching preset. - Shell completion.
pyrefly completiongenerates scripts for bash, zsh, and fish.
New checks
method-assignreports assignment to a method on an instance.- Unreachable code after an
if/elsewhere every branch returns or raises. - Opt-in
Anychecks, such asunknown-member-type,unknown-return-type, anduntyped-function-decorator, help you find whereAnyenters your code.
Library support
- Polars:
selectandwith_columnspreserve schemas, column names are validated infilter,sort,unique, anddrop_nulls, andpl.col.completes columns. - Django:
QuerySet.annotate()keeps keyword annotations on result rows, andForeignKey(to=...)resolves correctly.
Upgrading
Some changes in this release can surface new errors or change your editor setup. The release notes list the behavior changes and explain how to suppress new errors while you upgrade.
We're not done
v1.4 fixes the false positives we could reproduce, but it doesn't fix all of them, and reducing false positives remains a priority for upcoming releases. If Pyrefly reports an error on code that you think is correct, or anything else looks wrong, please open an issue. A small code sample that reproduces the problem is the fastest way for us to fix it.
Thank you to the 66 contributors to v1.4, and to everyone who has filed a bug report.
- GitHub milestones: upcoming releases
- Discord: chat with the team