Skip to content

Commit 3657007

Browse files
committed
Try more principled approach to method override inference
1 parent 53e3756 commit 3657007

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

mypy/checker.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
analyze_class_attribute_access,
1818
analyze_instance_member_access,
1919
analyze_member_access,
20+
is_instance_var,
2021
)
2122
from mypy.checkpattern import PatternChecker
2223
from mypy.constraints import SUPERTYPE_OF
@@ -3408,10 +3409,17 @@ def get_variable_type_context(self, inferred: Var, rvalue: Expression) -> Type |
34083409
type_contexts = []
34093410
if inferred.info:
34103411
for base in inferred.info.mro[1:]:
3412+
if inferred.name not in base.names:
3413+
continue
34113414
# For inference within class body, get supertype attribute as it would look on
3412-
# a class object for lambdas overriding methods.
3413-
base_type, base_node = self.lvalue_type_from_base(
3414-
inferred, base, is_class=isinstance(rvalue, LambdaExpr)
3415+
# a class object for lambdas overriding methods, etc.
3416+
base_node = base.names[inferred.name].node
3417+
base_type, _ = self.lvalue_type_from_base(
3418+
inferred,
3419+
base,
3420+
is_class=is_method(base_node)
3421+
or isinstance(base_node, Var)
3422+
and not is_instance_var(base_node),
34153423
)
34163424
if (
34173425
base_type
@@ -9167,3 +9175,11 @@ def is_typeddict_type_context(lvalue_type: Type | None) -> bool:
91679175
return False
91689176
lvalue_proper = get_proper_type(lvalue_type)
91699177
return isinstance(lvalue_proper, TypedDictType)
9178+
9179+
9180+
def is_method(node: SymbolNode | None) -> bool:
9181+
if isinstance(node, OverloadedFuncDef):
9182+
return not node.is_property
9183+
if isinstance(node, Decorator):
9184+
return not node.var.is_property
9185+
return isinstance(node, FuncDef)

test-data/unit/check-classes.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8613,6 +8613,26 @@ class C(B):
86138613

86148614
reveal_type(C().f) # N: Revealed type is "def (x: builtins.int) -> builtins.int"
86158615

8616+
[case testGenericDecoratorInOverrideInference]
8617+
from typing import Any, Callable, TypeVar
8618+
from typing_extensions import ParamSpec, Concatenate
8619+
8620+
P = ParamSpec("P")
8621+
T = TypeVar("T")
8622+
def wrap(f: Callable[Concatenate[Any, P], T]) -> Callable[Concatenate[Any, P], T]: ...
8623+
8624+
class Base:
8625+
def g(self, a: int) -> int:
8626+
return a + 1
8627+
8628+
class Derived(Base):
8629+
def _g(self, a: int) -> int:
8630+
return a + 2
8631+
g = wrap(_g)
8632+
8633+
reveal_type(Derived().g) # N: Revealed type is "def (a: builtins.int) -> builtins.int"
8634+
[builtins fixtures/paramspec.pyi]
8635+
86168636
[case testClassVarOverrideWithSubclass]
86178637
class A: ...
86188638
class B(A): ...

0 commit comments

Comments
 (0)