Don't display the implicit typing.Self type

This commit is contained in:
Glyphack 2025-09-03 21:05:14 +02:00
parent 8dd183e55c
commit f34b6d8245
4 changed files with 86 additions and 12 deletions

View File

@ -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

View File

@ -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
``` ```

View File

@ -1150,12 +1150,14 @@ 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() {
if !self.param.type_inffered() {
write!( write!(
f, 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() {
if self.param.annotated_type().is_some() { if self.param.annotated_type().is_some() {
@ -1167,8 +1169,10 @@ 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.
if !self.param.type_inffered() {
ty.display_with(self.db, self.settings).fmt(f)?; ty.display_with(self.db, self.settings).fmt(f)?;
} }
}
Ok(()) Ok(())
} }
} }

View File

@ -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 {