ruff/crates/ty_python_semantic/resources/mdtest
David Peter c0768dfd96
[ty] Attribute access on intersections with negative parts (#19524)
## Summary

We currently infer a `@Todo` type whenever we access an attribute on an
intersection type with negative components. This can happen very
naturally. Consequently, this `@Todo` type is rather pervasive and hides
a lot of true positives that ty could otherwise detect:

```py
class Foo:
    attr: int = 1

def _(f: Foo | None):
    if f:
        reveal_type(f)  # Foo & ~AlwaysFalsy

        reveal_type(f.attr)  # now: int, previously: @Todo
```

The changeset here proposes to handle member access on these
intersection types by simply ignoring all negative contributions. This
is not always ideal: a negative contribution like `~<Protocol with
members 'attr'>` could be a hint that `.attr` should not be accessible
on the full intersection type. The behavior can certainly be improved in
the future, but this seems like a reasonable initial step to get rid of
this unnecessary `@Todo` type.

## Ecosystem analysis

There are quite a few changes here. I spot-checked them and found one
bug where attribute access on pure negation types (`~P == object & ~P`)
would not allow attributes on `object` to be accessed. After that was
fixed, I only see true positives and known problems. The fact that a lot
of `unused-ignore-comment` diagnostics go away are also evidence for the
fact that this touches a sensitive area, where static analysis clashes
with dynamically adding attributes to objects:
```py
… # type: ignore # Runtime attribute access
```

## Test Plan

Updated tests.
2025-07-25 14:56:14 +02:00
..
annotations [ty] Fallback to Unknown if no type is stored for an expression (#19517) 2025-07-25 02:05:32 +00:00
assignment [ty] Homogeneous and mixed tuples (#18600) 2025-06-20 18:23:54 -04:00
binary [ty] Homogeneous and mixed tuples (#18600) 2025-06-20 18:23:54 -04:00
boolean
boundness_declaredness
call [ty] Rename type_api => ty_extensions (#19523) 2025-07-24 08:24:26 +00:00
class
comparison [ty] Enum literal types (#19328) 2025-07-15 21:31:53 +02:00
comprehensions
conditional [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
dataclasses [ty] Add basic support for dataclasses.field (#19553) 2025-07-25 14:56:04 +02:00
declaration [ty] Format conflicting types as an enumeration (#18956) 2025-06-26 14:29:33 +02:00
diagnostics lint on the global keyword if there's no explicit definition in the global scope 2025-07-15 16:56:54 -07:00
directives [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
doc
exception [ty] support del statement and deletion of except handler names (#18593) 2025-06-12 07:44:42 -07:00
expression [ty] Make tuple subclass constructors sound (#19469) 2025-07-21 21:25:11 +00:00
function [ty] Support empty function bodies in if TYPE_CHECKING blocks (#19372) 2025-07-16 14:48:04 -06:00
generics [ty] Improve protocol member type checking and relation handling (#18847) 2025-06-29 10:46:33 +00:00
ide_support [ty] Enum literal types (#19328) 2025-07-15 21:31:53 +02:00
import lint on the global keyword if there's no explicit definition in the global scope 2025-07-15 16:56:54 -07:00
literal
loops [ty] Do not consider a type T to satisfy a method member on a protocol unless the method is available on the meta-type of T (#19187) 2025-07-25 11:16:04 +01:00
narrow [ty] Attribute access on intersections with negative parts (#19524) 2025-07-25 14:56:14 +02:00
regression
scopes [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
shadowing
snapshots [ty] Rename type_api => ty_extensions (#19523) 2025-07-24 08:24:26 +00:00
stubs
subscript [ty] Fix false positives when subscripting an object inferred as having an Intersection type (#18920) 2025-06-24 18:39:02 +00:00
suppressions [ty] Consistent use of American english (in rules) (#19488) 2025-07-22 16:10:38 +02:00
type_compendium [ty] Make tuple subclass constructors sound (#19469) 2025-07-21 21:25:11 +00:00
type_of [ty] Enum literal types (#19328) 2025-07-15 21:31:53 +02:00
type_properties [ty] Infer single-valuedness for enums based on int/str (#19510) 2025-07-23 15:55:42 +02:00
type_qualifiers [ty] Support dataclasses.InitVar (#19527) 2025-07-24 16:33:33 +02:00
unary
with [ty] Add hint if async context manager is used in non-async with statement (#18299) 2025-05-26 21:34:47 +02:00
.mdformat.toml
attributes.md [ty] Attribute access on intersections with negative parts (#19524) 2025-07-25 14:56:14 +02:00
cycle.md
decorators.md
del.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
deprecated.md [ty] Consistent use of American english (in rules) (#19488) 2025-07-22 16:10:38 +02:00
descriptor_protocol.md [ty] Fix descriptor lookups for most types that overlap with None (#19120) 2025-07-05 19:34:23 +01:00
enums.md [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
exhaustiveness_checking.md [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
final.md
instance_layout_conflict.md [ty] Improve disjointness inference for NominalInstanceTypes and SubclassOfTypes (#18864) 2025-06-24 20:27:37 +00:00
intersection_types.md [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
invalid_syntax.md
known_constants.md
mdtest_config.md
mdtest_custom_typeshed.md
metaclass.md
mro.md [ty] Implement implicit inheritance from Generic[] for PEP-695 generic classes (#18283) 2025-05-26 20:40:16 +01:00
named_tuple.md [ty] Add generic inference for dataclasses (#18443) 2025-06-03 09:59:43 -07:00
overloads.md [ty] Add support for @staticmethods (#18809) 2025-06-20 10:38:17 +02:00
pep695_type_aliases.md
properties.md
protocols.md [ty] Attribute access on intersections with negative parts (#19524) 2025-07-25 14:56:14 +02:00
public_types.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
statically_known_branches.md [ty] Infer nonlocal types as unions of all reachable bindings (#18750) 2025-06-26 12:24:40 +02:00
sys_platform.md
sys_version_info.md
terminal_statements.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
ty_extensions.md [ty] Rename type_api => ty_extensions (#19523) 2025-07-24 08:24:26 +00:00
typed_dict.md [ty] Reduce false positives for TypedDict types (#19354) 2025-07-15 12:47:19 +01:00
union_types.md [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
unpacking.md [ty] Support variable-length tuples in unpacking assignments (#18948) 2025-06-27 15:29:04 -04:00
unreachable.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00