[ty] basic narrowing on attribute and subscript expressions (#17643)

## Summary

This PR closes astral-sh/ty#164.

This PR introduces a basic type narrowing mechanism for
attribute/subscript expressions.
Member accesses, int literal subscripts, string literal subscripts are
supported (same as mypy and pyright).

## Test Plan

New test cases are added to `mdtest/narrow/complex_target.md`.

---------

Co-authored-by: David Peter <mail@david-peter.de>
This commit is contained in:
Shunsuke Shibayama 2025-06-17 18:07:46 +09:00 committed by GitHub
parent 390918e790
commit 342b2665db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 739 additions and 327 deletions

View file

@ -661,6 +661,7 @@ fn place_by_id<'db>(
// See mdtest/known_constants.md#user-defined-type_checking for details.
let is_considered_non_modifiable = place_table(db, scope)
.place_expr(place_id)
.expr
.is_name_and(|name| matches!(name, "__slots__" | "TYPE_CHECKING"));
if scope.file(db).is_stub(db.upcast()) {
@ -1124,8 +1125,8 @@ mod implicit_globals {
module_type_symbol_table
.places()
.filter(|symbol| symbol.is_declared() && symbol.is_name())
.map(semantic_index::place::PlaceExpr::expect_name)
.filter(|place| place.is_declared() && place.is_name())
.map(semantic_index::place::PlaceExprWithFlags::expect_name)
.filter(|symbol_name| {
!matches!(&***symbol_name, "__dict__" | "__getattr__" | "__init__")
})