{"id":26159299,"url":"https://github.com/facebook/pyrefly","last_synced_at":"2026-04-02T22:13:48.915Z","repository":{"id":281740482,"uuid":"935685654","full_name":"facebook/pyrefly","owner":"facebook","description":"A fast type checker and IDE for Python","archived":false,"fork":false,"pushed_at":"2025-04-07T23:18:44.000Z","size":39099,"stargazers_count":92,"open_issues_count":44,"forks_count":6,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-04-08T00:24:57.463Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://pyrefly.org/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/facebook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-19T21:09:33.000Z","updated_at":"2025-04-07T23:18:48.000Z","dependencies_parsed_at":"2025-04-01T00:32:26.756Z","dependency_job_id":null,"html_url":"https://github.com/facebook/pyrefly","commit_stats":null,"previous_names":["facebook/pyrefly"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fpyrefly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fpyrefly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fpyrefly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fpyrefly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facebook","download_url":"https://codeload.github.com/facebook/pyrefly/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247752713,"owners_count":20990178,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-11T11:21:04.049Z","updated_at":"2026-04-02T22:13:48.870Z","avatar_url":"https://github.com/facebook.png","language":"Rust","readme":"[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n# Pyrefly: A fast type checker and IDE for Python\n\nNOT INTENDED FOR EXTERNAL USE YET. INCOMPLETE AND IN DEVELOPMENT.\n\nWe are building a new version of Pyre (Meta's Python type checker), named\nPyrefly, to increase our internal velocity and enable new features such as\nproducing typed ASTs. We aim to fully replace the existing Pyre by the end\nof 2025.\n\n## Developer cheat sheet\n\n### GitHub developers\n\n`cd pyrefly` then use the normal `cargo` commands (e.g. `cargo build`,\n`cargo test`).\n\n### Meta internal developers\n\nFrom this directory, you can run:\n\n- Check things are plausible: `./test.py` (runs the basic tests and linter)\n- Run a command: `buck2 run pyrefly -- COMMAND_LINE_ARGUMENTS`\n  - For example, run on a single file: `buck2 run pyrefly -- check test.py`\n- Run a single test: `buck2 test pyrefly -- NAME_OF_THE_TEST`\n- Run the end-to-end tests: `buck2 test test:`\n- Run `arc pyre` (a.k.a. per-target type checking) with Pyrefly:\n  `arc pyre check \u003ctargets_to_check\u003e -c python.type_checker=fbcode//pyrefly:pyrefly_for_buck`\n- Debug a file: `buck2 run pyrefly -- check \u003cfilename\u003e --debug-info=debug.js`,\n  then open `debug.html` in your browser\n- Fetch Typeshed from upstream\n  `HTTPS_PROXY=https://fwdproxy:8080 fbpython scripts/fetch_typeshed.py -o pyrefly/third_party`\n\n## Packaging\n\nWe use [maturin](https://github.com/PyO3/maturin) to build wheels and source\ndistributions. This also means that you can pip install `maturin` and use\n`maturin build` and `maturin develop` for local development. `pip install .` in\nthe `pyrefly/pyrefly` directory works as well.\n\n### Deploying to PyPI\n\nOnce a week, a\n[CodemodService job](https://www.internalfb.com/code/fbsource/xplat/scripts/codemod_service/configs/fbcode_pyrefly_version_upgrade.toml)\ngenerates a diff to update the version number. Accept this diff to upload a new\nversion to PyPI.\n\nIf you'd like to do a manual release between the weekly automated releases,\nfollow the instructions in\n[version.bzl](https://www.internalfb.com/code/fbsource/fbcode/pyrefly/version.bzl)\nto update the version number.\n\nBehind the scenes, what's happening is:\n\n- The\n  [publish_to_pypi workflow](https://github.com/facebook/pyrefly/blob/main/.github/workflows/publish_to_pypi.yml)\n  triggers on any change to version.bzl.\n- This workflow calls the\n  [build_binaries workflow](https://github.com/facebook/pyrefly/blob/main/.github/workflows/build_binaries.yml)\n  to build release artifacts, uploads them, and tags the corresponding commit\n  with the version number.\n\n## Coding conventions\n\nWe follow the\n[Buck2 coding conventions](https://github.com/facebook/buck2/blob/main/HACKING.md#coding-conventions),\nwith the caveat that we use our internal error framework for errors reported by\nthe type checker.\n\n## Choices\n\nThere are a number of choices when writing a Python type checker. We are take\ninspiration from [Pyre1](https://pyre-check.org/),\n[Pyright](https://github.com/microsoft/pyright) and\n[MyPy](https://mypy.readthedocs.io/en/stable/). Some notable choices:\n\n- We infer types in most locations, apart from parameters to functions. We do\n  infer types of variables and return types. As an example,\n  `def foo(x): return True` would result in something equivalent to had you\n  written `def foo(x: Any) -\u003e bool: ...`.\n- We attempt to infer the type of `[]` to however it is used first, then fix it\n  after. For example `xs = []; xs.append(1); xs.append(\"\")` will infer that\n  `xs: List[int]` and then error on the final statement.\n- We use flow types which refine static types, e.g. `x: int = 4` will both know\n  that `x` has type `int`, but also that the immediately next usage of `x` will\n  be aware the type is `Literal[4]`.\n- We aim for large-scale incrementality (at the module level) and optimised\n  checking with parallelism, aiming to use the advantages of Rust to keep the\n  code a bit simpler.\n- We expect large strongly connected components of modules, and do not attempt\n  to take advantage of a DAG-shape in the source code.\n\n## Design\n\nThere are many nuances of design that change on a regular basis. But the basic\nsubstrate on which the checker is built involves three steps:\n\n1. Figure out what each module exports. That requires solving all `import *`\n   statements transitively.\n2. For each module in isolation, convert it to bindings, dealing with all\n   statements and scope information (both static and flow).\n3. Solve those bindings, which may require the solutions of bindings in other\n   modules.\n\nIf we encounter unknowable information (e.g. recursion) we use `Type::Var` to\ninsert placeholders which are filled in later.\n\nFor each module, we solve the steps sequentially and completely. In particular,\nwe do not try and solve a specific identifier first (like\n[Rosyln](https://github.com/dotnet/roslyn) or\n[TypeScript](https://www.typescriptlang.org/)), and do not used fine-grained\nincrementality (like [Rust Analyzer](https://github.com/rust-lang/rust-analyzer)\nusing [Salsa](https://github.com/salsa-rs/salsa)). Instead, we aim for raw\nperformance and a simpler module-centric design - there's no need to solve a\nsingle binding in isolation if solving all bindings in a module is fast enough.\n\n### Example of bindings\n\nGiven the program:\n\n```python\n1: x: int = 4\n2: print(x)\n```\n\nWe might produce the bindings:\n\n- `define int@0` = `from builtins import int`\n- `define x@1` = `4: int@0`\n- `use x@2` = `x@1`\n- `anon @2` = `print(x@2)`\n- `export x` = `x@2`\n\nOf note:\n\n- The keys are things like `define` (the definition of something), `use` (a\n  usage of a thing) and `anon` (a statement we need to type check, but don't\n  care about the result of).\n- In many cases the value of a key refers to other keys.\n- Some keys are imported from other modules, via `export` keys and `import`\n  values.\n- In order to disamiguate identifiers we use the textual position at which they\n  occur (in the example I've used `@line`, but in reality its the byte offset in\n  the file).\n\n### Example of `Var`\n\nGiven the program:\n\n```python\n1: x = 1\n2: while test():\n3:     x = x\n4: print(x)\n```\n\nWe end up with the bindings:\n\n- `x@1` = `1`\n- `x@3` = `phi(x@1, x@3)`\n- `x@4` = `phi(x@1, x@3)`\n\nThe expression `phi` is the join point of the two values, e.g. `phi(int, str)`\nwould be `int | str`. We skip the distinction between `define` and `use`, since\nit is not necessary for this example.\n\nWhen solving `x@3` we encounter recursion. Operationally:\n\n- We start solving `x@3`.\n- That requires us to solve `x@1`.\n- We solve `x@1` to be `Literal[1]`\n- We start solving `x@3`. But we are currently solving `x@3`, so we invent a\n  fresh `Var` (let's call it `?1`) and return that.\n- We conclude that `x@3` must be `Literal[1] | ?1`.\n- Since `?1` was introduced by `x@3` we record that `?1 = Literal[1] | ?1`. We\n  can take the upper reachable bound of that and conclude that\n  `?1 = Literal[1]`.\n- We simplify `x@3` to just `Literal[1]`.\n","funding_links":[],"categories":["Rust","Type Checkers","后端"],"sub_categories":["文本处理"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Fpyrefly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacebook%2Fpyrefly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Fpyrefly/lists"}