Skip to content

Commit c795732

Browse files
committed
Assume type of self is typing.Self in signature
1 parent 02394b8 commit c795732

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

crates/ty_python_semantic/resources/mdtest/annotations/self.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Shape:
3535

3636
reveal_type(Shape().nested_type()) # revealed: list[Shape]
3737
reveal_type(Shape().nested_func()) # revealed: Shape
38+
reveal_type(Shape().implicit_self()) # revealed: Shape
3839

3940
class Circle(Shape):
4041
def set_scale(self: Self, scale: float) -> Self:

crates/ty_python_semantic/src/types/signatures.rs

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ use std::{collections::HashMap, slice::Iter};
1515
use itertools::EitherOrBoth;
1616
use smallvec::{SmallVec, smallvec};
1717

18-
use super::{DynamicType, Type, definition_expression_type};
19-
use crate::semantic_index::definition::Definition;
18+
use super::{
19+
DynamicType, FunctionDecorators, KnownInstanceType, Type, definition_expression_type,
20+
infer_definition_types, nearest_enclosing_class, semantic_index,
21+
};
22+
use crate::semantic_index::definition::{Definition, DefinitionKind};
2023
use crate::types::generics::GenericContext;
2124
use crate::types::{ClassLiteral, TypeMapping, TypeVarInstance, todo_type};
2225
use crate::{Db, FxOrderSet};
@@ -1028,16 +1031,57 @@ impl<'db> Parameters<'db> {
10281031
},
10291032
)
10301033
});
1031-
let positional_or_keyword = args.iter().map(|arg| {
1032-
Parameter::from_node_and_kind(
1033-
db,
1034-
definition,
1035-
&arg.parameter,
1036-
ParameterKind::PositionalOrKeyword {
1037-
name: arg.parameter.name.id.clone(),
1038-
default_type: default_type(arg),
1039-
},
1040-
)
1034+
let function_is_method = if matches!(definition.kind(db), DefinitionKind::Function(_)) {
1035+
let scope = definition.scope(db);
1036+
let index = semantic_index(db, scope.file(db));
1037+
nearest_enclosing_class(db, index, scope).is_some()
1038+
} else {
1039+
false
1040+
};
1041+
let classmethod = if let DefinitionKind::Function(f) = definition.kind(db) {
1042+
if f.name.id() == "__new__" {
1043+
true
1044+
} else {
1045+
let result = infer_definition_types(db, definition);
1046+
match result.declaration_type(definition).inner_type() {
1047+
Type::FunctionLiteral(t) => {
1048+
t.decorators(db).contains(FunctionDecorators::CLASSMETHOD)
1049+
}
1050+
_ => false,
1051+
}
1052+
}
1053+
} else {
1054+
false
1055+
};
1056+
let positional_or_keyword = args.iter().enumerate().map(|(index, arg)| {
1057+
if index == 0
1058+
&& function_is_method
1059+
&& arg.parameter.annotation().is_none()
1060+
// TODO: Handle type of cls
1061+
&& !classmethod
1062+
{
1063+
let implicit_annotation = Type::KnownInstance(KnownInstanceType::TypingSelf)
1064+
.in_type_expression(db, definition.scope(db))
1065+
.unwrap();
1066+
Parameter {
1067+
annotated_type: Some(implicit_annotation),
1068+
kind: ParameterKind::PositionalOrKeyword {
1069+
name: arg.parameter.name.id.clone(),
1070+
default_type: default_type(arg),
1071+
},
1072+
form: ParameterForm::Value,
1073+
}
1074+
} else {
1075+
Parameter::from_node_and_kind(
1076+
db,
1077+
definition,
1078+
&arg.parameter,
1079+
ParameterKind::PositionalOrKeyword {
1080+
name: arg.parameter.name.id.clone(),
1081+
default_type: default_type(arg),
1082+
},
1083+
)
1084+
}
10411085
});
10421086
let variadic = vararg.as_ref().map(|arg| {
10431087
Parameter::from_node_and_kind(

0 commit comments

Comments
 (0)