Skip to content

[ty] Reject functional TypedDict with mismatched name#24295

Merged
sharkdp merged 2 commits intomainfrom
charlie/ty-name
Mar 30, 2026
Merged

[ty] Reject functional TypedDict with mismatched name#24295
sharkdp merged 2 commits intomainfrom
charlie/ty-name

Conversation

@charliermarsh
Copy link
Copy Markdown
Member

@charliermarsh charliermarsh commented Mar 30, 2026

Summary

Given BadTypedDict = TypedDict("WrongName", {"name": str}), the conformance test suite suggests we need to raise a diagnostic due to the mismatch between BadTypedDict and WrongName.

See: #24174 (comment).

@astral-sh-bot astral-sh-bot bot added the ty Multi-file analysis & type inference label Mar 30, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 30, 2026

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 86.60% to 86.61%. The percentage of expected errors that received a diagnostic increased from 81.47% to 81.56%. The number of fully passing files improved from 69/132 to 70/132.

Summary

How are test cases classified?

Each test case represents one expected error annotation or a group of annotations sharing a tag. Counts are per test case, not per diagnostic — multiple diagnostics on the same line count as one. Required annotations (E) are true positives when ty flags the expected location and false negatives when it does not. Optional annotations (E?) are true positives when flagged but true negatives (not false negatives) when not. Tagged annotations (E[tag]) require ty to flag exactly one of the tagged lines; tagged multi-annotations (E[tag+]) allow any number up to the tag count. Flagging unexpected locations counts as a false positive.

Metric Old New Diff Outcome
True Positives 866 867 +1 ⏫ (✅)
False Positives 134 134 +0
False Negatives 197 196 -1 ⏬ (✅)
Total Diagnostics 1063 1064 +1
Precision 86.60% 86.61% +0.01% ⏫ (✅)
Recall 81.47% 81.56% +0.09% ⏫ (✅)
Passing Files 69/132 70/132 +1 ⏫ (✅)

Test file breakdown

1 file altered
File True Positives False Positives False Negatives Status
typeddicts_alt_syntax.py 7 (+1) ✅ 0 0 (-1) ✅ ✅ Newly Passing 🎉
Total (all files) 867 (+1) ✅ 134 196 (-1) ✅ 70/132

True positives added (1)

1 diagnostic
Test case Diff

typeddicts_alt_syntax.py:31

+error[invalid-argument-type] The name of a `TypedDict` (`WrongName`) must match the name of the variable it is assigned to (`BadTypedDict3`)

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 30, 2026

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 30, 2026

ecosystem-analyzer results

No diagnostic changes detected ✅

Full report with detailed diff (timing results)


let name = if let Some(literal) = name_type.as_string_literal() {
Name::new(literal.value(db))
let name = literal.value(db).to_string();
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.

Minor

Suggested change
let name = literal.value(db).to_string();
let name = literal.value(db);

@sharkdp sharkdp enabled auto-merge (squash) March 30, 2026 07:17
@sharkdp sharkdp merged commit e765eb0 into main Mar 30, 2026
48 checks passed
@sharkdp sharkdp deleted the charlie/ty-name branch March 30, 2026 07:22
@AlexWaygood
Copy link
Copy Markdown
Member

AlexWaygood commented Mar 30, 2026

On main (following this PR), we now emit an error for this:

from typing import TypedDict

X = TypedDict("Y", {})

but not for this, which seems just as questionable if (per the typing conformance suite) you think it's important for a type checker to enforce that the TypedDict name must exactly match the variable it's assigned to:

from typing import TypedDict

def f(x: str):
    Y = TypedDict(x, {})

(I still feel like this would be better as a bespoke warning-level diagnostic rather than having it use invalid-argument-type. It's just a lint, really; it honestly doesn't need to be enforced for correctness reasons. Though our similar error for NewType definitions is also an error-level diagnostic, so maybe it doesn't matter that much.)

carljm added a commit that referenced this pull request Mar 31, 2026
* main: (35 commits)
  Store definition indexes as u32 (#24307)
  Avoid re-using symbol in RUF024 fix (#24316)
  [ty] Add materialization to `Divergent` type (#24255)
  [ty] Make `Divergent` a top-level type variant (#24252)
  [ty] Fix nested global and nonlocal lookups through forwarding scopes (#24279)
  Fetch the cargo-dist binary directly instead of using the installer (#24258)
  [ty] Fix panic on `list[Annotated[()]]` (#24303)
  Don't measure the AST deallocation time in parser benchmarks (#24301)
  Enable CodSpeed's memory benchmarks for simulation benchmarks (#24298)
  Upgrade imara-diff to 0.2.0 (#24299)
  [ty] Represent `InitVar` as a special form internally, not a class (#24248)
  `RUF067`: Allow dunder-named assignments in non-strict mode
  [`pyupgrade`] UP018 should detect more unnecessarily wrapped literals (UP018) (#24093)
  [ty] Remove unused `system.glob` method (#24300)
  [ty] Reject functional TypedDict with mismatched name (#24295)
  Update Rust crate arc-swap to v1.9.0 (#24292)
  [ty] Remove unused `@Todo(Functional TypedDicts)` (#24297)
  Update CodSpeedHQ/action action to v4.12.1 (#24290)
  Update taiki-e/install-action action to v2.69.6 (#24293)
  Update Rust crate toml to v1.0.7 (#24289)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants