mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-03 05:13:00 +00:00
[ty] Add assertions to ensure that we never call KnownClass::Tuple.to_instance() or similar (#21027)
This commit is contained in:
parent
6271fba1e1
commit
40148d7b11
3 changed files with 53 additions and 28 deletions
|
|
@ -4614,7 +4614,13 @@ impl KnownClass {
|
||||||
/// the class. If this class is generic, this will use the default specialization.
|
/// the class. If this class is generic, this will use the default specialization.
|
||||||
///
|
///
|
||||||
/// If the class cannot be found in typeshed, a debug-level log message will be emitted stating this.
|
/// If the class cannot be found in typeshed, a debug-level log message will be emitted stating this.
|
||||||
|
#[track_caller]
|
||||||
pub(crate) fn to_instance(self, db: &dyn Db) -> Type<'_> {
|
pub(crate) fn to_instance(self, db: &dyn Db) -> Type<'_> {
|
||||||
|
debug_assert_ne!(
|
||||||
|
self,
|
||||||
|
KnownClass::Tuple,
|
||||||
|
"Use `Type::heterogeneous_tuple` or `Type::homogeneous_tuple` to create `tuple` instances"
|
||||||
|
);
|
||||||
self.to_class_literal(db)
|
self.to_class_literal(db)
|
||||||
.to_class_type(db)
|
.to_class_type(db)
|
||||||
.map(|class| Type::instance(db, class))
|
.map(|class| Type::instance(db, class))
|
||||||
|
|
@ -4623,7 +4629,13 @@ impl KnownClass {
|
||||||
|
|
||||||
/// Similar to [`KnownClass::to_instance`], but returns the Unknown-specialization where each type
|
/// Similar to [`KnownClass::to_instance`], but returns the Unknown-specialization where each type
|
||||||
/// parameter is specialized to `Unknown`.
|
/// parameter is specialized to `Unknown`.
|
||||||
|
#[track_caller]
|
||||||
pub(crate) fn to_instance_unknown(self, db: &dyn Db) -> Type<'_> {
|
pub(crate) fn to_instance_unknown(self, db: &dyn Db) -> Type<'_> {
|
||||||
|
debug_assert_ne!(
|
||||||
|
self,
|
||||||
|
KnownClass::Tuple,
|
||||||
|
"Use `Type::heterogeneous_tuple` or `Type::homogeneous_tuple` to create `tuple` instances"
|
||||||
|
);
|
||||||
self.try_to_class_literal(db)
|
self.try_to_class_literal(db)
|
||||||
.map(|literal| Type::instance(db, literal.unknown_specialization(db)))
|
.map(|literal| Type::instance(db, literal.unknown_specialization(db)))
|
||||||
.unwrap_or_else(Type::unknown)
|
.unwrap_or_else(Type::unknown)
|
||||||
|
|
@ -4667,11 +4679,17 @@ impl KnownClass {
|
||||||
///
|
///
|
||||||
/// If the class cannot be found in typeshed, or if you provide a specialization with the wrong
|
/// If the class cannot be found in typeshed, or if you provide a specialization with the wrong
|
||||||
/// number of types, a debug-level log message will be emitted stating this.
|
/// number of types, a debug-level log message will be emitted stating this.
|
||||||
|
#[track_caller]
|
||||||
pub(crate) fn to_specialized_instance<'db>(
|
pub(crate) fn to_specialized_instance<'db>(
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
specialization: impl IntoIterator<Item = Type<'db>>,
|
specialization: impl IntoIterator<Item = Type<'db>>,
|
||||||
) -> Type<'db> {
|
) -> Type<'db> {
|
||||||
|
debug_assert_ne!(
|
||||||
|
self,
|
||||||
|
KnownClass::Tuple,
|
||||||
|
"Use `Type::heterogeneous_tuple` or `Type::homogeneous_tuple` to create `tuple` instances"
|
||||||
|
);
|
||||||
self.to_specialized_class_type(db, specialization)
|
self.to_specialized_class_type(db, specialization)
|
||||||
.and_then(|class_type| Type::from(class_type).to_instance(db))
|
.and_then(|class_type| Type::from(class_type).to_instance(db))
|
||||||
.unwrap_or_else(Type::unknown)
|
.unwrap_or_else(Type::unknown)
|
||||||
|
|
@ -5566,11 +5584,19 @@ mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
for class in KnownClass::iter() {
|
for class in KnownClass::iter() {
|
||||||
assert_ne!(
|
// Check the class can be looked up successfully
|
||||||
class.to_instance(&db),
|
class.try_to_class_literal_without_logging(&db).unwrap();
|
||||||
Type::unknown(),
|
|
||||||
"Unexpectedly fell back to `Unknown` for `{class:?}`"
|
// We can't call `KnownClass::Tuple.to_instance()`;
|
||||||
);
|
// there are assertions to ensure that we always call `Type::homogeneous_tuple()`
|
||||||
|
// or `Type::heterogeneous_tuple()` instead.`
|
||||||
|
if class != KnownClass::Tuple {
|
||||||
|
assert_ne!(
|
||||||
|
class.to_instance(&db),
|
||||||
|
Type::unknown(),
|
||||||
|
"Unexpectedly fell back to `Unknown` for `{class:?}`"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5617,11 +5643,19 @@ mod tests {
|
||||||
current_version = version_added;
|
current_version = version_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_ne!(
|
// Check the class can be looked up successfully
|
||||||
class.to_instance(&db),
|
class.try_to_class_literal_without_logging(&db).unwrap();
|
||||||
Type::unknown(),
|
|
||||||
"Unexpectedly fell back to `Unknown` for `{class:?}` on Python {version_added}"
|
// We can't call `KnownClass::Tuple.to_instance()`;
|
||||||
);
|
// there are assertions to ensure that we always call `Type::homogeneous_tuple()`
|
||||||
|
// or `Type::heterogeneous_tuple()` instead.`
|
||||||
|
if class != KnownClass::Tuple {
|
||||||
|
assert_ne!(
|
||||||
|
class.to_instance(&db),
|
||||||
|
Type::unknown(),
|
||||||
|
"Unexpectedly fell back to `Unknown` for `{class:?}` on Python {version_added}"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5950,7 +5950,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
.unwrap_or(InferableTypeVars::None);
|
.unwrap_or(InferableTypeVars::None);
|
||||||
annotation.filter_disjoint_elements(
|
annotation.filter_disjoint_elements(
|
||||||
self.db(),
|
self.db(),
|
||||||
KnownClass::Tuple.to_instance(self.db()),
|
Type::homogeneous_tuple(self.db(), Type::unknown()),
|
||||||
inferable,
|
inferable,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -85,16 +85,6 @@ impl<'db> Type<'db> {
|
||||||
Type::NominalInstance(NominalInstanceType(NominalInstanceInner::ExactTuple(tuple)))
|
Type::NominalInstance(NominalInstanceType(NominalInstanceInner::ExactTuple(tuple)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// **Private** helper function to create a `Type::NominalInstance` from a class that
|
|
||||||
/// is known not to be `Any`, a protocol class, or a typed dict class.
|
|
||||||
fn non_tuple_instance(db: &'db dyn Db, class: ClassType<'db>) -> Self {
|
|
||||||
if class.is_known(db, KnownClass::Object) {
|
|
||||||
Type::NominalInstance(NominalInstanceType(NominalInstanceInner::Object))
|
|
||||||
} else {
|
|
||||||
Type::NominalInstance(NominalInstanceType(NominalInstanceInner::NonTuple(class)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) const fn into_nominal_instance(self) -> Option<NominalInstanceType<'db>> {
|
pub(crate) const fn into_nominal_instance(self) -> Option<NominalInstanceType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::NominalInstance(instance_type) => Some(instance_type),
|
Type::NominalInstance(instance_type) => Some(instance_type),
|
||||||
|
|
@ -353,9 +343,9 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
NominalInstanceInner::ExactTuple(tuple) => {
|
NominalInstanceInner::ExactTuple(tuple) => {
|
||||||
Type::tuple(tuple.normalized_impl(db, visitor))
|
Type::tuple(tuple.normalized_impl(db, visitor))
|
||||||
}
|
}
|
||||||
NominalInstanceInner::NonTuple(class) => {
|
NominalInstanceInner::NonTuple(class) => Type::NominalInstance(NominalInstanceType(
|
||||||
Type::non_tuple_instance(db, class.normalized_impl(db, visitor))
|
NominalInstanceInner::NonTuple(class.normalized_impl(db, visitor)),
|
||||||
}
|
)),
|
||||||
NominalInstanceInner::Object => Type::object(),
|
NominalInstanceInner::Object => Type::object(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -488,10 +478,11 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
NominalInstanceInner::ExactTuple(tuple) => {
|
NominalInstanceInner::ExactTuple(tuple) => {
|
||||||
Type::tuple(tuple.apply_type_mapping_impl(db, type_mapping, tcx, visitor))
|
Type::tuple(tuple.apply_type_mapping_impl(db, type_mapping, tcx, visitor))
|
||||||
}
|
}
|
||||||
NominalInstanceInner::NonTuple(class) => Type::non_tuple_instance(
|
NominalInstanceInner::NonTuple(class) => {
|
||||||
db,
|
Type::NominalInstance(NominalInstanceType(NominalInstanceInner::NonTuple(
|
||||||
class.apply_type_mapping_impl(db, type_mapping, tcx, visitor),
|
class.apply_type_mapping_impl(db, type_mapping, tcx, visitor),
|
||||||
),
|
)))
|
||||||
|
}
|
||||||
NominalInstanceInner::Object => Type::object(),
|
NominalInstanceInner::Object => Type::object(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue