@@ -109,6 +109,13 @@ def solve_constraints(
109109else :
110110candidate = AnyType (TypeOfAny .special_form )
111111res .append (candidate )
112+
113+ if not free_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+
112119return res ,free_vars
113120
114121
@@ -487,3 +494,31 @@ def check_linear(scc: set[TypeVarId], lowers: Bounds, uppers: Bounds) -> bool:
487494def get_vars (target :Type ,vars :list [TypeVarId ])-> set [TypeVarId ]:
488495"""Find type variables for which we are solving in a target type."""
489496return {tv .id for tv in get_all_type_vars (target )}& set (vars )
497+
498+
499+ def pre_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+ for t ,s in zip (original_vars ,solutions ):
511+ if s is not None and not is_subtype (s ,t .upper_bound ):
512+ bound_satisfies_all = True
513+ for c in constraints :
514+ if c .op == SUBTYPE_OF and not is_subtype (t .upper_bound ,c .target ):
515+ bound_satisfies_all = False
516+ break
517+ if c .op == SUPERTYPE_OF and not is_subtype (c .target ,t .upper_bound ):
518+ bound_satisfies_all = False
519+ break
520+ if bound_satisfies_all :
521+ new_solutions .append (t .upper_bound )
522+ continue
523+ new_solutions .append (s )
524+ return new_solutions