diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 4afbef3181..eb0fdc7033 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -1986,11 +1986,6 @@ impl<'db> Type<'db> { (Type::Dynamic(_), _) | (_, Type::Dynamic(_)) => C::unsatisfiable(db), - (Type::TypedDict(_), _) | (_, Type::TypedDict(_)) => { - // TODO: Implement disjointness for TypedDict - C::unsatisfiable(db) - } - (Type::TypeAlias(alias), _) => { let self_alias_ty = alias.value_type(db); visitor.visit((self_alias_ty, other), || { @@ -2005,6 +2000,11 @@ impl<'db> Type<'db> { }) } + (Type::TypedDict(_), _) | (_, Type::TypedDict(_)) => { + // TODO: Implement disjointness for TypedDict + C::unsatisfiable(db) + } + // A typevar is never disjoint from itself, since all occurrences of the typevar must // be specialized to the same type. (This is an important difference between typevars // and `Any`!) Different typevars might be disjoint, depending on their bounds and @@ -5924,6 +5924,8 @@ impl<'db> Type<'db> { Type::AlwaysTruthy | Type::AlwaysFalsy => KnownClass::Type.to_instance(db), Type::BoundSuper(_) => KnownClass::Super.to_class_literal(db), Type::ProtocolInstance(protocol) => protocol.to_meta_type(db), + // `TypedDict` instances are instances of `dict` at runtime, but its important that we + // understand a more specific meta type in order to correctly handle `__getitem__`. Type::TypedDict(typed_dict) => SubclassOfType::from(db, typed_dict.defining_class()), Type::TypeAlias(alias) => alias.value_type(db).to_meta_type(db), } diff --git a/crates/ty_python_semantic/src/types/type_ordering.rs b/crates/ty_python_semantic/src/types/type_ordering.rs index d1262802e9..ccfe598091 100644 --- a/crates/ty_python_semantic/src/types/type_ordering.rs +++ b/crates/ty_python_semantic/src/types/type_ordering.rs @@ -212,6 +212,12 @@ pub(super) fn union_or_intersection_elements_ordering<'db>( (Type::TypeAlias(_), _) => Ordering::Less, (_, Type::TypeAlias(_)) => Ordering::Greater, + (Type::TypedDict(left), Type::TypedDict(right)) => { + left.defining_class().cmp(&right.defining_class()) + } + (Type::TypedDict(_), _) => Ordering::Less, + (_, Type::TypedDict(_)) => Ordering::Greater, + (Type::Union(_), _) | (_, Type::Union(_)) => { unreachable!("our type representation does not permit nested unions"); } @@ -243,12 +249,6 @@ pub(super) fn union_or_intersection_elements_ordering<'db>( unreachable!("Two equal, normalized intersections should share the same Salsa ID") } - - (Type::TypedDict(left), Type::TypedDict(right)) => { - left.defining_class().cmp(&right.defining_class()) - } - (Type::TypedDict(_), _) => Ordering::Less, - (_, Type::TypedDict(_)) => Ordering::Greater, } }