mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
More cleanup, clarification
This commit is contained in:
parent
0b99dfdb90
commit
2a2e03c3b9
3 changed files with 26 additions and 29 deletions
|
@ -376,8 +376,8 @@ pub enum ClassType<'db> {
|
||||||
|
|
||||||
#[salsa::tracked]
|
#[salsa::tracked]
|
||||||
impl<'db> ClassType<'db> {
|
impl<'db> ClassType<'db> {
|
||||||
pub(super) const fn is_not_generic(self) -> bool {
|
pub(super) const fn is_generic(self) -> bool {
|
||||||
matches!(self, Self::NonGeneric(_))
|
matches!(self, Self::Generic(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) const fn into_generic_alias(self) -> Option<GenericAlias<'db>> {
|
pub(super) const fn into_generic_alias(self) -> Option<GenericAlias<'db>> {
|
||||||
|
|
|
@ -5954,7 +5954,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
// but constructor calls to `tuple[int]`, `tuple[int, ...]`, `tuple[int, *tuple[str, ...]]` (etc.)
|
// but constructor calls to `tuple[int]`, `tuple[int, ...]`, `tuple[int, *tuple[str, ...]]` (etc.)
|
||||||
// are handled by the default constructor-call logic (we synthesize a `__new__` method for them
|
// are handled by the default constructor-call logic (we synthesize a `__new__` method for them
|
||||||
// in `ClassType::own_class_member()`).
|
// in `ClassType::own_class_member()`).
|
||||||
class.is_known(self.db(), KnownClass::Tuple) && class.is_not_generic()
|
class.is_known(self.db(), KnownClass::Tuple) && !class.is_generic()
|
||||||
);
|
);
|
||||||
|
|
||||||
// temporary special-casing for all subclasses of `enum.Enum`
|
// temporary special-casing for all subclasses of `enum.Enum`
|
||||||
|
|
|
@ -27,16 +27,16 @@ use crate::types::infer::nearest_enclosing_class;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, ClassType,
|
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, ClassType,
|
||||||
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsEquivalentVisitor, KnownClass,
|
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsEquivalentVisitor, KnownClass,
|
||||||
MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation, TypeVarKind,
|
MaterializationKind, NormalizedVisitor, TypeMapping, TypeRelation, VarianceInferable,
|
||||||
VarianceInferable, todo_type,
|
todo_type,
|
||||||
};
|
};
|
||||||
use crate::{Db, FxOrderSet};
|
use crate::{Db, FxOrderSet};
|
||||||
use ruff_python_ast::{self as ast, name::Name};
|
use ruff_python_ast::{self as ast, name::Name};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct MethodInformation<'db> {
|
struct MethodInformation<'db> {
|
||||||
method_type: FunctionType<'db>,
|
method: FunctionType<'db>,
|
||||||
class_type: ClassType<'db>,
|
class: ClassType<'db>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_method_information<'db>(
|
fn infer_method_information<'db>(
|
||||||
|
@ -50,7 +50,7 @@ fn infer_method_information<'db>(
|
||||||
let class_scope = index.scope(class_scope_id.file_scope_id(db));
|
let class_scope = index.scope(class_scope_id.file_scope_id(db));
|
||||||
let class_node = class_scope.node().as_class()?;
|
let class_node = class_scope.node().as_class()?;
|
||||||
|
|
||||||
let method_type = infer_definition_types(db, definition)
|
let method = infer_definition_types(db, definition)
|
||||||
.declaration_type(definition)
|
.declaration_type(definition)
|
||||||
.inner_type()
|
.inner_type()
|
||||||
.into_function_literal()?;
|
.into_function_literal()?;
|
||||||
|
@ -59,12 +59,9 @@ fn infer_method_information<'db>(
|
||||||
let class_literal = infer_definition_types(db, class_def)
|
let class_literal = infer_definition_types(db, class_def)
|
||||||
.declaration_type(class_def)
|
.declaration_type(class_def)
|
||||||
.inner_type();
|
.inner_type();
|
||||||
let class_type = class_literal.to_class_type(db)?;
|
let class = class_literal.to_class_type(db)?;
|
||||||
|
|
||||||
Some(MethodInformation {
|
Some(MethodInformation { method, class })
|
||||||
method_type,
|
|
||||||
class_type,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The signature of a single callable. If the callable is overloaded, there is a separate
|
/// The signature of a single callable. If the callable is overloaded, there is a separate
|
||||||
|
@ -1260,16 +1257,12 @@ impl<'db> Parameters<'db> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let method_info = infer_method_information(db, definition);
|
let method_info = infer_method_information(db, definition);
|
||||||
let is_classmethod = method_info.is_some_and(|f| f.method_type.is_classmethod(db));
|
let is_static_or_classmethod = method_info
|
||||||
let is_staticmethod = method_info.is_some_and(|f| f.method_type.is_staticmethod(db));
|
.is_some_and(|f| f.method.is_staticmethod(db) || f.method.is_classmethod(db));
|
||||||
|
|
||||||
let positional_or_keyword = pos_or_keyword_iter.map(|arg| {
|
let positional_or_keyword = pos_or_keyword_iter.map(|arg| {
|
||||||
if let Some(MethodInformation {
|
if let Some(MethodInformation { method, class }) = method_info
|
||||||
method_type: method,
|
&& !is_static_or_classmethod
|
||||||
class_type: class,
|
|
||||||
}) = method_info
|
|
||||||
&& !is_staticmethod
|
|
||||||
&& !is_classmethod
|
|
||||||
&& arg.parameter.annotation().is_none()
|
&& arg.parameter.annotation().is_none()
|
||||||
&& parameters.index(arg.name().id()) == Some(0)
|
&& parameters.index(arg.name().id()) == Some(0)
|
||||||
{
|
{
|
||||||
|
@ -1279,18 +1272,16 @@ impl<'db> Parameters<'db> {
|
||||||
context
|
context
|
||||||
.variables(db)
|
.variables(db)
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.typevar(db).kind(db) == TypeVarKind::TypingSelf);
|
.any(|v| v.typevar(db).is_self(db))
|
||||||
true
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let implicit_annotation = if !method_has_self_in_generic_context
|
|
||||||
&& class.is_not_generic()
|
let inferred_annotation = if method_has_self_in_generic_context
|
||||||
&& !class.known(db).is_some_and(KnownClass::is_fallback_class)
|
|| class.is_generic()
|
||||||
|
|| class.known(db).is_some_and(KnownClass::is_fallback_class)
|
||||||
{
|
{
|
||||||
Type::instance(db, class)
|
|
||||||
} else {
|
|
||||||
let scope_id = definition.scope(db);
|
let scope_id = definition.scope(db);
|
||||||
let typevar_binding_context = Some(definition);
|
let typevar_binding_context = Some(definition);
|
||||||
let index = semantic_index(db, scope_id.file(db));
|
let index = semantic_index(db, scope_id.file(db));
|
||||||
|
@ -1304,9 +1295,15 @@ impl<'db> Parameters<'db> {
|
||||||
definition,
|
definition,
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
// For methods of non-generic classes that are not otherwise generic (e.g. return `Self` or
|
||||||
|
// have additional type parameters), the implicit `Self` type of the `self` parameter would
|
||||||
|
// be the only type variable, so we can just use the class directly.
|
||||||
|
Type::instance(db, class)
|
||||||
};
|
};
|
||||||
|
|
||||||
Parameter {
|
Parameter {
|
||||||
annotated_type: Some(implicit_annotation),
|
annotated_type: Some(inferred_annotation),
|
||||||
inferred_annotation: true,
|
inferred_annotation: true,
|
||||||
kind: ParameterKind::PositionalOrKeyword {
|
kind: ParameterKind::PositionalOrKeyword {
|
||||||
name: arg.parameter.name.id.clone(),
|
name: arg.parameter.name.id.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue