Pyrefly v1.2.0-dev.2
Pre-releaseRelease date: July 10, 2026
About dev releases
Dev releases (versions likeX.Y.Z-dev.N) are non-stable snapshots cut periodically from trunk. They give early adopters a chance to try in-progress features and surface issues before the next stable release, but they don't carry the same stability or compatibility guarantees as a stable release — don't pin production projects to a dev version.
Pyrefly v1.2.0-dev.2 bundles 158 commits from 23 contributors.
✨ New & Improved
Type Checking
- Functions decorated with
functools.singledispatchnow type-check calls using the signature of the function you decorated, catching argument errors likef("bad")when that function expectsint. Registered implementations are also checked against that function's first parameter, so their dispatch types must be compatible. - Generic
singledispatchfunctions now infer their generic types from call arguments instead of reportingUnknown. - Pyrefly can now warn when a function declared to return a concrete type returns
Any, with separate diagnostics for explicit and inferredAnyreturns. These warnings are off by default for backward compatibility; you can enable them explicitly, or let Pyrefly migrate the setting from mypy whenwarn_return_anyis enabled. isinstance(x, type)now preserves type arguments when narrowing unions, sotype[int] | strnarrows totype[int]instead of baretype.- Class decorators annotated as returning
type[Any]now make the decorated class behave dynamically, matching decorators that can substantially change the class at runtime. - Class methods can now access generic class attributes through
cls, fixing falsemissing-attributeerrors on abstract base classes. - Membership checks with
Any/unknown items now invoke the container's__contains__method and returnboolinstead ofUnknown. copy.replaceis now type-checked like dataclass replacement, so Pyrefly validates immutable updates more accurately.
Language Server
- Hover tooltips for union methods now look at each union member, so
x: A | B; x.foo()correctly showsfooas a method when bothA.fooandB.fooare methods. - Hovering over augmented assignment operators like
+=now shows the__iadd__definition and type, or the right-hand side literal type when that is the best available information. - Attribute hovers like
c.xnow show where the attribute's type was narrowed instead of unrelated first-use info. - Hover and type lookups now work correctly in notebook cells after the first.
- Inlay hints, document symbols, references, and diagnostic grouping now work correctly in notebook code cells that follow markdown cells.
- Auto-import completions now respect the
python.analysis.autoImportCompletionssetting, skipping auto-imports when disabled. - Value completions are now skipped when typing a keyword-argument name (e.g.,
func(foo=1, ba|)), and statement keywords liketry/whileare no longer offered in expression contexts. - Deprecated stdlib typing aliases (e.g.,
typing.List) are now ranked below theircollections.abcequivalents in auto-import completions.
Bazel Integration
- A new, experimental
bazel-checkcommand adds Bazel-focused type-checking for projects that provide source information through JSON manifests. It is intended to collaborate with an in-progressrules_pyreflyBazel rule implementation.
Tensor Shape Types
- Shape-aware stubs can now express methods whose types follow another method on the same object. This lets
nn.Module.__call__type-check like the module'sforwardmethod. SizeTupleis now the public way to write shape parameters, with support for compact syntax likendarray[[2, 3], dtype]and unpacking with*Elements[SizeTuple].- Torch and NumPy shape stubs now use
SizeTuple, making it easier to model APIs involving multiple tensors with different shapes. - Symbolic shape variables now use
SymVar, written asN: SymVarin PEP 695 syntax. Shape arithmetic is now limited to these symbolic shape variables.
🐛 Bug fixes
We closed 26 bug reports this release 👏
- #897: Fixed an issue where attribute narrowing with optional values failed to preserve the narrowed type across conditional branches, causing false positives when accessing attributes after a null check.
- #3585: Fixed
isinstance(value, type)narrowing fortype[int] | strunions, which previously collapsed to baretypeinstead of preservingtype[int]. - #3584: Fixed
isinstance(value, type)narrowing forTypeForm[object], which previously producedtype & TypeForm[object]instead of the correcttype[int]after anissubclasscheck. - #2689: Fixed subsequent
isinstance(cls, type)andissubclass(cls, upper_bound)checks erasingTypeVarinformation, sotype[F]is preserved through assertion chains instead of widening to the bound. - #3806: Added
no-any-returnerror kinds to detect returningAnyfrom functions declared to return concrete types, with explicit and implicit variants and support for migrating mypy'swarn_return_anysetting. - #4024: Fixed
pyrefly coverage check --strictincorrectly labeling fully-Anysymbols (e.g.,def f(x: Any) -> Any) ascoverage-partialinstead ofcoverage-missing. - #4062: Fixed
pytorch-efficiency-lintsnot recognizingTensorin common stub layouts. - #4083: Fixed
tuple(xs)losing track of tuple length whenxsis already a tuple, now preserving known shapes liketuple[int, int]instead of widening totuple[int, ...]. - #4093: Fixed an internal error when accessing
__class__.__setattr__on a class object, caused by missing metaclass handling. - #4073: Fixed unpacked
TypeVarTuplearguments liketuple[int, *Ts]not being assignable to varargs typetuple[int, *Ts]due to an internal mismatch in how Pyrefly represented the tuple types. - And more! #4025, #4019, #4020, #4021, #3730, #3732, #3997, #4018, #4023, #3949, #4022, #3920, #4092, #3078, #3960, #4064
Thank you to all our contributors who found these bugs and reported them! Did you know this is one of the most helpful contributions you can make to an open-source project? If you find any bugs in Pyrefly, we want to know about them! Please open a bug report issue here.
📦 Upgrade
pip install --upgrade pyrefly==1.2.0-dev.2How to safely upgrade your codebase
Upgrading the version of Pyrefly you're using or a third-party library you depend on can reveal new type errors in your code. Fixing them all at once is often unrealistic. We've written scripts to help you temporarily silence them. After upgrading, follow these steps:
pyrefly check --suppress-errors- Run your code formatter of choice
pyrefly check --remove-unused-ignores- Repeat until you achieve a clean formatting run and a clean type check.
This will add # pyrefly: ignore comments to your code, enabling you to silence errors and return to them later. This can make the process of upgrading a large codebase much more manageable.
Read more about error suppressions in the Pyrefly documentation.
🖊️ Contributors this release
@stroxler, @grievejia, @shobhitmehro, @asukaminato0721, @jorenham, @kinto0, @yangdanny97, David Tolnay, @ericzhonghou, @connernilsen, @qnox, @mikeleppane, @dillydill123, @arthaud, @alexander-beedie, @NathanTempest, @fhoehle, @WilliamK112, @xaskii, @durvesh1992, @lennardwalter, @kz357, @nitishagar
Please note: These release notes summarize major updates and features. For brevity, not all individual commits are listed.