From 95209c9e644c6274d3cd8a52ec23e599ad807264 Mon Sep 17 00:00:00 2001 From: Timothy Nguyen Date: Sat, 3 Jan 2026 09:40:01 +0700 Subject: [PATCH 1/2] fix/issue-1616-final --- pyrefly/lib/alt/narrow.rs | 43 ++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/pyrefly/lib/alt/narrow.rs b/pyrefly/lib/alt/narrow.rs index 7effe5f1da..9858409348 100644 --- a/pyrefly/lib/alt/narrow.rs +++ b/pyrefly/lib/alt/narrow.rs @@ -219,13 +219,46 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { self.unions(res) } - fn narrow_is_not_instance(&self, left: &Type, right: &Type) -> Type { + fn narrow_is_not_instance(&self, left_type: &Type, right_type: &Type) -> Type { let mut res = Vec::new(); - for right in self.as_class_info(right.clone()) { - if let Some(right) = self.unwrap_class_object_silently(&right) { - res.push(self.subtract(left, &right)) + for right_class_info_type in self.as_class_info(right_type.clone()) { + if let Some(runtime_type) = self.unwrap_class_object_silently(&right_class_info_type) { + let type_without_runtime_type_matches = + self.distribute_over_union(left_type, |union_member_type| { + if union_member_type.is_any() { + return union_member_type.clone(); + } + + let does_union_member_type_match_runtime_type = + match (union_member_type, &runtime_type) { + ( + Type::ClassType(union_member_class_type), + Type::ClassType(runtime_class_type), + ) => self.has_superclass( + union_member_class_type.class_object(), + runtime_class_type.class_object(), + ), + ( + Type::TypedDict(_) | Type::PartialTypedDict(_), + Type::ClassType(runtime_class_type), + ) => self.has_superclass( + self.stdlib.dict_object(), + runtime_class_type.class_object(), + ), + _ => false, + }; + + if does_union_member_type_match_runtime_type + || self.is_subset_eq(union_member_type, &runtime_type) + { + Type::never() + } else { + union_member_type.clone() + } + }); + res.push(type_without_runtime_type_matches) } else { - res.push(left.clone()) + res.push(left_type.clone()) } } self.intersects(&res) From 93cd8784fca89d14cfb7559829157a035e938529 Mon Sep 17 00:00:00 2001 From: Timothy Nguyen Date: Sat, 3 Jan 2026 19:53:12 +0700 Subject: [PATCH 2/2] fix/issue-1616-final: add testcase --- pyrefly/lib/test/narrow.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pyrefly/lib/test/narrow.rs b/pyrefly/lib/test/narrow.rs index 3463ecc1c2..331029a4c3 100644 --- a/pyrefly/lib/test/narrow.rs +++ b/pyrefly/lib/test/narrow.rs @@ -1456,6 +1456,18 @@ def f(a: A | list[int]): "#, ); +testcase!( + test_dict_literal_key_isinstance_narrowing, + r#" +from typing import Literal, reveal_type +def get_value(x: dict[Literal["value"], int] | int) -> int | None: + if isinstance(x, dict): + return x.get("value") + reveal_type(x) # E: revealed type: int + return x + "#, +); + testcase!( test_nested_or_with_multiple_vars, r#"