Skip to content

Commit 8882598

Browse files
Merge 35b633c into 6468a35
2 parents 6468a35 + 35b633c commit 8882598

2 files changed

Lines changed: 41 additions & 25 deletions

File tree

crates/ty_python_semantic/resources/mdtest/typed_dict.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,12 +2529,22 @@ Movie2 = TypedDict("Movie2", name=str, year=int)
25292529
```py
25302530
from typing_extensions import TypedDict
25312531

2532-
# error: [invalid-argument-type] "Invalid argument to parameter `typename` of `TypedDict()`"
2532+
# error: [invalid-argument-type] "TypedDict name must match the variable it is assigned to: Expected "Bad1", got variable of type `Literal[123]`"
25332533
Bad1 = TypedDict(123, {"name": str})
25342534

2535-
# error: [invalid-argument-type] "The name of a `TypedDict` (`WrongName`) must match the name of the variable it is assigned to (`BadTypedDict3`)"
2535+
# error: [invalid-argument-type] "TypedDict name must match the variable it is assigned to: Expected "BadTypedDict3", got "WrongName""
25362536
BadTypedDict3 = TypedDict("WrongName", {"name": str})
25372537

2538+
def f(x: str) -> None:
2539+
# error: [invalid-argument-type] "TypedDict name must match the variable it is assigned to: Expected "Y", got variable of type `str`"
2540+
Y = TypedDict(x, {})
2541+
2542+
def g(x: str) -> None:
2543+
TypedDict(x, {}) # fine
2544+
2545+
name = "GoodTypedDict"
2546+
GoodTypedDict = TypedDict(name, {"name": str})
2547+
25382548
# error: [invalid-argument-type] "Expected a dict literal for parameter `fields` of `TypedDict()`"
25392549
Bad2 = TypedDict("Bad2", "not a dict")
25402550

crates/ty_python_semantic/src/types/infer/builder/typed_dict.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -158,34 +158,40 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
158158
);
159159
}
160160

161-
let name = if let Some(literal) = name_type.as_string_literal() {
162-
let name = literal.value(db);
163-
164-
if let Some(assigned_name) = definition.and_then(|definition| definition.name(db))
165-
&& name != assigned_name
166-
&& let Some(builder) = self.context.report_lint(&INVALID_ARGUMENT_TYPE, name_arg)
167-
{
168-
builder.into_diagnostic(format_args!(
169-
"The name of a `TypedDict` (`{name}`) must match \
170-
the name of the variable it is assigned to (`{assigned_name}`)"
171-
));
172-
}
173-
174-
Name::new(name)
175-
} else {
176-
if !name_type.is_assignable_to(db, KnownClass::Str.to_instance(db))
177-
&& let Some(builder) = self.context.report_lint(&INVALID_ARGUMENT_TYPE, name_arg)
178-
{
179-
let mut diagnostic = builder.into_diagnostic(format_args!(
180-
"Invalid argument to parameter `typename` of `TypedDict()`"
161+
let name = name_type
162+
.as_string_literal()
163+
.map(|literal| Name::new(literal.value(db)));
164+
165+
if let Some(definition) = definition
166+
&& let Some(assigned_name) = definition.name(db)
167+
&& Some(assigned_name.as_str()) != name.as_deref()
168+
&& let Some(builder) = self.context.report_lint(&INVALID_ARGUMENT_TYPE, name_arg)
169+
{
170+
let mut diagnostic =
171+
builder.into_diagnostic("TypedDict name must match the variable it is assigned to");
172+
if let Some(name) = name.as_deref() {
173+
diagnostic.set_primary_message(format_args!(
174+
"Expected \"{assigned_name}\", got \"{name}\""
181175
));
176+
} else {
182177
diagnostic.set_primary_message(format_args!(
183-
"Expected `str`, found `{}`",
178+
"Expected \"{assigned_name}\", got variable of type `{}`",
184179
name_type.display(db)
185180
));
186181
}
187-
Name::new_static("<unknown>")
188-
};
182+
} else if !name_type.is_assignable_to(db, KnownClass::Str.to_instance(db))
183+
&& let Some(builder) = self.context.report_lint(&INVALID_ARGUMENT_TYPE, name_arg)
184+
{
185+
let mut diagnostic = builder.into_diagnostic(format_args!(
186+
"Invalid argument to parameter `typename` of `TypedDict()`"
187+
));
188+
diagnostic.set_primary_message(format_args!(
189+
"Expected `str`, found `{}`",
190+
name_type.display(db)
191+
));
192+
}
193+
194+
let name = name.unwrap_or_else(|| Name::new_static("<unknown>"));
189195

190196
if let Some(definition) = definition {
191197
self.deferred.insert(definition);

0 commit comments

Comments
 (0)