text: """Type inference constraint solving"""
  
  from typing import List, Dict, Optional
  from collections import defaultdict
  
  from mypy.types import Type, AnyType, UninhabitedType, TypeVarId, TypeOfAny
  from mypy.constraints import Constraint, SUPERTYPE_OF
  from mypy.join import join_types
  from mypy.meet import meet_types
  from mypy.subtypes import is_subtype
  
  
  def solve_constraints(vars: List[TypeVarId], constraints: List[Constraint],
                        strict: bool = True) -> List[Optional[Type]]:
      """Solve type constraints.
  
      Return the best type(s) for type variables; each type can be None if the value of the variable
      could not be solved.
  
      If a variable has no constraints, if strict=True then arbitrarily
      pick NoneTyp as the value of the type variable.  If strict=False,
      pick AnyType.
      """
      # Collect a list of constraints for each type variable.
      cmap = defaultdict(list)  # type: Dict[TypeVarId, List[Constraint]]
      for con in constraints:
          cmap[con.type_var].append(con)
  
      res = []  # type: List[Optional[Type]]
  
      # Solve each type variable separately.
      for tvar in vars:
          bottom = None  # type: Optional[Type]
          top = None  # type: Optional[Type]
          candidate = None  # type: Optional[Type]
  
          # Process each constraint separately, and calculate the lower and upper
          # bounds based on constraints. Note that we assume that the constraint
          # targets do not have constraint references.
          for c in cmap.get(tvar, []):
              if c.op == SUPERTYPE_OF:
                  if bottom is None:
                      bottom = c.target
                  else:
                      bottom = join_types(bottom, c.target)
              else:
                  if top is None:
                      top = c.target
                  else:
                      top = meet_types(top, c.target)
  
          if isinstance(top, AnyType) or isinstance(bottom, AnyType):
              source_any = top if isinstance(top, AnyType) else bottom
              assert isinstance(source_any, AnyType)
              res.append(AnyType(TypeOfAny.from_another_any, source_any=source_any))
              continue
          elif bottom is None:
              if top:
                  candidate = top
              else:
                  # No constraints for type variable -- 'UninhabitedType' is the most specific type.
                  if strict:
                      candidate = UninhabitedType()
                      candidate.ambiguous = True
                  else:
                      candidate = AnyType(TypeOfAny.special_form)
          elif top is None:
              candidate = bottom
          elif is_subtype(bottom, top):
              candidate = bottom
          else:
              candidate = None
          res.append(candidate)
  
      return res
  