Skip to content

Commit 419d085

Browse files
committed
Assume type of self is typing.Self
1 parent 5ecd560 commit 419d085

File tree

4 files changed

+54
-30
lines changed

4 files changed

+54
-30
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@ class Shape:
2929
return inner()
3030

3131
def implicit_self(self) -> Self:
32-
# TODO: first argument in a method should be considered as "typing.Self"
3332
reveal_type(self) # revealed: Unknown
3433
return self
3534

36-
# TODO: should be `list[Shape]`
37-
reveal_type(Shape().nested_type()) # revealed: list[Self]
35+
reveal_type(Shape().nested_type()) # revealed: list[Shape]
3836

3937
reveal_type(Shape().nested_func()) # revealed: Shape
4038

crates/ty_python_semantic/src/types.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use infer::enclosing_class_symbol;
1+
use infer::enclosing_class_definition;
22
use itertools::Either;
33

44
use std::slice::Iter;
@@ -4798,21 +4798,17 @@ impl<'db> Type<'db> {
47984798

47994799
KnownInstanceType::TypingSelf => {
48004800
let index = semantic_index(db, scope_id.file(db));
4801-
let Some(class_ty) = enclosing_class_symbol(db, index, scope_id) else {
4801+
let Some(class_def) = enclosing_class_definition(db, index, scope_id) else {
48024802
return Err(InvalidTypeExpressionError {
48034803
fallback_type: Type::unknown(),
48044804
invalid_expressions: smallvec::smallvec![
48054805
InvalidTypeExpression::InvalidType(*self)
48064806
],
48074807
});
48084808
};
4809-
let Some(TypeDefinition::Class(class_def)) = class_ty.definition(db) else {
4810-
debug_assert!(
4811-
false,
4812-
"enclosing_class_symbol must return a type with class definition"
4813-
);
4814-
return Ok(Type::unknown());
4815-
};
4809+
let class_ty = infer_definition_types(db, class_def)
4810+
.declaration_type(class_def)
4811+
.inner_type();
48164812
let Some(instance) = class_ty.to_instance(db) else {
48174813
debug_assert!(
48184814
false,

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -317,31 +317,45 @@ pub(super) fn infer_unpack_types<'db>(db: &'db dyn Db, unpack: Unpack<'db>) -> U
317317
unpacker.finish()
318318
}
319319

320-
/// Returns the type of the nearest enclosing class for the given scope.
320+
/// Returns the definition of the nearest enclosing class for the given scope.
321321
///
322322
/// This function walks up the ancestor scopes starting from the given scope,
323323
/// and finds the closest class definition.
324324
///
325325
/// Returns `None` if no enclosing class is found.a
326-
pub(crate) fn enclosing_class_symbol<'db>(
326+
pub(crate) fn enclosing_class_definition<'db>(
327327
db: &'db dyn Db,
328328
semantic: &SemanticIndex<'db>,
329329
scope: ScopeId,
330-
) -> Option<Type<'db>> {
330+
) -> Option<Definition<'db>> {
331331
semantic
332332
.ancestor_scopes(scope.file_scope_id(db))
333333
.find_map(|(_, ancestor_scope)| {
334334
if let NodeWithScopeKind::Class(class) = ancestor_scope.node() {
335335
let definition = semantic.expect_single_definition(class.node());
336-
let result = infer_definition_types(db, definition);
337-
338-
Some(result.declaration_type(definition).inner_type())
336+
Some(definition)
339337
} else {
340338
None
341339
}
342340
})
343341
}
344342

343+
/// Returns the type of the nearest enclosing class for the given scope.
344+
///
345+
/// This function walks up the ancestor scopes starting from the given scope,
346+
/// and finds the closest class definition.
347+
///
348+
/// Returns `None` if no enclosing class is found.a
349+
pub(crate) fn enclosing_class_type<'db>(
350+
db: &'db dyn Db,
351+
semantic: &SemanticIndex<'db>,
352+
scope: ScopeId,
353+
) -> Option<Type<'db>> {
354+
let definition = enclosing_class_definition(db, semantic, scope)?;
355+
let result = infer_definition_types(db, definition);
356+
return Some(result.declaration_type(definition).inner_type());
357+
}
358+
345359
/// A region within which we can infer types.
346360
#[derive(Copy, Clone, Debug)]
347361
pub(crate) enum InferenceRegion<'db> {
@@ -4975,7 +4989,7 @@ impl<'db> TypeInferenceBuilder<'db> {
49754989
[] => {
49764990
let scope = self.scope();
49774991

4978-
let Some(enclosing_class) = enclosing_class_symbol(
4992+
let Some(enclosing_class) = enclosing_class_type(
49794993
self.db(),
49804994
self.index,
49814995
scope,

crates/ty_python_semantic/src/types/signatures.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use smallvec::{smallvec, SmallVec};
1818
use super::{definition_expression_type, DynamicType, Type};
1919
use crate::semantic_index::definition::Definition;
2020
use crate::types::generics::{GenericContext, Specialization, TypeMapping};
21-
use crate::types::{todo_type, ClassLiteral, TypeVarInstance};
21+
use crate::types::{todo_type, ClassLiteral, KnownInstanceType, TypeVarInstance};
2222
use crate::{Db, FxOrderSet};
2323
use ruff_python_ast::{self as ast, name::Name};
2424

@@ -1032,16 +1032,32 @@ impl<'db> Parameters<'db> {
10321032
},
10331033
)
10341034
});
1035-
let positional_or_keyword = args.iter().map(|arg| {
1036-
Parameter::from_node_and_kind(
1037-
db,
1038-
definition,
1039-
&arg.parameter,
1040-
ParameterKind::PositionalOrKeyword {
1041-
name: arg.parameter.name.id.clone(),
1042-
default_type: default_type(arg),
1043-
},
1044-
)
1035+
let positional_or_keyword = args.iter().enumerate().map(|(index, arg)| {
1036+
// TODO: Check for classmethod decorator
1037+
if index == 0 && arg.name() == "self" {
1038+
Parameter {
1039+
annotated_type: Some(
1040+
Type::KnownInstance(KnownInstanceType::TypingSelf)
1041+
.in_type_expression(db, definition.scope(db))
1042+
.unwrap(),
1043+
),
1044+
kind: ParameterKind::PositionalOrKeyword {
1045+
name: arg.parameter.name.id.clone(),
1046+
default_type: default_type(arg),
1047+
},
1048+
form: ParameterForm::Value,
1049+
}
1050+
} else {
1051+
Parameter::from_node_and_kind(
1052+
db,
1053+
definition,
1054+
&arg.parameter,
1055+
ParameterKind::PositionalOrKeyword {
1056+
name: arg.parameter.name.id.clone(),
1057+
default_type: default_type(arg),
1058+
},
1059+
)
1060+
}
10451061
});
10461062
let variadic = vararg.as_ref().map(|arg| {
10471063
Parameter::from_node_and_kind(

0 commit comments

Comments
 (0)