Skip to content

Commit a187f59

Browse files
Merge branch 'master' into reverse_op_for_subclass
2 parents 053118d + f336726 commit a187f59

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

mypy/constraints.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ def handle_recursive_union(template: UnionType, actual: Type, direction: int) ->
512512
) or infer_constraints(UnionType.make_union(type_var_items), actual, direction)
513513

514514

515-
def any_constraints(options: list[list[Constraint] | None], eager: bool) -> list[Constraint]:
515+
def any_constraints(options: list[list[Constraint] | None], *, eager: bool) -> list[Constraint]:
516516
"""Deduce what we can from a collection of constraint lists.
517517
518518
It's a given that at least one of the lists must be satisfied. A
@@ -547,14 +547,22 @@ def any_constraints(options: list[list[Constraint] | None], eager: bool) -> list
547547
if option in trivial_options:
548548
continue
549549
merged_options.append([merge_with_any(c) for c in option])
550-
return any_constraints(list(merged_options), eager)
550+
return any_constraints(list(merged_options), eager=eager)
551551

552552
# If normal logic didn't work, try excluding trivially unsatisfiable constraint (due to
553553
# upper bounds) from each option, and comparing them again.
554554
filtered_options = [filter_satisfiable(o) for o in options]
555555
if filtered_options != options:
556556
return any_constraints(filtered_options, eager=eager)
557557

558+
# Try harder: if that didn't work, try to strip typevars that aren't meta vars.
559+
# Note this is what we would always do, but unfortunately some callers may not
560+
# set the meta var status correctly (for historical reasons), so we use this as
561+
# a fallback only.
562+
filtered_options = [exclude_non_meta_vars(o) for o in options]
563+
if filtered_options != options:
564+
return any_constraints(filtered_options, eager=eager)
565+
558566
# Otherwise, there are either no valid options or multiple, inconsistent valid
559567
# options. Give up and deduce nothing.
560568
return []
@@ -569,6 +577,7 @@ def filter_satisfiable(option: list[Constraint] | None) -> list[Constraint] | No
569577
"""
570578
if not option:
571579
return option
580+
572581
satisfiable = []
573582
for c in option:
574583
if isinstance(c.origin_type_var, TypeVarType) and c.origin_type_var.values:
@@ -583,6 +592,15 @@ def filter_satisfiable(option: list[Constraint] | None) -> list[Constraint] | No
583592
return satisfiable
584593

585594

595+
def exclude_non_meta_vars(option: list[Constraint] | None) -> list[Constraint] | None:
596+
# If we had an empty list, keep it intact
597+
if not option:
598+
return option
599+
# However, if none of the options actually references meta vars, better remove
600+
# this constraint entirely.
601+
return [c for c in option if c.type_var.is_meta_var()] or None
602+
603+
586604
def is_same_constraints(x: list[Constraint], y: list[Constraint]) -> bool:
587605
for c1 in x:
588606
if not any(is_same_constraint(c1, c2) for c2 in y):

mypyc/lib-rt/str_ops.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
#include <Python.h>
66
#include "CPy.h"
77

8+
// The _PyUnicode_CheckConsistency definition has been moved to the internal API
9+
// https://github.com/python/cpython/pull/106398
10+
#if defined(Py_DEBUG) && defined(CPY_3_13_FEATURES)
11+
#include "internal/pycore_unicodeobject.h"
12+
#endif
13+
814
// Copied from cpython.git:Objects/unicodeobject.c@0ef4ffeefd1737c18dc9326133c7894d58108c2e.
915
#define BLOOM_MASK unsigned long
1016
#define BLOOM(mask, ch) ((mask & (1UL << ((ch) & (BLOOM_WIDTH - 1)))))
@@ -182,7 +188,9 @@ PyObject *CPyStr_Build(Py_ssize_t len, ...) {
182188
assert(res_offset == PyUnicode_GET_LENGTH(res));
183189
}
184190

191+
#ifdef Py_DEBUG
185192
assert(_PyUnicode_CheckConsistency(res, 1));
193+
#endif
186194
return res;
187195
}
188196

test-data/unit/check-inference.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,3 +3963,19 @@ def f() -> None:
39633963

39643964
# The type below should not be Any.
39653965
reveal_type(x) # N: Revealed type is "builtins.int"
3966+
3967+
[case testInferenceMappingTypeVarGet]
3968+
from typing import Generic, TypeVar, Union
3969+
3970+
_T = TypeVar("_T")
3971+
_K = TypeVar("_K")
3972+
_V = TypeVar("_V")
3973+
3974+
class Mapping(Generic[_K, _V]):
3975+
def get(self, key: _K, default: Union[_V, _T]) -> Union[_V, _T]: ...
3976+
3977+
def check(mapping: Mapping[str, _T]) -> None:
3978+
ok1 = mapping.get("", "")
3979+
reveal_type(ok1) # N: Revealed type is "Union[_T`-1, builtins.str]"
3980+
ok2: Union[_T, str] = mapping.get("", "")
3981+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)