[red-knot] Add AlwaysTruthy and AlwaysFalsy to knot_extensions (#15437)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
@@ -94,6 +94,36 @@ reveal_type(C.__mro__)
|
||||
u: Unknown[str]
|
||||
```
|
||||
|
||||
### `AlwaysTruthy` and `AlwaysFalsy`
|
||||
|
||||
`AlwaysTruthy` and `AlwaysFalsy` represent the sets of all possible objects whose truthiness is
|
||||
always truthy or falsy, respectively.
|
||||
|
||||
They do not accept any type arguments.
|
||||
|
||||
```py
|
||||
from typing_extensions import Literal
|
||||
|
||||
from knot_extensions import AlwaysFalsy, AlwaysTruthy, is_subtype_of, static_assert
|
||||
|
||||
static_assert(is_subtype_of(Literal[True], AlwaysTruthy))
|
||||
static_assert(is_subtype_of(Literal[False], AlwaysFalsy))
|
||||
|
||||
static_assert(not is_subtype_of(int, AlwaysFalsy))
|
||||
static_assert(not is_subtype_of(str, AlwaysFalsy))
|
||||
|
||||
def _(t: AlwaysTruthy, f: AlwaysFalsy):
|
||||
reveal_type(t) # revealed: AlwaysTruthy
|
||||
reveal_type(f) # revealed: AlwaysFalsy
|
||||
|
||||
def f(
|
||||
a: AlwaysTruthy[int], # error: [invalid-type-form]
|
||||
b: AlwaysFalsy[str], # error: [invalid-type-form]
|
||||
):
|
||||
reveal_type(a) # revealed: Unknown
|
||||
reveal_type(b) # revealed: Unknown
|
||||
```
|
||||
|
||||
## Static assertions
|
||||
|
||||
### Basics
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user