diff --git a/crates/ty_python_semantic/resources/mdtest/literal/collections/dictionary.md b/crates/ty_python_semantic/resources/mdtest/literal/collections/dictionary.md index 73e63e5b44c49..e91b007ae7730 100644 --- a/crates/ty_python_semantic/resources/mdtest/literal/collections/dictionary.md +++ b/crates/ty_python_semantic/resources/mdtest/literal/collections/dictionary.md @@ -189,25 +189,54 @@ def _(x: dict[str, int | str], flag: bool): # error: [invalid-argument-type] f1(**x) -x2: dict[str, object] = {"outer": {"a": 1}} +x2: dict[str, object] = {"inner": {"a": 1}} # error: [invalid-argument-type] f1(**x2) -class Y: - x: dict[str, object] - -y1 = Y() -y1.x = {"a": 1, "b": "a"} +x3: dict[str, dict[str, object]] = {"inner": {"a": 1, "b": "a"}} -f2(**y1.x) # ok -f1(**y1.x) # ok +f2(**x3["inner"]) # ok +f1(**x3["inner"]) # ok # error: [invalid-argument-type] -f3(**y1.x) +f3(**x3["inner"]) -y1.x["c"] = 1.0 -f3(**y1.x) # ok +x3["inner"]["c"] = 1.0 +f3(**x3["inner"]) # ok -y1.x = {"outer": {"a": 1}} +x3["inner"] = {"inner": {"a": 1}} # error: [invalid-argument-type] -f1(**y1.x) +f1(**x3["inner"]) + +def _(x: dict[str, object]): + x["inner"]: dict[str, float | str] = {"a": 1, "b": "a"} + + f2(**x["inner"]) # ok + f1(**x["inner"]) # ok + # error: [invalid-argument-type] + f3(**x["inner"]) + + x["inner"]["c"] = 1.0 + f3(**x["inner"]) # ok + + x["inner"] = {"inner": {"a": 1}} + # error: [invalid-argument-type] + f1(**x["inner"]) + +class Y: + inner: dict[str, object] + +def _(y: Y): + y.inner = {"a": 1, "b": "a"} + + f2(**y.inner) # ok + f1(**y.inner) # ok + # error: [invalid-argument-type] + f3(**y.inner) + + y.inner["c"] = 1.0 + f3(**y.inner) # ok + + y.inner = {"inner": {"a": 1}} + # error: [invalid-argument-type] + f1(**y.inner) ``` diff --git a/crates/ty_python_semantic/src/semantic_index/builder.rs b/crates/ty_python_semantic/src/semantic_index/builder.rs index 8c0a2bff91192..f47c72e69a45b 100644 --- a/crates/ty_python_semantic/src/semantic_index/builder.rs +++ b/crates/ty_python_semantic/src/semantic_index/builder.rs @@ -857,14 +857,7 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { continue; }; - // Recurse into nested dictionaries. - self.add_dict_key_assignment_definitions_impl( - &member_expr, - (&item.value).into(), - assignment, - ); - - if let Some(place_expr) = PlaceExpr::try_from_member_expr(member_expr) { + if let Some(place_expr) = PlaceExpr::try_from_member_expr(member_expr.clone()) { let place_id = self.add_place(place_expr); self.add_definition( @@ -875,6 +868,16 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { value: &item.value, }, ); + + // Recurse into nested dictionaries. + // + // Note that we must do this _after_ adding the outer place in order to track + // sub-member places correctly. + self.add_dict_key_assignment_definitions_impl( + &member_expr, + (&item.value).into(), + assignment, + ); } } }