8000 Fix some daemon crashes involving classes becoming generic · python/mypy@d84fc52 · GitHub
[go: up one dir, main page]

Skip to content

Commit d84fc52

Browse files
committed
Fix some daemon crashes involving classes becoming generic
Fixes #3279. Also fixes another related crash.
1 parent da8880e commit d84fc52

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

mypy/constraints.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,29 +347,33 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
347347
template.type.has_base(instance.type.fullname)):
348348
mapped = map_instance_to_supertype(template, instance.type)
349349
tvars = mapped.type.defn.type_vars
350-
for i in range(len(instance.args)):
350+
# N.B: We use zip instead of indexing because the lengths might have
351+
# mismatches during daemon reprocessing.
352+
for tvar, mapped_arg, instance_arg in zip(tvars, mapped.args, instance.args):
351353
# The constraints for generic type parameters depend on variance.
352354
# Include constraints from both directions if invariant.
353-
if tvars[i].variance != CONTRAVARIANT:
355+
if tvar.variance != CONTRAVARIANT:
354356
res.extend(infer_constraints(
355-
mapped.args[i], instance.args[i], self.direction))
356-
if tvars[i].variance != COVARIANT:
357+
mapped_arg, instance_arg, self.direction))
358+
if tvar.variance != COVARIANT:
357359
res.extend(infer_constraints(
358-
mapped.args[i], instance.args[i], neg_op(self.direction)))
360+
mapped_arg, instance_arg, neg_op(self.direction)))
359361
return res
360362
elif (self.direction == SUPERTYPE_OF and
361363
instance.type.has_base(template.type.fullname)):
362364
mapped = map_instance_to_supertype(instance, template.type)
363365
tvars = template.type.defn.type_vars
364-
for j in range(len(template.args)):
366+
# N.B: We use zip instead of indexing because the lengths might have
367+
# mismatches during daemon reprocessing.
368+
for tvar, mapped_arg, template_arg in zip(tvars, mapped.args, template.args):
365369
# The constraints for generic type parameters depend on variance.
366370
# Include constraints from both directions if invariant.
367-
if tvars[j].variance != CONTRAVARIANT:
371+
if tvar.variance != CONTRAVARIANT:
368372
res.extend(infer_constraints(
369-
template.args[j], mapped.args[j], self.direction))
370-
if tvars[j].variance != COVARIANT:
373+
template_arg, mapped_arg, self.direction))
374+
if tvar.variance != COVARIANT:
371375
res.extend(infer_constraints(
372-
template.args[j], mapped.args[j], neg_op(self.direction)))
376+
template_arg, mapped_arg, neg_op(self.direction)))
373377
return res
374378
if (template.type.is_protocol and self.direction == SUPERTYPE_OF and
375379
# We avoid infinite recursion for structural subtypes by checking

mypy/meet.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,15 @@ def visit_type_var(self, t: TypeVarType) -> ProperType:
486486
def visit_instance(self, t: Instance) -> ProperType:
487487
if isinstance(self.s, Instance):
488488
si = self.s
489-
if t.type == si.type:
489+
if t.type == si.type and len(t.args) == len(si.args):
490490
if is_subtype(t, self.s) or is_subtype(self.s, t):
491491
# Combine type arguments. We could have used join below
492492
# equivalently.
493493
args = [] # type: List[Type]
494-
for i in range(len(t.args)):
495-
args.append(self.meet(t.args[i], si.args[i]))
494+
# N.B: We use zip instead of indexing because the lengths might have
495+
# mismatches during daemon reprocessing.
496+
for ta, sia in zip(t.args, si.args):
497+
args.append(self.meet(ta, sia))
496498
return Instance(t.type, args)
497499
else:
498500
if state.strict_optional:

test-data/unit/fine-grained.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9288,3 +9288,32 @@ class B:
92889288
self.x = 0
92899289
[out]
92909290
==
9291+
9292+
[case testGenericChange]
9293+
import a
9294+
[file a.py]
9295+
import b
9296+
def f() -> b.C: pass
9297+
[file b.py]
9298+
import a
9299+
class C: pass
9300+
[file b.py.2]
9301+
from typing import TypeVar, Generic, Type, List
9302+
import a
9303+
9304+
T = TypeVar('T')
9305+
class C(Generic[T]): pass
9306+
9307+
reveal_type(a.f)
9308+
c: C[int]
9309+
l = a.f() if True else c
9310+
d = a.f()
9311+
d = c
9312+
c = d
9313+
9314+
x: List[C] = [a.f(), a.f()]
9315+
9316+
[out]
9317+
==
9318+
b.py:7: note: Revealed type is 'def () -> b.C[Any]'
9319+
[builtins fixtures/list.pyi]

0 commit comments

Comments
 (0)
0