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,
|
UnittestMock,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
Uuid,
|
Uuid,
|
||||||
|
#[cfg(test)]
|
||||||
|
UnderscoreSsl,
|
||||||
Warnings,
|
Warnings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,6 +357,8 @@ impl KnownModule {
|
||||||
Self::UnittestMock => "unittest.mock",
|
Self::UnittestMock => "unittest.mock",
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
Self::Uuid => "uuid",
|
Self::Uuid => "uuid",
|
||||||
|
#[cfg(test)]
|
||||||
|
Self::UnderscoreSsl => "_ssl",
|
||||||
Self::Templatelib => "string.templatelib",
|
Self::Templatelib => "string.templatelib",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1460,11 +1460,6 @@ impl<'db> Type<'db> {
|
||||||
.has_relation_to_impl(db, right, relation, visitor)
|
.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:
|
// 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`.
|
// 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`.
|
// 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))
|
.unwrap_or_else(|| KnownClass::Type.to_instance(db))
|
||||||
.has_relation_to_impl(db, target, relation, visitor),
|
.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)`,
|
// 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
|
// 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.
|
// (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
|
/// where the class has `Any` in its MRO
|
||||||
UnittestMockInstance,
|
UnittestMockInstance,
|
||||||
UnittestMockLiteral,
|
UnittestMockLiteral,
|
||||||
|
/// A custom `TypedDict`, imported from the `_ssl` module
|
||||||
|
TypedDict(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -236,6 +238,15 @@ impl Ty {
|
||||||
returns.map(|ty| ty.into_type(db)),
|
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",
|
class: "int",
|
||||||
method: "bit_length",
|
method: "bit_length",
|
||||||
},
|
},
|
||||||
|
Ty::TypedDict("_Cipher"),
|
||||||
|
Ty::TypedDict("_CertInfo"),
|
||||||
];
|
];
|
||||||
let types = if fully_static {
|
let types = if fully_static {
|
||||||
&types[fully_static_index..]
|
&types[fully_static_index..]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue