ruff/crates/ty_python_semantic/resources/mdtest
Shaygan Hooshyari 988c38c013
[ty] Skip eagerly evaluated scopes for attribute storing (#20856)
## Summary

Fix https://github.com/astral-sh/ty/issues/664

This PR adds support for storing attributes in comprehension scopes (any
eager scope.)

For example in the following code we infer type of `z` correctly:

```py
class C:
    def __init__(self):
        [None for self.z in range(1)]
reveal_type(C().z) # previously [unresolved-attribute] but now shows Unknown | int
```

The fix works by adjusting the following logics:

To identify if an attriute is an assignment to self or cls we need to
check the scope is a method. To allow comprehension scopes here we skip
any eager scope in the check.
Also at this stage the code checks if self or the first method argument
is shadowed by another binding that eager scope to prevent this:

```py
class D:
    g: int

class C:
    def __init__(self):
        [[None for self.g in range(1)] for self in [D()]]
reveal_type(C().g) # [unresolved-attribute]
```

When determining scopes that attributes might be defined after
collecting all the methods of the class the code also returns any
decendant scope that is eager and only has eager parents until the
method scope.

When checking reachability of a attribute definition if the attribute is
defined in an eager scope we use the reachability of the first non eager
scope which must be a method. This allows attributes to be marked as
reachable and be seen.


There are also which I didn't add support for:

```py
class C:
    def __init__(self):
        def f():
            [None for self.z in range(1)]
        f()

reveal_type(C().z) # [unresolved-attribute]
```

In the above example we will not even return the comprehension scope as
an attribute scope because there is a non eager scope (`f` function)
between the comprehension and the `__init__` method

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-11-11 14:45:34 -08:00
..
annotations [ty] implement `typing.NewType` by adding `Type::NewTypeInstance` 2025-11-10 14:55:47 -08:00
assignment [ty] Handle annotated `self` parameter in constructor of non-invariant generic classes (#21325) 2025-11-10 19:46:49 -05:00
binary [ty] Rename `UnionType` to `types.UnionType` (#21262) 2025-11-03 22:06:56 +01:00
boolean Revert "[ty] Better control flow for boolean expressions that are inside if (#18010)" (#18150) 2025-05-17 08:27:32 -04:00
boundness_declaredness [ty] Reformulation of public symbol inference test suite (#20667) 2025-10-01 14:26:17 +02:00
call [ty] Silence false-positive diagnostics when using `typing.Dict` or `typing.Callable` as the second argument to `isinstance()` (#21386) 2025-11-11 19:30:01 +00:00
class [ty] implement `typing.NewType` by adding `Type::NewTypeInstance` 2025-11-10 14:55:47 -08:00
comparison [ty] detect cycles in binary comparison inference (#20446) 2025-09-17 09:45:25 +02:00
comprehensions [ty] `dict` is not assignable to `TypedDict` (#21238) 2025-11-03 16:57:49 -05:00
conditional [ty] Support as-patterns in reachability analysis (#19728) 2025-08-04 20:13:50 +02:00
dataclasses [ty] Improve generic call expression inference (#21210) 2025-11-10 21:29:05 +00:00
declaration [ty] Format conflicting types as an enumeration (#18956) 2025-06-26 14:29:33 +02:00
diagnostics [ty] `continue` and `break` statements outside loops are syntax errors (#20944) 2025-10-17 17:13:40 +00:00
directives [ty] Use annotated parameters as type context (#20635) 2025-10-03 17:14:51 -04:00
doc ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
exception [ty] Filter out `revealed-type` and `undefined-reveal` diagnostics from mdtest snapshots (#20820) 2025-10-12 18:39:32 +00:00
expression [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
function [ty] don't union in default type for annotated parameters (#21208) 2025-11-02 18:21:54 -05:00
generics [ty] Handle annotated `self` parameter in constructor of non-invariant generic classes (#21325) 2025-11-10 19:46:49 -05:00
ide_support [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
import [ty] Consider `from thispackage import y` to re-export `y` in `__init__.pyi` (#21387) 2025-11-11 14:41:14 -05:00
literal [ty] Type inference for comprehensions (#20962) 2025-11-02 14:35:33 +01:00
loops [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
narrow [ty] Support `isinstance()` and `issubclass()` narrowing when the second argument is a `typing.py` stdlib alias (#21391) 2025-11-11 21:09:24 +00:00
regression [ty] Fix panic due to simplifying `Divergent` types out of intersections types (#21253) 2025-11-03 15:41:11 +00:00
scopes [ty] Improve error messages for unresolved attribute diagnostics (#20963) 2025-10-19 10:58:25 +01:00
shadowing Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
snapshots [ty] implement `typing.NewType` by adding `Type::NewTypeInstance` 2025-11-10 14:55:47 -08:00
stubs [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
subscript [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
suppressions [ty] Add suggestion to unknown rule diagnostics, rename `unknown-rule` lint to `ignore-comment-unknown-rule` (#20948) 2025-10-18 12:44:21 +02:00
type_compendium [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
type_of [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
type_properties [ty] introduce local variables for `from` imports of submodules in `__init__.py(i)` (#21173) 2025-11-10 23:04:56 +00:00
type_qualifiers [ty] Fix false positive for Final attribute assignment in __init__ (#21158) 2025-11-11 12:54:05 -08:00
unary Update class literal display to use `<class 'Foo'>` style (#17889) 2025-05-06 20:11:25 -04:00
with [ty] Use `typing.Self` for the first parameter of instance methods (#20517) 2025-09-29 21:08:08 +02:00
.mdformat.toml Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
async.md [ty] Support `async`/`await`, `async with` and `yield from` (#19595) 2025-07-30 11:51:21 +02:00
attributes.md [ty] Skip eagerly evaluated scopes for attribute storing (#20856) 2025-11-11 14:45:34 -08:00
bidirectional.md [ty] Improve generic call expression inference (#21210) 2025-11-10 21:29:05 +00:00
classes.md [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
cycle.md [ty] Avoid ever-growing default types (#20991) 2025-10-21 19:13:36 +02:00
decorators.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
del.md [ty] No union with `Unknown` for module-global symbols (#20664) 2025-10-01 16:40:30 +02:00
deprecated.md [ty] Consistent use of American english (in rules) (#19488) 2025-07-22 16:10:38 +02:00
descriptor_protocol.md [ty] Infer type for implicit `self` parameters in method bodies (#20922) 2025-10-23 09:34:39 +02:00
enums.md [ty] Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums (#20541) 2025-11-10 17:53:08 +00:00
exhaustiveness_checking.md [ty] Improve exhaustiveness analysis for type variables with bounds or constraints (#21172) 2025-10-31 16:51:11 -04:00
final.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
implicit_type_aliases.md [ty] Allow PEP-604 unions in stubs and `TYPE_CHECKING` blocks prior to 3.10 (#21379) 2025-11-11 14:33:43 +00:00
instance_layout_conflict.md [ty] initial support for `slots=True` in dataclasses (#20278) 2025-09-07 18:25:35 +01:00
intersection_types.md [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
invalid_syntax.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
known_constants.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
literal_promotion.md [ty] Do not promote literals in contravariant positions of generic specializations (#21171) 2025-10-31 17:48:34 +01:00
mdtest_config.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
mdtest_custom_typeshed.md [ty] Remove `Type::Tuple` (#19669) 2025-08-11 22:03:32 +01:00
metaclass.md Update class literal display to use `<class 'Foo'>` style (#17889) 2025-05-06 20:11:25 -04:00
mro.md [ty] Rename `UnionType` to `types.UnionType` (#21262) 2025-11-03 22:06:56 +01:00
named_tuple.md [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
overloads.md [ty] Infer type of `self` for decorated methods and properties (#21123) 2025-10-29 21:22:38 +00:00
paramspec.md [ty] Understand legacy and PEP 695 `ParamSpec` (#21139) 2025-11-06 11:14:40 -05:00
pep613_type_aliases.md [ty] Fall back to `Divergent` for deeply nested specializations (#20988) 2025-10-22 14:29:10 +02:00
pep695_type_aliases.md [ty] Add cycle handling to `lazy_default` (#20967) 2025-10-23 10:05:08 +02:00
properties.md [ty] Add support for properties that return `Self` (#21335) 2025-11-10 11:13:36 +01:00
protocols.md [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
public_types.md [ty] Disambiguate classes that live in different modules but have the same fully qualified names (#20756) 2025-10-08 18:27:40 +01:00
statically_known_branches.md [ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492) 2025-09-23 14:26:55 +00:00
sys_platform.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
sys_version_info.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
t_strings.md [ty] Add support for PEP 750 t-strings (#20085) 2025-08-25 18:49:49 +00:00
terminal_statements.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
ty_extensions.md [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
typed_dict.md [ty] `dict` is not assignable to `TypedDict` (#21238) 2025-11-03 16:57:49 -05:00
union_types.md [ty] Introduce `TypeRelation::Redundancy` (#20602) 2025-10-03 18:35:30 +01:00
unpacking.md [ty] Infer more precise types for collection literals (#20360) 2025-09-17 18:51:50 -04:00
unreachable.md [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00