Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5f6961b

Browse files
authored
Use upper bounds as fallback solutions for inference (#16184)
Fixes#13220This looks a bit ad-hoc, but it is probably the least disruptivesolution possible.
1 parent4b66fa9 commit5f6961b

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

‎mypy/solve.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ def solve_constraints(
109109
else:
110110
candidate=AnyType(TypeOfAny.special_form)
111111
res.append(candidate)
112+
113+
ifnotfree_vars:
114+
# Most of the validation for solutions is done in applytype.py, but here we can
115+
# quickly test solutions w.r.t. to upper bounds, and use the latter (if possible),
116+
# if solutions are actually not valid (due to poor inference context).
117+
res=pre_validate_solutions(res,original_vars,constraints)
118+
112119
returnres,free_vars
113120

114121

@@ -487,3 +494,31 @@ def check_linear(scc: set[TypeVarId], lowers: Bounds, uppers: Bounds) -> bool:
487494
defget_vars(target:Type,vars:list[TypeVarId])->set[TypeVarId]:
488495
"""Find type variables for which we are solving in a target type."""
489496
return {tv.idfortvinget_all_type_vars(target)}&set(vars)
497+
498+
499+
defpre_validate_solutions(
500+
solutions:list[Type|None],
501+
original_vars:Sequence[TypeVarLikeType],
502+
constraints:list[Constraint],
503+
)->list[Type|None]:
504+
"""Check is each solution satisfies the upper bound of the corresponding type variable.
505+
506+
If it doesn't satisfy the bound, check if bound itself satisfies all constraints, and
507+
if yes, use it instead as a fallback solution.
508+
"""
509+
new_solutions:list[Type|None]= []
510+
fort,sinzip(original_vars,solutions):
511+
ifsisnotNoneandnotis_subtype(s,t.upper_bound):
512+
bound_satisfies_all=True
513+
forcinconstraints:
514+
ifc.op==SUBTYPE_OFandnotis_subtype(t.upper_bound,c.target):
515+
bound_satisfies_all=False
516+
break
517+
ifc.op==SUPERTYPE_OFandnotis_subtype(c.target,t.upper_bound):
518+
bound_satisfies_all=False
519+
break
520+
ifbound_satisfies_all:
521+
new_solutions.append(t.upper_bound)
522+
continue
523+
new_solutions.append(s)
524+
returnnew_solutions

‎test-data/unit/check-inference.test‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,14 @@ T = TypeVar("T")
35423542
def type_or_callable(value: T, tp: Union[Type[T], Callable[[int], T]]) -> T: ...
35433543
reveal_type(type_or_callable(A("test"), A)) # N: Revealed type is "__main__.A"
35443544

3545+
[case testUpperBoundAsInferenceFallback]
3546+
from typing import Callable, TypeVar, Any, Mapping, Optional
3547+
T = TypeVar("T", bound=Mapping[str, Any])
3548+
def raises(opts: Optional[T]) -> T: pass
3549+
def assertRaises(cb: Callable[..., object]) -> None: pass
3550+
assertRaises(raises) # OK
3551+
[builtins fixtures/dict.pyi]
3552+
35453553
[case testJoinWithAnyFallback]
35463554
from unknown import X # type: ignore[import]
35473555

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp