Skip to content

[ty] Improve keyword argument narrowing for nested dictionaries - #24010

Merged
ibraheemdev merged 1 commit into
mainfrom
ibraheem/dict-unpack-narrowing
Mar 20, 2026
Merged

ibraheemdev merged 1 commit into
mainfrom
ibraheem/dict-unpack-narrowing

Conversation

@ibraheemdev

Copy link
Copy Markdown
Member

Fixes a bug in #23436 where nested dictionary literals are not tracked, e.g.,

def f(a: int, b: str): ...

x = {"inner": {"a": 1, "b": "a"}}
f(**x["inner"])

This is unlikely to have an ecosystem impact, but seems worth doing nonetheless.

@ibraheemdev ibraheemdev added the ty The ty type checker label Mar 17, 2026
@astral-sh-bot

astral-sh-bot Bot commented Mar 17, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 85.29%. The percentage of expected errors that received a diagnostic held steady at 78.13%. The number of fully passing files held steady at 64/132.

@astral-sh-bot

astral-sh-bot Bot commented Mar 17, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented Mar 17, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-await 0 40 0
invalid-return-type 0 1 0
Total 0 41 0

Full report with detailed diff (timing results)

@carljm carljm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change adds false negatives for direct assignments to nested keys:

def f(*, b: int): ...

x: dict[str, dict[str, int]] = {"a": {"b": 1}}
x["a"]["b"] = 1

# This should be an error: x has no top-level key "b".
f(**x)

This is correctly an error on main, but a false negative with this PR.

@ibraheemdev

Copy link
Copy Markdown
Member Author

@carljm that example seems to error correctly on this PR?

➜  sandbox git:(ibraheem/dict-unpack-narrowing) ✗ cargo run --bin ty --manifest-path ~/dev/astral/ruff/Cargo.toml check main.py
error[invalid-argument-type]: Argument to function `f` is incorrect
  --> main.py:23:3
   |
22 | # This should be an error: x has no top-level key "b".
23 | f(**x)
   |   ^^^ Expected `int`, found `dict[str, int]`
   |
info: Function defined here
  --> main.py:17:5
   |
15 | #         self.mylist = [None, None, None]
16 |
17 | def f(*, b: int): ...
   |     ^    ------ Parameter declared here
18 |
19 | x: dict[str, dict[str, int]] = {"a": {"b": 1}}
   |
info: rule `invalid-argument-type` is enabled by default

Found 1 diagnostic

@carljm carljm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, sorry! I'm sure I tested that... not sure what I did wrong. Maybe I had an earlier branch checked out by accident. Never mind!

@ibraheemdev
ibraheemdev merged commit b6f3b5c into main Mar 20, 2026
53 checks passed
@ibraheemdev
ibraheemdev deleted the ibraheem/dict-unpack-narrowing branch March 20, 2026 11:14
carljm added a commit that referenced this pull request Mar 25, 2026
* main:
  [`flake8-bandit`] Check tuple arguments for partial paths in `S607` (#24080)
  [ty] Update Salsa (#24081)
  Update Rust toolchain to 1.94 and MSRV to 1.92 (#24076)
  [ty] Move ruffen-docs formatting config to a `ruff.toml` config file (#24074)
  [ty] `reveal_type` diagnostics in unreachable code (#24070)
  [ty] Improve keyword argument narrowing for nested dictionaries (#24010)
  [ty] Preserve blank lines between comments and imports in add-import action (#24066)
  [ty] Add diagnostic hint for invalid assignments involving invariant generics (#24032)
  Clarify `extend-ignore` and `extend-select` settings documentation (#24064)
  [ty] Batch changes to watched paths (#24045)
  replace deprecated `std::f64::EPSILON` with `f64::EPSILON` (#24067)
  [ty] Fix untracked reads in Salsa queries that can lead to backdating panics (#24051)
  [ty] Unions/intersections of gradual types should be assignable to `Never` (#24056)
  Fix incorrect path for ty_python_semantic in fuzzer (#24052)
  Bump 0.15.7 (#24049)
  [ty] ecosystem-analyzer: Fail on newly panicking projects (#24043)
  Don't show noqa hover for non-Python documents (#24040)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty The ty type checker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants