Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Hm, it doesn't seem to be dealing particularly well with imported packages that don't have type annotations. Seeing a bunch of "has no attribute" warnings. Some of the "substitute" annotations also seem to be wrong (e.g. asyncio in CPython has no annotations [in my installed version], but it's pulling some in from somewhere and they're not quite right…) It's also getting confused about lists and tuples in __slots__.


The standard library does not directly include type hints, they are stored in typeshed: https://github.com/python/typeshed

You can take a look yourself if you think some of them are wrong: https://github.com/python/typeshed/tree/main/stdlib/asyncio

The advantage is type hints can be fixed without needing to release a new version of Python. The disadvantage is there's a lot of code in the standard library that doesn't really consider how to represent it with type hints, and it can be really tricky and not always possible.

I'm surprised to see so many people moving to pyrefly, ty, and zuban so quickly. I was going to wait until some time in 2026 to see which has matured to the point I find useful, I guess some users really find existing solutions actually unworkable.


> You can take a look yourself if you think some of them are wrong: https://github.com/python/typeshed/tree/main/stdlib/asyncio

Hmm. Presumably mypy and pyrefly use the same ones, but then I don't understand why pyrefly is complaining and mypy isn't:

  ERROR Argument `Future[list[BaseException | Any]]` is not assignable to parameter `future` with type `Awaitable[tuple[Any]]` in function `asyncio.events.AbstractEventLoop.run_until_complete` [bad-argument-type]
     --> xxx/xxx.py:513:33
      |
  513 |         loop.run_until_complete(tasks.gather(*x, return_exceptions=True))
      |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The definition in typeshed is this:

  def run_until_complete(self, future: _AwaitableLike[_T]) -> _T: ...
…where is it even puling "tuple[Any]" from…

(tbh this is rather insignificant compared to the noise from external packages without type annotations, or with incomplete ones… pyrefly's inferences at the existence of attributes and their types are extremely conservative…)


> Hmm. Presumably mypy and pyrefly use the same ones, but then I don't understand why pyrefly is complaining and mypy isn't:

> …where is it even puling "tuple[Any]" from…

Perhaps it's a bug in pyrefly, perhaps mypy or pyrefly is able to infer something about the types that the other isn't. I would strongly suggest checking their issues page, and if not seeing a report already report it yourself.

While there is an ongoing push to more consistently document the typing spec: https://typing.python.org/. It does not actually cover all the things you can infer from type hints, and different type hint checkers have decided to take different design choices compared to mypy and will produce different errors even in the most ideal situation.

This is one of the reasons why I am waiting for these libraries to mature a little more.


> it does not actually cover what rules you can check or infer from type hints

Indeed this is the cause of maybe 30% of the warnings I'm seeing… items being added to lists or dicts in some place (or something else making it infer a container type), and pyrefly then refusing other types getting added elsewhere. The most "egregious" one I saw was:

  def something(x: list[str]) -> str:
      foo = []
      for i in x:
          foo.append(i)
      return "".join(foo)
Where it complains:

  ERROR Argument `str` is not assignable to parameter `object` with type `LiteralString` in function `list.append` [bad-argument-type]
   --> test.py:4:20
  4 |         foo.append(i)
Edit: now that I have posted it, this might actually be a bug in the .join type annotation… or something

Edit: nah, it's the loop (and the LiteralString variant of .join is just the first overload listed in the type hints)… https://github.com/facebook/pyrefly/issues/1107 - this is kinda important, I don't think I can use it before this is improved :/


I assume in your example if you update the foo declaration to the following it solves the complaint:

    foo: list[str] = []
If so this a type checking design choice:

  * What can I infer from an empty collection declaration?
  * What do I allow further down the code to update inferences further up the code?
I don't know Pyrefly's philosophy here, but I assume it's guided by opinionated coding guidelines inside Meta, not what is perhaps the easiest for users to understand.


Yes, annotating the type explicitly fixes it; but tbh I'd consider that type annotation "unnecessary/distracting code litter".

As far as their philosophy goes, it's an open issue they're working on, so their philosophy seems to agree this particular pattern should work :)


It is a purely subjective design decision, but I personally prefer the stricter rules that don’t do backwards type inferences like this… type hints shouldn’t follow duck typing semantics. Otherwise you’re not providing nearly as much value IMO. Typescript is really the model organism here. They took the most cursed mainstream programming language, and made it downright good.

Today, the “: list[str]” is 11 wasted characters and it’s not as aesthetically pleasing. Tomorrow, you do some refactor and your inferred list[str] becomes a list[int] without you realizing it… I’m sure that sounds silly in this toy example, but just imagine it’s a much more complex piece of code. The fact of the matter is, you declared foo as a list[any] and you’re passing it to a function that takes an iterable[str] — it ought to complain at you! Type hints are optional in Python, and you can tell linters to suppress warnings in a scope with a comment too.

That being said, perhaps these more permissive rules might be useful in a legacy codebase where no type annotations exist yet.

Really, it’d be extra nice if they made this behavior configurable, but I’m probably asking for too much there. What’s next, a transpiler? Dogs and cats living together?!


> Today, the “: list[str]” is 11 wasted characters and it’s not as aesthetically pleasing. Tomorrow, you do some refactor and your inferred list[str] becomes a list[int] without you realizing it… I’m sure that sounds silly in this toy example, but just imagine it’s a much more complex piece of code.

Hmm. I'm looking at a codebase that is still in a lot of "early flux", where one day I might be looking at a "list[VirtualRouter]" but the next day it's a "list[VirtualRouterSpec]". It's already gone through several refactors and it kinda felt like the type hints were pretty much spot on in terms of effort-benefit. It's not a legacy codebase; it has reasonably good type hint coverage, but it's focused on type hinting interfaces (a few Protocol in there), classes and functions. The type hinting inline in actual code is limited.

I do understand your perspective, but tbh to me it feels like if I went that far I might rather not choose Python to begin with…


I agree, but as a type checker it is a subjective choice, whether to be explicit and not make assumptions or whether to infer from certain certain patterns as probably correct and not be noisy to the user. Very glad to see they plan to fix this.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: