Conversation
408f532 to
b0c84c9
Compare
|
|
The primer report looks great to me! For comparison with other type checkers:
|
081c5b3 to
5ec3b42
Compare
5ec3b42 to
e4501a8
Compare
fixing this false positive in a followup PR: #18055 |
We should update the rather than The merged version is more readable in its display, and probably more performant too. However, there's some other work I'd like to do first before doing that. If this PR is merged, I'll open an issue to remind me to followup on this later. |
…eepish * origin/main: [ty] Induct into instances and subclasses when finding and applying generics (#18052) [ty] Allow classes to inherit from `type[Any]` or `type[Unknown]` (#18060) [ty] Allow a class to inherit from an intersection if the intersection contains a dynamic type and the intersection is not disjoint from `type` (#18055) [ty] Narrowing for `hasattr()` (#18053) Update reference documentation for `--python-version` (#18056) [`flake8-bugbear`] Ignore `B028` if `skip_file_prefixes` is present (#18047) [`airflow`] Apply try-catch guard to all AIR3 rules (`AIR3`) (#17887) [`pylint`] add fix safety section (`PLW3301`) (#17878) Update `--python` to accept paths to executables in virtual environments (#17954) [`pylint`] add fix safety section (`PLE4703`) (#17824) [`ruff`] Implement a recursive check for `RUF060` (#17976) [`flake8-use-pathlib`] `PTH*` suppress diagnostic for all `os.*` functions that have the `dir_fd` parameter (#17968) [`refurb`] Mark autofix as safe only for number literals in `FURB116` (#17692) [`flake8-simplify`] Fix `SIM905` autofix for `rsplit` creating a reversed list literal (#18045) Avoid initializing progress bars early (#18049)
…eep-dish * origin/main: [ty] Infer parameter specializations of generic aliases (#18021) [ty] Understand homogeneous tuple annotations (#17998) [ty] Induct into instances and subclasses when finding and applying generics (#18052) [ty] Allow classes to inherit from `type[Any]` or `type[Unknown]` (#18060) [ty] Allow a class to inherit from an intersection if the intersection contains a dynamic type and the intersection is not disjoint from `type` (#18055) [ty] Narrowing for `hasattr()` (#18053) Update reference documentation for `--python-version` (#18056) [`flake8-bugbear`] Ignore `B028` if `skip_file_prefixes` is present (#18047) [`airflow`] Apply try-catch guard to all AIR3 rules (`AIR3`) (#17887) [`pylint`] add fix safety section (`PLW3301`) (#17878) Update `--python` to accept paths to executables in virtual environments (#17954) [`pylint`] add fix safety section (`PLE4703`) (#17824) [`ruff`] Implement a recursive check for `RUF060` (#17976) [`flake8-use-pathlib`] `PTH*` suppress diagnostic for all `os.*` functions that have the `dir_fd` parameter (#17968) [`refurb`] Mark autofix as safe only for number literals in `FURB116` (#17692) [`flake8-simplify`] Fix `SIM905` autofix for `rsplit` creating a reversed list literal (#18045) Avoid initializing progress bars early (#18049)
| if hasattr(x, "spam"): | ||
| reveal_type(x) # revealed: Foo & <Protocol with members 'spam'> | ||
| reveal_type(x.spam) # revealed: object |
There was a problem hiding this comment.
Can we also add a test for the negated constraint (with a TODO, if needed)? This doesn't seem to work yet?
else:
reveal_type(x) # revealed: Foo & ~<Protocol with members 'spam'>
reveal_type(x.spam) # no error?There was a problem hiding this comment.
The false negative here appears to be due to some pre-existing TODOs for intersection types. I can reproduce it using isinstance() narrowing with else branches as well as with hasattr() narrowing:
from typing import reveal_type
class Foo:
y: int
def f(x: object):
if isinstance(x, Foo):
reveal_type(x.y) # revealed: int
else:
reveal_type(x.y) # revealed: @Todo(map with boundness: intersections with negative contributions)
if hasattr(x, "foo"):
reveal_type(x.foo) # revealed: int
else:
reveal_type(x.foo) # revealed: @Todo(map with boundness: intersections with negative contributions)But you're right, I should have added a test for the else branch! I'll make a followup PR.
## Summary This addresses @sharkdp's post-merge review in #18053 (comment) ## Test Plan `cargo test -p ty_python_semantic`
…h#18067) ## Summary This addresses @sharkdp's post-merge review in astral-sh#18053 (comment) ## Test Plan `cargo test -p ty_python_semantic`
Summary
Narrow the type of an object in a
hasattr()branch by intersecting with a synthesized protocol type that has a single member with typeobjectTest Plan
mdtests added