Handle explicit specialization before outputting lints
This commit is contained in:
@@ -13,8 +13,6 @@ class C[T]: ...
|
||||
A class that inherits from a generic class, and fills its type parameters with typevars, is generic:
|
||||
|
||||
```py
|
||||
# TODO: no error
|
||||
# error: [non-subscriptable]
|
||||
class D[U](C[U]): ...
|
||||
```
|
||||
|
||||
@@ -22,8 +20,6 @@ A class that inherits from a generic class, but fills its type parameters with c
|
||||
_not_ generic:
|
||||
|
||||
```py
|
||||
# TODO: no error
|
||||
# error: [non-subscriptable]
|
||||
class E(C[int]): ...
|
||||
```
|
||||
|
||||
@@ -65,9 +61,7 @@ The type parameter can be specified explicitly:
|
||||
class C[T]:
|
||||
x: T
|
||||
|
||||
# TODO: no error
|
||||
# TODO: revealed: C[int]
|
||||
# error: [non-subscriptable]
|
||||
reveal_type(C[int]()) # revealed: C
|
||||
```
|
||||
|
||||
@@ -131,16 +125,11 @@ propagate through:
|
||||
class Base[T]:
|
||||
x: T | None = None
|
||||
|
||||
# TODO: no error
|
||||
# error: [non-subscriptable]
|
||||
class Sub[U](Base[U]): ...
|
||||
|
||||
# TODO: no error
|
||||
# TODO: revealed: int | None
|
||||
# error: [non-subscriptable]
|
||||
reveal_type(Base[int].x) # revealed: T | None
|
||||
# TODO: revealed: int | None
|
||||
# error: [non-subscriptable]
|
||||
reveal_type(Sub[int].x) # revealed: T | None
|
||||
```
|
||||
|
||||
@@ -155,8 +144,6 @@ Here, `Sub` is not a generic class, since it fills its superclass's type paramet
|
||||
|
||||
```pyi
|
||||
class Base[T]: ...
|
||||
# TODO: no error
|
||||
# error: [non-subscriptable]
|
||||
class Sub(Base[Sub]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
@@ -169,8 +156,6 @@ A similar case can work in a non-stub file, if forward references are stringifie
|
||||
```py
|
||||
class Base[T]: ...
|
||||
|
||||
# TODO: no error
|
||||
# error: [non-subscriptable]
|
||||
class Sub(Base["Sub"]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
@@ -183,8 +168,6 @@ In a non-stub file, without stringified forward references, this raises a `NameE
|
||||
```py
|
||||
class Base[T]: ...
|
||||
|
||||
# TODO: the unresolved-reference error is correct, the non-subscriptable is not
|
||||
# error: [non-subscriptable]
|
||||
# error: [unresolved-reference]
|
||||
class Sub(Base[Sub]): ...
|
||||
```
|
||||
|
||||
@@ -8,8 +8,6 @@ In type stubs, classes can reference themselves in their base class definitions.
|
||||
```pyi
|
||||
class Foo[T]: ...
|
||||
|
||||
# TODO: actually is subscriptable
|
||||
# error: [non-subscriptable]
|
||||
class Bar(Foo[Bar]): ...
|
||||
|
||||
reveal_type(Bar) # revealed: Literal[Bar]
|
||||
|
||||
@@ -39,7 +39,7 @@ pub struct Class<'db> {
|
||||
#[return_ref]
|
||||
pub(crate) name: ast::name::Name,
|
||||
|
||||
generic_context: Option<GenericContext<'db>>,
|
||||
pub(crate) generic_context: Option<GenericContext<'db>>,
|
||||
body_scope: ScopeId<'db>,
|
||||
|
||||
pub(crate) known: Option<KnownClass>,
|
||||
|
||||
@@ -64,6 +64,7 @@ use crate::symbol::{
|
||||
typing_extensions_symbol, Boundness, LookupError,
|
||||
};
|
||||
use crate::types::call::{Argument, Bindings, CallArgumentTypes, CallArguments, CallError};
|
||||
use crate::types::class::{ClassLiteralType, MetaclassErrorKind};
|
||||
use crate::types::diagnostic::{
|
||||
report_implicit_return_type, report_invalid_arguments_to_annotated,
|
||||
report_invalid_arguments_to_callable, report_invalid_assignment,
|
||||
@@ -80,12 +81,11 @@ use crate::types::generics::GenericContext;
|
||||
use crate::types::mro::MroErrorKind;
|
||||
use crate::types::unpacker::{UnpackResult, Unpacker};
|
||||
use crate::types::{
|
||||
class::MetaclassErrorKind, todo_type, Class, DynamicType, FunctionType, InstanceType,
|
||||
IntersectionBuilder, IntersectionType, KnownClass, KnownFunction, KnownInstanceType,
|
||||
MetaclassCandidate, Parameter, ParameterForm, Parameters, SliceLiteralType, SubclassOfType,
|
||||
Symbol, SymbolAndQualifiers, Truthiness, TupleType, Type, TypeAliasType, TypeAndQualifiers,
|
||||
TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints, TypeVarInstance, UnionBuilder,
|
||||
UnionType,
|
||||
todo_type, Class, DynamicType, FunctionType, InstanceType, IntersectionBuilder,
|
||||
IntersectionType, KnownClass, KnownFunction, KnownInstanceType, MetaclassCandidate, Parameter,
|
||||
ParameterForm, Parameters, SliceLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers,
|
||||
Truthiness, TupleType, Type, TypeAliasType, TypeAndQualifiers, TypeArrayDisplay,
|
||||
TypeQualifiers, TypeVarBoundOrConstraints, TypeVarInstance, UnionBuilder, UnionType,
|
||||
};
|
||||
use crate::types::{CallableType, GeneralCallableType, Signature};
|
||||
use crate::unpack::Unpack;
|
||||
@@ -5795,9 +5795,16 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
if matches!(value_ty, Type::ClassLiteral(class_literal) if class_literal.class().is_known(self.db(), KnownClass::Type))
|
||||
{
|
||||
return KnownClass::GenericAlias.to_instance(self.db());
|
||||
if let Type::ClassLiteral(ClassLiteralType { class }) = value_ty {
|
||||
if class.is_known(self.db(), KnownClass::Type) {
|
||||
return KnownClass::GenericAlias.to_instance(self.db());
|
||||
}
|
||||
|
||||
if class.generic_context(self.db()).is_some() {
|
||||
// TODO: specialize the generic class using these explicit type
|
||||
// variable assignments
|
||||
return value_ty;
|
||||
}
|
||||
}
|
||||
|
||||
report_non_subscriptable(
|
||||
@@ -5820,6 +5827,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
// TODO: proper support for generic classes
|
||||
// For now, just infer `Sequence`, if we see something like `Sequence[str]`. This allows us
|
||||
// to look up attributes on generic base classes, even if we don't understand generics yet.
|
||||
// Note that this isn't handled by the clause up above for generic classes
|
||||
// that use legacy type variables and an explicit `Generic` base class.
|
||||
// Once we handle legacy typevars, this special case will be removed in
|
||||
// favor of the specialization logic above.
|
||||
value_ty
|
||||
}
|
||||
_ => Type::unknown(),
|
||||
|
||||
Reference in New Issue
Block a user