mirror of https://github.com/astral-sh/ruff
Don't display the implicit typing.Self type
This commit is contained in:
parent
8dd183e55c
commit
f34b6d8245
|
|
@ -42,7 +42,6 @@ class Shape:
|
||||||
|
|
||||||
reveal_type(Shape().nested_type()) # revealed: list[Shape]
|
reveal_type(Shape().nested_type()) # revealed: list[Shape]
|
||||||
reveal_type(Shape().nested_func()) # revealed: Shape
|
reveal_type(Shape().nested_func()) # revealed: Shape
|
||||||
reveal_type(Shape().implicit_self()) # revealed: Shape
|
|
||||||
|
|
||||||
class Circle(Shape):
|
class Circle(Shape):
|
||||||
def set_scale(self: Self, scale: float) -> Self:
|
def set_scale(self: Self, scale: float) -> Self:
|
||||||
|
|
@ -56,6 +55,37 @@ class Outer:
|
||||||
return self
|
return self
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Detection of Self
|
||||||
|
|
||||||
|
The first argument in method is assumed to have type `typing.Self`.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.11"
|
||||||
|
```
|
||||||
|
|
||||||
|
```py
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
class A:
|
||||||
|
def implicit_self(self) -> Self:
|
||||||
|
# TODO: first argument in a method should be considered as "typing.Self"
|
||||||
|
reveal_type(self) # revealed: Unknown
|
||||||
|
return self
|
||||||
|
|
||||||
|
def foo(self) -> int:
|
||||||
|
def first_arg_is_not_self(a: int) -> int:
|
||||||
|
return a
|
||||||
|
return first_arg_is_not_self(1)
|
||||||
|
# TODO: Make sure cls is not considered as "typing.Self". Don't know how to test this
|
||||||
|
@classmethod
|
||||||
|
def bar(cls) -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
reveal_type(A().implicit_self()) # revealed: A
|
||||||
|
reveal_type(A.implicit_self) # revealed: def implicit_self(self) -> Self
|
||||||
|
```
|
||||||
|
|
||||||
## typing_extensions
|
## typing_extensions
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,9 @@ reveal_type(bound_method(1)) # revealed: str
|
||||||
When we call the function object itself, we need to pass the `instance` explicitly:
|
When we call the function object itself, we need to pass the `instance` explicitly:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
C.f(1) # error: [missing-argument]
|
# error: [invalid-argument-type]
|
||||||
|
# error: [missing-argument]
|
||||||
|
C.f(1)
|
||||||
|
|
||||||
reveal_type(C.f(C(), 1)) # revealed: str
|
reveal_type(C.f(C(), 1)) # revealed: str
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1150,11 +1150,13 @@ impl Display for DisplayParameter<'_> {
|
||||||
if let Some(name) = self.param.display_name() {
|
if let Some(name) = self.param.display_name() {
|
||||||
f.write_str(&name)?;
|
f.write_str(&name)?;
|
||||||
if let Some(annotated_type) = self.param.annotated_type() {
|
if let Some(annotated_type) = self.param.annotated_type() {
|
||||||
write!(
|
if !self.param.type_inffered() {
|
||||||
f,
|
write!(
|
||||||
": {}",
|
f,
|
||||||
annotated_type.display_with(self.db, self.settings)
|
": {}",
|
||||||
)?;
|
annotated_type.display_with(self.db, self.settings)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Default value can only be specified if `name` is given.
|
// Default value can only be specified if `name` is given.
|
||||||
if let Some(default_ty) = self.param.default_type() {
|
if let Some(default_ty) = self.param.default_type() {
|
||||||
|
|
@ -1167,7 +1169,9 @@ impl Display for DisplayParameter<'_> {
|
||||||
} else if let Some(ty) = self.param.annotated_type() {
|
} else if let Some(ty) = self.param.annotated_type() {
|
||||||
// This case is specifically for the `Callable` signature where name and default value
|
// This case is specifically for the `Callable` signature where name and default value
|
||||||
// cannot be provided.
|
// cannot be provided.
|
||||||
ty.display_with(self.db, self.settings).fmt(f)?;
|
if !self.param.type_inffered() {
|
||||||
|
ty.display_with(self.db, self.settings).fmt(f)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use smallvec::{SmallVec, smallvec_inline};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
DynamicType, FunctionDecorators, KnownInstanceType, Type, definition_expression_type,
|
DynamicType, FunctionDecorators, KnownInstanceType, Type, definition_expression_type,
|
||||||
infer_definition_types, nearest_enclosing_class, semantic_index,
|
infer_definition_types, semantic_index,
|
||||||
};
|
};
|
||||||
use super::{DynamicType, Type, TypeVarVariance, definition_expression_type};
|
use super::{DynamicType, Type, TypeVarVariance, definition_expression_type};
|
||||||
use super::{DynamicType, Type, definition_expression_type};
|
use super::{DynamicType, Type, definition_expression_type};
|
||||||
|
|
@ -1179,12 +1179,14 @@ impl<'db> Parameters<'db> {
|
||||||
let function_is_method = if matches!(definition.kind(db), DefinitionKind::Function(_)) {
|
let function_is_method = if matches!(definition.kind(db), DefinitionKind::Function(_)) {
|
||||||
let scope = definition.scope(db);
|
let scope = definition.scope(db);
|
||||||
let index = semantic_index(db, scope.file(db));
|
let index = semantic_index(db, scope.file(db));
|
||||||
nearest_enclosing_class(db, index, scope).is_some()
|
let current_scope = index.scope(scope.file_scope_id(db));
|
||||||
|
// class_context_of_current_method(db, index, scope).is_some()
|
||||||
|
current_scope.kind().is_class()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
let classmethod = if let DefinitionKind::Function(f) = definition.kind(db) {
|
let classmethod = if let DefinitionKind::Function(f) = definition.kind(db) {
|
||||||
if f.name.id() == "__new__" {
|
if matches!(f.name.id().as_str(), "__new__" | "__class_getitem__") {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let result = infer_definition_types(db, definition);
|
let result = infer_definition_types(db, definition);
|
||||||
|
|
@ -1198,11 +1200,12 @@ impl<'db> Parameters<'db> {
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let positional_or_keyword = args.iter().enumerate().map(|(index, arg)| {
|
let positional_or_keyword = args.iter().enumerate().map(|(index, arg)| {
|
||||||
if index == 0
|
if index == 0
|
||||||
&& function_is_method
|
&& function_is_method
|
||||||
&& arg.parameter.annotation().is_none()
|
&& arg.parameter.annotation().is_none()
|
||||||
// TODO: Handle type of cls
|
// TODO: Handle case when cls is not annotated
|
||||||
&& !classmethod
|
&& !classmethod
|
||||||
{
|
{
|
||||||
let implicit_annotation = Type::KnownInstance(KnownInstanceType::TypingSelf)
|
let implicit_annotation = Type::KnownInstance(KnownInstanceType::TypingSelf)
|
||||||
|
|
@ -1210,6 +1213,7 @@ impl<'db> Parameters<'db> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Parameter {
|
Parameter {
|
||||||
annotated_type: Some(implicit_annotation),
|
annotated_type: Some(implicit_annotation),
|
||||||
|
type_inffered: true,
|
||||||
kind: ParameterKind::PositionalOrKeyword {
|
kind: ParameterKind::PositionalOrKeyword {
|
||||||
name: arg.parameter.name.id.clone(),
|
name: arg.parameter.name.id.clone(),
|
||||||
default_type: default_type(arg),
|
default_type: default_type(arg),
|
||||||
|
|
@ -1383,6 +1387,10 @@ pub(crate) struct Parameter<'db> {
|
||||||
/// Annotated type of the parameter.
|
/// Annotated type of the parameter.
|
||||||
annotated_type: Option<Type<'db>>,
|
annotated_type: Option<Type<'db>>,
|
||||||
|
|
||||||
|
/// If the type of parameter was inferred e.g. the first argument of a method has type
|
||||||
|
/// `typing.Self`.
|
||||||
|
type_inffered: bool,
|
||||||
|
|
||||||
kind: ParameterKind<'db>,
|
kind: ParameterKind<'db>,
|
||||||
pub(crate) form: ParameterForm,
|
pub(crate) form: ParameterForm,
|
||||||
}
|
}
|
||||||
|
|
@ -1391,6 +1399,7 @@ impl<'db> Parameter<'db> {
|
||||||
pub(crate) fn positional_only(name: Option<Name>) -> Self {
|
pub(crate) fn positional_only(name: Option<Name>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
annotated_type: None,
|
annotated_type: None,
|
||||||
|
type_inffered: false,
|
||||||
kind: ParameterKind::PositionalOnly {
|
kind: ParameterKind::PositionalOnly {
|
||||||
name,
|
name,
|
||||||
default_type: None,
|
default_type: None,
|
||||||
|
|
@ -1402,6 +1411,7 @@ impl<'db> Parameter<'db> {
|
||||||
pub(crate) fn positional_or_keyword(name: Name) -> Self {
|
pub(crate) fn positional_or_keyword(name: Name) -> Self {
|
||||||
Self {
|
Self {
|
||||||
annotated_type: None,
|
annotated_type: None,
|
||||||
|
type_inffered: false,
|
||||||
kind: ParameterKind::PositionalOrKeyword {
|
kind: ParameterKind::PositionalOrKeyword {
|
||||||
name,
|
name,
|
||||||
default_type: None,
|
default_type: None,
|
||||||
|
|
@ -1413,6 +1423,7 @@ impl<'db> Parameter<'db> {
|
||||||
pub(crate) fn variadic(name: Name) -> Self {
|
pub(crate) fn variadic(name: Name) -> Self {
|
||||||
Self {
|
Self {
|
||||||
annotated_type: None,
|
annotated_type: None,
|
||||||
|
type_inffered: false,
|
||||||
kind: ParameterKind::Variadic { name },
|
kind: ParameterKind::Variadic { name },
|
||||||
form: ParameterForm::Value,
|
form: ParameterForm::Value,
|
||||||
}
|
}
|
||||||
|
|
@ -1421,6 +1432,7 @@ impl<'db> Parameter<'db> {
|
||||||
pub(crate) fn keyword_only(name: Name) -> Self {
|
pub(crate) fn keyword_only(name: Name) -> Self {
|
||||||
Self {
|
Self {
|
||||||
annotated_type: None,
|
annotated_type: None,
|
||||||
|
type_inffered: false,
|
||||||
kind: ParameterKind::KeywordOnly {
|
kind: ParameterKind::KeywordOnly {
|
||||||
name,
|
name,
|
||||||
default_type: None,
|
default_type: None,
|
||||||
|
|
@ -1432,6 +1444,7 @@ impl<'db> Parameter<'db> {
|
||||||
pub(crate) fn keyword_variadic(name: Name) -> Self {
|
pub(crate) fn keyword_variadic(name: Name) -> Self {
|
||||||
Self {
|
Self {
|
||||||
annotated_type: None,
|
annotated_type: None,
|
||||||
|
type_inffered: false,
|
||||||
kind: ParameterKind::KeywordVariadic { name },
|
kind: ParameterKind::KeywordVariadic { name },
|
||||||
form: ParameterForm::Value,
|
form: ParameterForm::Value,
|
||||||
}
|
}
|
||||||
|
|
@ -1470,6 +1483,7 @@ impl<'db> Parameter<'db> {
|
||||||
.annotated_type
|
.annotated_type
|
||||||
.map(|ty| ty.apply_type_mapping_impl(db, type_mapping, visitor)),
|
.map(|ty| ty.apply_type_mapping_impl(db, type_mapping, visitor)),
|
||||||
kind: self.kind.apply_type_mapping_impl(db, type_mapping, visitor),
|
kind: self.kind.apply_type_mapping_impl(db, type_mapping, visitor),
|
||||||
|
type_inffered: self.type_inffered,
|
||||||
form: self.form,
|
form: self.form,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1485,6 +1499,7 @@ impl<'db> Parameter<'db> {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let Parameter {
|
let Parameter {
|
||||||
annotated_type,
|
annotated_type,
|
||||||
|
type_inffered,
|
||||||
kind,
|
kind,
|
||||||
form,
|
form,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -1527,7 +1542,14 @@ impl<'db> Parameter<'db> {
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
<<<<<<< HEAD
|
||||||
annotated_type: Some(annotated_type),
|
annotated_type: Some(annotated_type),
|
||||||
|
||||||| parent of 63531eab6 (Don't display the implicit typing.Self type)
|
||||||
|
annotated_type,
|
||||||
|
=======
|
||||||
|
annotated_type,
|
||||||
|
type_inffered: *type_inffered,
|
||||||
|
>>>>>>> 63531eab6 (Don't display the implicit typing.Self type)
|
||||||
kind,
|
kind,
|
||||||
form: *form,
|
form: *form,
|
||||||
}
|
}
|
||||||
|
|
@ -1540,12 +1562,23 @@ impl<'db> Parameter<'db> {
|
||||||
kind: ParameterKind<'db>,
|
kind: ParameterKind<'db>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
<<<<<<< HEAD
|
||||||
annotated_type: parameter.annotation().map(|annotation| {
|
annotated_type: parameter.annotation().map(|annotation| {
|
||||||
definition_expression_type(db, definition, annotation).apply_type_mapping(
|
definition_expression_type(db, definition, annotation).apply_type_mapping(
|
||||||
db,
|
db,
|
||||||
&TypeMapping::MarkTypeVarsInferable(BindingContext::Definition(definition)),
|
&TypeMapping::MarkTypeVarsInferable(BindingContext::Definition(definition)),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
||||||| parent of 63531eab6 (Don't display the implicit typing.Self type)
|
||||||
|
annotated_type: parameter
|
||||||
|
.annotation()
|
||||||
|
.map(|annotation| definition_expression_type(db, definition, annotation)),
|
||||||
|
=======
|
||||||
|
annotated_type: parameter
|
||||||
|
.annotation()
|
||||||
|
.map(|annotation| definition_expression_type(db, definition, annotation)),
|
||||||
|
type_inffered: false,
|
||||||
|
>>>>>>> 63531eab6 (Don't display the implicit typing.Self type)
|
||||||
kind,
|
kind,
|
||||||
form: ParameterForm::Value,
|
form: ParameterForm::Value,
|
||||||
}
|
}
|
||||||
|
|
@ -1602,6 +1635,11 @@ impl<'db> Parameter<'db> {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the type of the parameter was inferred.
|
||||||
|
pub(crate) fn type_inffered(&self) -> bool {
|
||||||
|
self.type_inffered
|
||||||
|
}
|
||||||
|
|
||||||
/// Name of the parameter (if it has one).
|
/// Name of the parameter (if it has one).
|
||||||
pub(crate) fn name(&self) -> Option<&ast::name::Name> {
|
pub(crate) fn name(&self) -> Option<&ast::name::Name> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue