mirror of https://github.com/astral-sh/ruff
[ty] Consider a TypedDict type to be a subtype of itself
This commit is contained in:
parent
b49aa35074
commit
4eaf24028d
|
|
@ -330,6 +330,8 @@ pub enum KnownModule {
|
|||
UnittestMock,
|
||||
#[cfg(test)]
|
||||
Uuid,
|
||||
#[cfg(test)]
|
||||
UnderscoreSsl,
|
||||
Warnings,
|
||||
}
|
||||
|
||||
|
|
@ -355,6 +357,8 @@ impl KnownModule {
|
|||
Self::UnittestMock => "unittest.mock",
|
||||
#[cfg(test)]
|
||||
Self::Uuid => "uuid",
|
||||
#[cfg(test)]
|
||||
Self::UnderscoreSsl => "_ssl",
|
||||
Self::Templatelib => "string.templatelib",
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1460,11 +1460,6 @@ impl<'db> Type<'db> {
|
|||
.has_relation_to_impl(db, right, relation, visitor)
|
||||
}
|
||||
|
||||
(Type::TypedDict(_), _) | (_, Type::TypedDict(_)) => {
|
||||
// TODO: Implement assignability and subtyping for TypedDict
|
||||
C::from_bool(db, relation.is_assignability())
|
||||
}
|
||||
|
||||
// In general, a TypeVar `T` is not a subtype of a type `S` unless one of the two conditions is satisfied:
|
||||
// 1. `T` is a bound TypeVar and `T`'s upper bound is a subtype of `S`.
|
||||
// TypeVars without an explicit upper bound are treated as having an implicit upper bound of `object`.
|
||||
|
|
@ -1816,6 +1811,16 @@ impl<'db> Type<'db> {
|
|||
.unwrap_or_else(|| KnownClass::Type.to_instance(db))
|
||||
.has_relation_to_impl(db, target, relation, visitor),
|
||||
|
||||
(Type::TypedDict(left), Type::TypedDict(right)) if left == right => {
|
||||
// TODO: Implement structural assignability and subtyping for TypedDict
|
||||
C::always_satisfiable(db)
|
||||
}
|
||||
|
||||
(Type::TypedDict(_), _) | (_, Type::TypedDict(_)) => {
|
||||
// TODO: Implement structural assignability and subtyping for TypedDict
|
||||
C::from_bool(db, relation.is_assignability())
|
||||
}
|
||||
|
||||
// For example: `Type::SpecialForm(SpecialFormType::Type)` is a subtype of `Type::NominalInstance(_SpecialForm)`,
|
||||
// because `Type::SpecialForm(SpecialFormType::Type)` is a set with exactly one runtime value in it
|
||||
// (the symbol `typing.Type`), and that symbol is known to be an instance of `typing._SpecialForm` at runtime.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ pub(crate) enum Ty {
|
|||
/// where the class has `Any` in its MRO
|
||||
UnittestMockInstance,
|
||||
UnittestMockLiteral,
|
||||
/// A custom `TypedDict`, imported from the `_ssl` module
|
||||
TypedDict(&'static str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
@ -236,6 +238,15 @@ impl Ty {
|
|||
returns.map(|ty| ty.into_type(db)),
|
||||
),
|
||||
),
|
||||
Ty::TypedDict(name) => {
|
||||
let ty = known_module_symbol(db, KnownModule::UnderscoreSsl, name)
|
||||
.place
|
||||
.expect_type()
|
||||
.to_instance(db)
|
||||
.expect("Class type should be convertible to instance");
|
||||
assert!(ty.is_typed_dict());
|
||||
ty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,6 +325,8 @@ fn arbitrary_core_type(g: &mut Gen, fully_static: bool) -> Ty {
|
|||
class: "int",
|
||||
method: "bit_length",
|
||||
},
|
||||
Ty::TypedDict("_Cipher"),
|
||||
Ty::TypedDict("_CertInfo"),
|
||||
];
|
||||
let types = if fully_static {
|
||||
&types[fully_static_index..]
|
||||
|
|
|
|||
Loading…
Reference in New Issue