Update mdtests

This commit is contained in:
Glyphack 2025-09-05 20:59:21 +02:00
parent a27013bdd3
commit a51982bac6
5 changed files with 52 additions and 60 deletions

View File

@ -75,15 +75,23 @@ class A:
def first_arg_is_not_self(a: int) -> int: def first_arg_is_not_self(a: int) -> int:
return a return a
return first_arg_is_not_self(1) 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
# TODO: revealed: A @classmethod
# Requires implicit in method body detection def bar(cls): ...
reveal_type(A().implicit_self()) # revealed: Unknown @staticmethod
reveal_type(A.implicit_self) # revealed: def implicit_self(self) -> Self@implicit_self def static(x): ...
a = A()
# TODO: Should reveal Self@implicit_self. Requires implicit self in method body(https://github.com/astral-sh/ruff/pull/18473)
reveal_type(a.implicit_self()) # revealed: Unknown
reveal_type(a.implicit_self) # revealed: bound method A.implicit_self() -> A
```
If the method is a class or static method then first argument is not self:
```py
A.bar()
a.static(1)
``` ```
## typing_extensions ## typing_extensions
@ -253,23 +261,4 @@ reveal_type(D().instance_method)
reveal_type(D.class_method) reveal_type(D.class_method)
``` ```
## Test
```py
from ty_extensions import generic_context
from typing import Generic, TypeVar
T = TypeVar("T")
U = TypeVar("U")
class C(Generic[T]):
def method(self, u: int) -> int:
return u
def generic_method(self, t: T, u: U) -> U:
return u
reveal_type(generic_context(C.method)) # revealed: tuple[Self@method]
```
[self attribute]: https://typing.python.org/en/latest/spec/generics.html#use-in-attribute-annotations [self attribute]: https://typing.python.org/en/latest/spec/generics.html#use-in-attribute-annotations

View File

@ -165,10 +165,9 @@ class C[T]:
return y return y
c: C[int] = C() c: C[int] = C()
reveal_type(c) # revealed: C[Unknown]
# reveal_type(c) # revealed: C[Unknown] # TODO:
# TODO: Next line fails. The reason is the reveal type above # error: [invalid-argument-type] "Argument to bound method `m` is incorrect: Expected `Self@m`, found `C[Unknown]`"
# error: 13 [invalid-argument-type] "Argument to bound method `m` is incorrect: Expected `Self@m`, found `C[Unknown]`"
reveal_type(c.m(1, "string")) # revealed: Literal["string"] reveal_type(c.m(1, "string")) # revealed: Literal["string"]
``` ```

View File

@ -357,8 +357,10 @@ class Invariant[T]:
def _(x: object): def _(x: object):
if isinstance(x, Invariant): if isinstance(x, Invariant):
reveal_type(x) # revealed: Top[Invariant[Unknown]] reveal_type(x) # revealed: Top[Invariant[Unknown]]
# error: [invalid-argument-type] "Argument to bound method `get` is incorrect: Expected `Self@get`, found `Top[Invariant[Unknown]]`"
reveal_type(x.get()) # revealed: object reveal_type(x.get()) # revealed: object
# error: [invalid-argument-type] "Argument to bound method `push` is incorrect: Expected `Never`, found `Literal[42]`" # error: [invalid-argument-type] "Argument to bound method `push` is incorrect: Expected `Never`, found `Literal[42]`"
# error: [invalid-argument-type] "Argument to bound method `push` is incorrect: Expected `Self@push`, found `Top[Invariant[Unknown]]`"
x.push(42) x.push(42)
``` ```

View File

@ -1834,7 +1834,6 @@ class P4(Protocol):
@z.setter @z.setter
def z(self, value: int) -> None: ... def z(self, value: int) -> None: ...
# error: [static-assert-error]
static_assert(is_equivalent_to(P1, P2)) static_assert(is_equivalent_to(P1, P2))
# TODO: should pass # TODO: should pass
@ -1848,7 +1847,6 @@ differently ordered unions:
class A: ... class A: ...
class B: ... class B: ...
# error: [static-assert-error]
static_assert(is_equivalent_to(A | B | P1, P2 | B | A)) static_assert(is_equivalent_to(A | B | P1, P2 | B | A))
# TODO: should pass # TODO: should pass

View File

@ -45,7 +45,7 @@ fn infer_method_type<'db>(
return None; return None;
}; };
let class_scope = index.scope(class_scope_id.file_scope_id(db)); let class_scope = index.scope(class_scope_id.file_scope_id(db));
class_scope.node().as_class(&module)?; class_scope.node().as_class()?;
let method_definition = index.expect_single_definition(func_def.node(&module)); let method_definition = index.expect_single_definition(func_def.node(&module));
let func_type = infer_definition_types(db, method_definition) let func_type = infer_definition_types(db, method_definition)
@ -382,8 +382,12 @@ impl<'db> Signature<'db> {
is_generator: bool, is_generator: bool,
has_implicitly_positional_first_parameter: bool, has_implicitly_positional_first_parameter: bool,
) -> Self { ) -> Self {
let parameters = let parameters = Parameters::from_parameters(
Parameters::from_parameters(db, definition, function_node.parameters.as_ref()); db,
definition,
function_node.parameters.as_ref(),
has_implicitly_positional_first_parameter,
);
let return_ty = function_node.returns.as_ref().map(|returns| { let return_ty = function_node.returns.as_ref().map(|returns| {
let plain_return_ty = definition_expression_type(db, definition, returns.as_ref()) let plain_return_ty = definition_expression_type(db, definition, returns.as_ref())
@ -1218,42 +1222,42 @@ impl<'db> Parameters<'db> {
.map(pos_only_param), .map(pos_only_param),
); );
} }
let method_type = infer_method_type(db, definition); let method_type = infer_method_type(db, definition);
let is_method = method_type.is_some(); let is_method = method_type.is_some();
let is_classmethod = method_type.is_some_and(|f| f.is_classmethod(db)); let is_classmethod = method_type.is_some_and(|f| f.is_classmethod(db));
let is_staticmethod = method_type.is_some_and(|f| f.is_staticmethod(db)); let is_staticmethod = method_type.is_some_and(|f| f.is_staticmethod(db));
let positional_or_keyword = pos_or_keyword_iter.map(|arg| { let positional_or_keyword = pos_or_keyword_iter.map(|arg| {
if is_method if is_method
&& !is_staticmethod && !is_staticmethod
&& !is_classmethod && !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)
{ {
let implicit_annotation = Type::SpecialForm(SpecialFormType::TypingSelf) let implicit_annotation = Type::SpecialForm(SpecialFormType::TypingSelf)
.in_type_expression(db, definition.scope(db), Some(definition)) .in_type_expression(db, definition.scope(db), Some(definition))
.ok(); .ok();
Parameter { Parameter {
annotated_type: implicit_annotation, annotated_type: implicit_annotation,
synthetic_annotation: true, synthetic_annotation: 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),
}, },
form: ParameterForm::Value, form: ParameterForm::Value,
} }
} else { } else {
Parameter::from_node_and_kind( Parameter::from_node_and_kind(
db, db,
definition, definition,
&arg.parameter, &arg.parameter,
ParameterKind::PositionalOrKeyword { ParameterKind::PositionalOrKeyword {
name: arg.parameter.name.id.clone(), name: arg.parameter.name.id.clone(),
default_type: default_type(arg), default_type: default_type(arg),
}, },
) )
} }
}); });
let variadic = vararg.as_ref().map(|arg| { let variadic = vararg.as_ref().map(|arg| {