I found performance not that different to Pyright. The major difference is quality and correctness. Mypy is full of weird bugs and insane typing holes.
I found cases where it would even treat `foo: SomeType` and `foo # type: SomeType` differently!
I tried to fix that one but looking into the code lowered my impression of it even further. It's a complete mess. It's not at all a surprise that it gets so many things wrong.
Overall Mypy is like kind of like a type checker written by people who've only ever seen linters before. It checks some types but it's kind of wooly and heuristic and optional.
Pyright is a type checker written by someone who knows what they are doing. It is mostly sound, doesn't just say "eh we won't check that" half the time, and has barely any bugs.
Seriously check the closed/open issues on Github - there's a touch of "I disagree so I'm closing that" but only a touch. It mostly has so few open issues because the main author is a machine.
The only real problems with it are performance (it's ok but definitely could be better), and the slightly annoying dependence on Node.
I upvoted as your comment sounds reasonable, but in a sibling comment I see:
>By comparison [to pyright], mypy uses a more traditional multi-pass architecture where semantic analysis is performed multiple times on a module from the top to the bottom until all types converge
That makes it sound like mypy does in fact do The Right Thing (albeit the slower, less-suitable-for-LSP thing), rather than a messy pile of heuristic/optional hacks.
> It is mostly sound, doesn't just say "eh we won't check that" half the time
No, but they did kinda say that about `attrs`, which is a big deal for me and my stuff at least. Hopefully this new project can deal with all the crazy dynamic stuff python allows you to get away with.
Not really knowing fully about how type checkers work, one thing I struggled with a fair amount working with Mypy is how the stubs made available from various libraries were both all over the place in quality and not straightforward as a beginner to get working. Is this approach of using stubs a requirement for basically any static type checker that Python uses, or is this a specific way that Mypy chose to implement this concept?
But without that, I always felt like I was actively fighting mypy. It seemed like it was written for a totally different language than Python.
Compared to another more modern type system like TypeScript, sometimes you don't explicitly type something and yet TypeScript usually does exactly what you expect.
> Pyright was designed with performance in mind. It is not unusual for pyright to be 3x to 5x faster than mypy when type checking large code bases. Some of its design decisions were motivated by this goal.
> Pyright was also designed to be used as the foundation for a Python language server. Language servers provide interactive programming features such as completion suggestions, function signature help, type information on hover, semantic-aware search, semantic-aware renaming, semantic token coloring, refactoring tools, etc. For a good user experience, these features require highly responsive type evaluation performance during interactive code modification. They also require type evaluation to work on code that is incomplete and contains syntax errors.
> To achieve these design goals, pyright is implemented as a “lazy” or “just-in-time” type evaluator. Rather than analyzing all code in a module from top to bottom, it is able to evaluate the type of an arbitrary identifier anywhere within a module. If the type of that identifier depends on the types of other expressions or symbols, pyright recursively evaluates those in turn until it has enough information to determine the type of the target identifier. By comparison, mypy uses a more traditional multi-pass architecture where semantic analysis is performed multiple times on a module from the top to the bottom until all types converge.
> Pyright implements its own parser, which recovers gracefully from syntax errors and continues parsing the remainder of the source file. By comparison, mypy uses the parser built in to the Python interpreter, and it does not support recovery after a syntax error. This also means that when you run mypy on an older version of Python, it cannot support newer language features that require grammar changes.
Astral's type checker seems to an exercise in speeding up Pyright's approach to designing a type checker, and removing the Node dependency from it.
I haven't had any issues from MyPy regarding speed. So performance issues did not exist whenever I used MyPy. Also not sure why I need incremental anything. I save a file and then I want it to be checked.
If I am not implementing a LS, then how is it of any importance, whether the type checker was designed with typing a LS? How does that benefit me in my normal projects?
If there are no semantic improvements, that allow more type inference than MyPy allows, I don't see much going for Pyright. Sounds like a "ours is blazingly faster than the other" kind of sales pitch.
Just to throw my anecdote in: I used to work at the mypy shop - our client code base was on the order of millions of lines of very thorny Python code. This was several years ago, but to the best of my recollection, even at that scale, mypy was nowhere near that slow.
Like I said, this was many years ago - mypy might've gotten slower, but computers have also gotten faster, so who knows. My hunch is still that you have an issue with misconfiguration, or perhaps you're hitting a bug.
My current company is a Python shop, 1M+ LOC. My CI run earlier today completed mypy typechecking in 9 minutes 5 seconds. Take from that what you will.
Ditto, same order of magnitude experience; at least for --no-incremental runs.
Part of the problem for me is how easily caches get invalidated. A type error somewhere will invalidate the cache of the file and anything in its dependency tree, which blows a huge hole runtime.
Checking 1 file in a big repo can take 10 seconds, or more than a minute as a result.
I think you have something misconfigured, or are timing incorrectly. I'm working on a project right now with ~10K LOC. I haven't timed it, but it's easily <= 2 seconds. Even if I nuke MyPy's cache, it's at most 5 seconds. This is on an M3 MBP FWIW.
Pyright has semantic improvements (and also some differences) over MyPy. As for using the type checker as a language server, it's difficult to go back to “it's compiling” after you've had one stop you from typing bugs out in-flight.
Pyright infers return types for me correctly in most cases, while mypy couldn't even property infer the return type of void functions (you have to specify `-> None` explicitly).
I think that https://github.com/microsoft/pyright/blob/main/docs/mypy-com... actually covers the majority of my gripes with mypy, the main issues I encounter with mypy are due to its lack of precision. It produces a lot of false positives for code that is well-typed that pyright can handle. Also the lack of type inference and lack of type checking for unannotated code (by default) is kinda painful. Mypy in general makes certain patterns which are pythonic not typecheck whilst pyright is a lot less painful in that regard.
I've personally found that dealing with mypy has been more noisy and painful than using pyright and leads to a lot of users/other devs just ignoring typing altogether.
I think that type checking has to closely match the semantics of the language and if there's a gap, it will often push users to do the easy thing, which is just ignoring checks.