[red-knot] Add AlwaysTruthy and AlwaysFalsy to knot_extensions (#15437)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
InSync
2025-01-13 00:00:57 +07:00
committed by GitHub
parent 06b7f4495e
commit d1666fbbee
5 changed files with 63 additions and 6 deletions

View File

@@ -2292,6 +2292,8 @@ impl<'db> Type<'db> {
fallback_type: Type::unknown(),
}),
Type::KnownInstance(KnownInstanceType::Unknown) => Ok(Type::unknown()),
Type::KnownInstance(KnownInstanceType::AlwaysTruthy) => Ok(Type::AlwaysTruthy),
Type::KnownInstance(KnownInstanceType::AlwaysFalsy) => Ok(Type::AlwaysFalsy),
_ => Ok(todo_type!(
"Unsupported or invalid type in a type expression"
)),
@@ -2827,6 +2829,10 @@ pub enum KnownInstanceType<'db> {
TypeAliasType(TypeAliasType<'db>),
/// The symbol `knot_extensions.Unknown`
Unknown,
/// The symbol `knot_extensions.AlwaysTruthy`
AlwaysTruthy,
/// The symbol `knot_extensions.AlwaysFalsy`
AlwaysFalsy,
/// The symbol `knot_extensions.Not`
Not,
/// The symbol `knot_extensions.Intersection`
@@ -2888,6 +2894,8 @@ impl<'db> KnownInstanceType<'db> {
Self::OrderedDict => "OrderedDict",
Self::ReadOnly => "ReadOnly",
Self::Unknown => "Unknown",
Self::AlwaysTruthy => "AlwaysTruthy",
Self::AlwaysFalsy => "AlwaysFalsy",
Self::Not => "Not",
Self::Intersection => "Intersection",
Self::TypeOf => "TypeOf",
@@ -2931,6 +2939,8 @@ impl<'db> KnownInstanceType<'db> {
| Self::ReadOnly
| Self::TypeAliasType(_)
| Self::Unknown
| Self::AlwaysTruthy
| Self::AlwaysFalsy
| Self::Not
| Self::Intersection
| Self::TypeOf => Truthiness::AlwaysTrue,
@@ -2974,6 +2984,8 @@ impl<'db> KnownInstanceType<'db> {
Self::TypeVar(typevar) => typevar.name(db),
Self::TypeAliasType(_) => "typing.TypeAliasType",
Self::Unknown => "knot_extensions.Unknown",
Self::AlwaysTruthy => "knot_extensions.AlwaysTruthy",
Self::AlwaysFalsy => "knot_extensions.AlwaysFalsy",
Self::Not => "knot_extensions.Not",
Self::Intersection => "knot_extensions.Intersection",
Self::TypeOf => "knot_extensions.TypeOf",
@@ -3020,6 +3032,8 @@ impl<'db> KnownInstanceType<'db> {
Self::Not => KnownClass::SpecialForm,
Self::Intersection => KnownClass::SpecialForm,
Self::Unknown => KnownClass::Object,
Self::AlwaysTruthy => KnownClass::Object,
Self::AlwaysFalsy => KnownClass::Object,
}
}
@@ -3071,6 +3085,8 @@ impl<'db> KnownInstanceType<'db> {
"NotRequired" => Self::NotRequired,
"LiteralString" => Self::LiteralString,
"Unknown" => Self::Unknown,
"AlwaysTruthy" => Self::AlwaysTruthy,
"AlwaysFalsy" => Self::AlwaysFalsy,
"Not" => Self::Not,
"Intersection" => Self::Intersection,
"TypeOf" => Self::TypeOf,
@@ -3123,9 +3139,12 @@ impl<'db> KnownInstanceType<'db> {
| Self::TypeVar(_) => {
matches!(module, KnownModule::Typing | KnownModule::TypingExtensions)
}
Self::Unknown | Self::Not | Self::Intersection | Self::TypeOf => {
module.is_knot_extensions()
}
Self::Unknown
| Self::AlwaysTruthy
| Self::AlwaysFalsy
| Self::Not
| Self::Intersection
| Self::TypeOf => module.is_knot_extensions(),
}
}

View File

@@ -105,7 +105,9 @@ impl<'db> ClassBase<'db> {
| KnownInstanceType::Optional
| KnownInstanceType::Not
| KnownInstanceType::Intersection
| KnownInstanceType::TypeOf => None,
| KnownInstanceType::TypeOf
| KnownInstanceType::AlwaysTruthy
| KnownInstanceType::AlwaysFalsy => None,
KnownInstanceType::Unknown => Some(Self::unknown()),
KnownInstanceType::Any => Some(Self::any()),
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO

View File

@@ -4539,7 +4539,7 @@ impl<'db> TypeInferenceBuilder<'db> {
return dunder_getitem_method
.call(self.db(), &CallArguments::positional([value_ty, slice_ty]))
.return_ty_result( &self.context, value_node.into())
.return_ty_result(&self.context, value_node.into())
.unwrap_or_else(|err| {
self.context.report_lint(
&CALL_NON_CALLABLE,
@@ -5373,7 +5373,11 @@ impl<'db> TypeInferenceBuilder<'db> {
self.infer_type_expression(arguments_slice);
todo_type!("`Unpack[]` special form")
}
KnownInstanceType::NoReturn | KnownInstanceType::Never | KnownInstanceType::Any => {
KnownInstanceType::NoReturn
| KnownInstanceType::Never
| KnownInstanceType::Any
| KnownInstanceType::AlwaysTruthy
| KnownInstanceType::AlwaysFalsy => {
self.context.report_lint(
&INVALID_TYPE_FORM,
subscript.into(),