Skip to content

Commit 00855a0

Browse files
committed
Add Type::KnownInstance
1 parent 515322b commit 00855a0

File tree

14 files changed

+776
-739
lines changed

14 files changed

+776
-739
lines changed

crates/ty_python_semantic/src/symbol.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ fn widen_type_for_undeclared_public_symbol<'db>(
11311131
// such.
11321132
let is_known_instance = inferred
11331133
.ignore_possibly_unbound()
1134-
.is_some_and(|ty| matches!(ty, Type::KnownInstance(_)));
1134+
.is_some_and(|ty| matches!(ty, Type::SpecialForm(_) | Type::KnownInstance(_)));
11351135

11361136
if is_considered_non_modifiable || is_known_instance {
11371137
inferred

crates/ty_python_semantic/src/types.rs

Lines changed: 241 additions & 94 deletions
Large diffs are not rendered by default.

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use crate::types::generics::{Specialization, SpecializationBuilder, Specializati
2121
use crate::types::signatures::{Parameter, ParameterForm};
2222
use crate::types::{
2323
BoundMethodType, DataclassParams, DataclassTransformerParams, FunctionDecorators, FunctionType,
24-
KnownClass, KnownFunction, MethodWrapperKind, PropertyInstanceType, SpecialForm, TupleType,
25-
TypeMapping, UnionType, WrapperDescriptorKind, todo_type,
24+
KnownClass, KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType,
25+
SpecialFormType, TupleType, TypeMapping, UnionType, WrapperDescriptorKind, todo_type,
2626
};
2727
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
2828
use ruff_python_ast as ast;
@@ -314,7 +314,9 @@ impl<'db> Bindings<'db> {
314314
}
315315
[
316316
Some(Type::PropertyInstance(property)),
317-
Some(Type::KnownInstance(SpecialForm::TypeAliasType(type_alias))),
317+
Some(Type::KnownInstance(KnownInstanceType::TypeAliasType(
318+
type_alias,
319+
))),
318320
..,
319321
] if property.getter(db).is_some_and(|getter| {
320322
getter
@@ -327,7 +329,7 @@ impl<'db> Bindings<'db> {
327329
}
328330
[
329331
Some(Type::PropertyInstance(property)),
330-
Some(Type::KnownInstance(SpecialForm::TypeVar(typevar))),
332+
Some(Type::KnownInstance(KnownInstanceType::TypeVar(typevar))),
331333
..,
332334
] => {
333335
match property
@@ -913,7 +915,7 @@ impl<'db> Bindings<'db> {
913915
_ => {}
914916
},
915917

916-
Type::KnownInstance(SpecialForm::TypedDict) => {
918+
Type::SpecialForm(SpecialFormType::TypedDict) => {
917919
overload.set_return_type(todo_type!("TypedDict"));
918920
}
919921

crates/ty_python_semantic/src/types/class.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use crate::semantic_index::definition::Definition;
1111
use crate::types::generics::{GenericContext, Specialization};
1212
use crate::types::signatures::{Parameter, Parameters};
1313
use crate::types::{
14-
CallableType, DataclassParams, DataclassTransformerParams, Signature, SpecialForm, TypeMapping,
15-
TypeVarInstance,
14+
CallableType, DataclassParams, DataclassTransformerParams, KnownInstanceType, Signature,
15+
TypeMapping, TypeVarInstance,
1616
};
1717
use crate::{
1818
Db, FxOrderSet, KnownModule, Program,
@@ -593,7 +593,8 @@ impl<'db> ClassLiteral<'db> {
593593
pub(crate) fn legacy_generic_context(self, db: &'db dyn Db) -> Option<GenericContext<'db>> {
594594
self.explicit_bases(db).iter().find_map(|base| match base {
595595
Type::KnownInstance(
596-
SpecialForm::Generic(generic_context) | SpecialForm::Protocol(generic_context),
596+
KnownInstanceType::Generic(generic_context)
597+
| KnownInstanceType::Protocol(generic_context),
597598
) => *generic_context,
598599
_ => None,
599600
})
@@ -746,7 +747,7 @@ impl<'db> ClassLiteral<'db> {
746747
.iter()
747748
.rev()
748749
.take(3)
749-
.any(|base| matches!(base, Type::KnownInstance(SpecialForm::Protocol(_))))
750+
.any(|base| matches!(base, Type::KnownInstance(KnownInstanceType::Protocol(_))))
750751
})
751752
}
752753

crates/ty_python_semantic/src/types/class_base.rs

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::Db;
22
use crate::types::generics::Specialization;
33
use crate::types::{
4-
ClassType, DynamicType, KnownClass, MroError, MroIterator, SpecialForm, Type, TypeMapping,
5-
todo_type,
4+
ClassType, DynamicType, KnownClass, KnownInstanceType, MroError, MroIterator, SpecialFormType,
5+
Type, TypeMapping, todo_type,
66
};
77

88
/// Enumeration of the possible kinds of types we allow in class bases.
@@ -147,66 +147,78 @@ impl<'db> ClassBase<'db> {
147147
| Type::ProtocolInstance(_)
148148
| Type::AlwaysFalsy
149149
| Type::AlwaysTruthy => None,
150+
150151
Type::KnownInstance(known_instance) => match known_instance {
151-
SpecialForm::TypeVar(_)
152-
| SpecialForm::TypeAliasType(_)
153-
| SpecialForm::Annotated
154-
| SpecialForm::Literal
155-
| SpecialForm::LiteralString
156-
| SpecialForm::Union
157-
| SpecialForm::NoReturn
158-
| SpecialForm::Never
159-
| SpecialForm::Final
160-
| SpecialForm::NotRequired
161-
| SpecialForm::TypeGuard
162-
| SpecialForm::TypeIs
163-
| SpecialForm::TypingSelf
164-
| SpecialForm::Unpack
165-
| SpecialForm::ClassVar
166-
| SpecialForm::Concatenate
167-
| SpecialForm::Required
168-
| SpecialForm::TypeAlias
169-
| SpecialForm::ReadOnly
170-
| SpecialForm::Optional
171-
| SpecialForm::Not
172-
| SpecialForm::Intersection
173-
| SpecialForm::TypeOf
174-
| SpecialForm::CallableTypeOf
175-
| SpecialForm::AlwaysTruthy
176-
| SpecialForm::AlwaysFalsy => None,
177-
SpecialForm::Unknown => Some(Self::unknown()),
152+
KnownInstanceType::Generic(_) => Some(Self::Generic),
153+
KnownInstanceType::Protocol(_) => Some(Self::Protocol),
154+
KnownInstanceType::TypeAliasType(_) | KnownInstanceType::TypeVar(_) => None,
155+
},
156+
157+
Type::SpecialForm(special_form) => match special_form {
158+
SpecialFormType::Annotated
159+
| SpecialFormType::Literal
160+
| SpecialFormType::LiteralString
161+
| SpecialFormType::Union
162+
| SpecialFormType::NoReturn
163+
| SpecialFormType::Never
164+
| SpecialFormType::Final
165+
| SpecialFormType::NotRequired
166+
| SpecialFormType::TypeGuard
167+
| SpecialFormType::TypeIs
168+
| SpecialFormType::TypingSelf
169+
| SpecialFormType::Unpack
170+
| SpecialFormType::ClassVar
171+
| SpecialFormType::Concatenate
172+
| SpecialFormType::Required
173+
| SpecialFormType::TypeAlias
174+
| SpecialFormType::ReadOnly
175+
| SpecialFormType::Optional
176+
| SpecialFormType::Not
177+
| SpecialFormType::Intersection
178+
| SpecialFormType::TypeOf
179+
| SpecialFormType::CallableTypeOf
180+
| SpecialFormType::AlwaysTruthy
181+
| SpecialFormType::AlwaysFalsy => None,
182+
183+
SpecialFormType::Unknown => Some(Self::unknown()),
178184
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
179-
SpecialForm::Dict => Self::try_from_type(db, KnownClass::Dict.to_class_literal(db)),
180-
SpecialForm::List => Self::try_from_type(db, KnownClass::List.to_class_literal(db)),
181-
SpecialForm::Type => Self::try_from_type(db, KnownClass::Type.to_class_literal(db)),
182-
SpecialForm::Tuple => {
185+
SpecialFormType::Dict => {
186+
Self::try_from_type(db, KnownClass::Dict.to_class_literal(db))
187+
}
188+
SpecialFormType::List => {
189+
Self::try_from_type(db, KnownClass::List.to_class_literal(db))
190+
}
191+
SpecialFormType::Type => {
192+
Self::try_from_type(db, KnownClass::Type.to_class_literal(db))
193+
}
194+
SpecialFormType::Tuple => {
183195
Self::try_from_type(db, KnownClass::Tuple.to_class_literal(db))
184196
}
185-
SpecialForm::Set => Self::try_from_type(db, KnownClass::Set.to_class_literal(db)),
186-
SpecialForm::FrozenSet => {
197+
SpecialFormType::Set => {
198+
Self::try_from_type(db, KnownClass::Set.to_class_literal(db))
199+
}
200+
SpecialFormType::FrozenSet => {
187201
Self::try_from_type(db, KnownClass::FrozenSet.to_class_literal(db))
188202
}
189-
SpecialForm::ChainMap => {
203+
SpecialFormType::ChainMap => {
190204
Self::try_from_type(db, KnownClass::ChainMap.to_class_literal(db))
191205
}
192-
SpecialForm::Counter => {
206+
SpecialFormType::Counter => {
193207
Self::try_from_type(db, KnownClass::Counter.to_class_literal(db))
194208
}
195-
SpecialForm::DefaultDict => {
209+
SpecialFormType::DefaultDict => {
196210
Self::try_from_type(db, KnownClass::DefaultDict.to_class_literal(db))
197211
}
198-
SpecialForm::Deque => {
212+
SpecialFormType::Deque => {
199213
Self::try_from_type(db, KnownClass::Deque.to_class_literal(db))
200214
}
201-
SpecialForm::OrderedDict => {
215+
SpecialFormType::OrderedDict => {
202216
Self::try_from_type(db, KnownClass::OrderedDict.to_class_literal(db))
203217
}
204-
SpecialForm::TypedDict => Self::try_from_type(db, todo_type!("TypedDict")),
205-
SpecialForm::Callable => {
218+
SpecialFormType::TypedDict => Self::try_from_type(db, todo_type!("TypedDict")),
219+
SpecialFormType::Callable => {
206220
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
207221
}
208-
SpecialForm::Protocol(_) => Some(ClassBase::Protocol),
209-
SpecialForm::Generic(_) => Some(ClassBase::Generic),
210222
},
211223
}
212224
}
@@ -280,8 +292,8 @@ impl<'db> From<ClassBase<'db>> for Type<'db> {
280292
match value {
281293
ClassBase::Dynamic(dynamic) => Type::Dynamic(dynamic),
282294
ClassBase::Class(class) => class.into(),
283-
ClassBase::Protocol => Type::KnownInstance(SpecialForm::Protocol(None)),
284-
ClassBase::Generic => Type::KnownInstance(SpecialForm::Generic(None)),
295+
ClassBase::Protocol => Type::KnownInstance(KnownInstanceType::Protocol(None)),
296+
ClassBase::Generic => Type::KnownInstance(KnownInstanceType::Generic(None)),
285297
}
286298
}
287299
}

crates/ty_python_semantic/src/types/diagnostic.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use super::{
55
CallArgumentTypes, CallDunderError, ClassBase, ClassLiteral, KnownClass,
66
add_inferred_python_version_hint_to_diagnostic,
77
};
8-
use crate::db::Db;
98
use crate::declare_lint;
109
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
1110
use crate::suppression::FileSuppressionId;
@@ -15,7 +14,7 @@ use crate::types::string_annotation::{
1514
IMPLICIT_CONCATENATED_STRING_TYPE_ANNOTATION, INVALID_SYNTAX_IN_FORWARD_ANNOTATION,
1615
RAW_STRING_TYPE_ANNOTATION,
1716
};
18-
use crate::types::{KnownFunction, SpecialForm, Type, protocol_class::ProtocolClassLiteral};
17+
use crate::types::{KnownFunction, SpecialFormType, Type, protocol_class::ProtocolClassLiteral};
1918
use itertools::Itertools;
2019
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
2120
use ruff_python_ast::{self as ast, AnyNodeRef};
@@ -1823,7 +1822,6 @@ pub(crate) fn report_base_with_incompatible_slots(context: &InferContext, node:
18231822
}
18241823

18251824
pub(crate) fn report_invalid_arguments_to_annotated(
1826-
db: &dyn Db,
18271825
context: &InferContext,
18281826
subscript: &ast::ExprSubscript,
18291827
) {
@@ -1833,7 +1831,7 @@ pub(crate) fn report_invalid_arguments_to_annotated(
18331831
builder.into_diagnostic(format_args!(
18341832
"Special form `{}` expected at least 2 arguments \
18351833
(one type and at least one metadata element)",
1836-
SpecialForm::Annotated.repr(db)
1834+
SpecialFormType::Annotated
18371835
));
18381836
}
18391837

@@ -1873,7 +1871,6 @@ pub(crate) fn report_bad_argument_to_get_protocol_members(
18731871
}
18741872

18751873
pub(crate) fn report_invalid_arguments_to_callable(
1876-
db: &dyn Db,
18771874
context: &InferContext,
18781875
subscript: &ast::ExprSubscript,
18791876
) {
@@ -1882,7 +1879,7 @@ pub(crate) fn report_invalid_arguments_to_callable(
18821879
};
18831880
builder.into_diagnostic(format_args!(
18841881
"Special form `{}` expected exactly two arguments (parameter types and return type)",
1885-
SpecialForm::Callable.repr(db)
1882+
SpecialFormType::Callable
18861883
));
18871884
}
18881885

crates/ty_python_semantic/src/types/display.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl Display for DisplayRepresentation<'_> {
110110
SubclassOfInner::Class(class) => write!(f, "type[{}]", class.name(self.db)),
111111
SubclassOfInner::Dynamic(dynamic) => write!(f, "type[{dynamic}]"),
112112
},
113+
Type::SpecialForm(special_form) => special_form.fmt(f),
113114
Type::KnownInstance(known_instance) => known_instance.repr(self.db).fmt(f),
114115
Type::FunctionLiteral(function) => {
115116
let signature = function.signature(self.db);

crates/ty_python_semantic/src/types/generics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::types::class_base::ClassBase;
99
use crate::types::instance::{NominalInstanceType, Protocol, ProtocolInstanceType};
1010
use crate::types::signatures::{Parameter, Parameters, Signature};
1111
use crate::types::{
12-
SpecialForm, Type, TypeMapping, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarVariance,
13-
UnionType, declaration_type, todo_type,
12+
KnownInstanceType, Type, TypeMapping, TypeVarBoundOrConstraints, TypeVarInstance,
13+
TypeVarVariance, UnionType, declaration_type, todo_type,
1414
};
1515
use crate::{Db, FxOrderSet};
1616

@@ -51,7 +51,7 @@ impl<'db> GenericContext<'db> {
5151
match type_param_node {
5252
ast::TypeParam::TypeVar(node) => {
5353
let definition = index.expect_single_definition(node);
54-
let Type::KnownInstance(SpecialForm::TypeVar(typevar)) =
54+
let Type::KnownInstance(KnownInstanceType::TypeVar(typevar)) =
5555
declaration_type(db, definition).inner_type()
5656
else {
5757
return None;

0 commit comments

Comments
 (0)