Exemplo n.º 1
0
  def bad_matches(self, var, other_type, node):
    """Match a Variable against a type. Return views that don't match.

    Args:
      var: A cfg.Variable, containing instances.
      other_type: An instance of BaseValue.
      node: A cfg.CFGNode. The position in the CFG from which we "observe" the
        match.
    Returns:
      A list of all the views of var that didn't match.
    """
    bad = []
    if (var.data == [self.vm.convert.unsolvable] or
        other_type == self.vm.convert.unsolvable):
      # An unsolvable matches everything. Since bad_matches doesn't need to
      # compute substitutions, we can return immediately.
      return bad
    views = abstract_utils.get_views([var], node)
    skip_future = None
    while True:
      try:
        view = views.send(skip_future)
      except StopIteration:
        break
      if self.match_var_against_type(var, other_type, {}, node, view) is None:
        if node.HasCombination(list(view.values())):
          bad.append(view)
        # To get complete error messages, we need to collect all bad views, so
        # we can't skip any.
        skip_future = False
      else:
        skip_future = True
    return bad
Exemplo n.º 2
0
    def bad_matches(self, var, other_type, node):
        """Match a Variable against a type. Return views that don't match.

    Args:
      var: A cfg.Variable, containing instances.
      other_type: An instance of AtomicAbstractValue.
      node: A cfg.CFGNode. The position in the CFG from which we "observe" the
        match.
    Returns:
      A list of all the views of var that didn't match.
    """
        bad = []
        views = abstract_utils.get_views([var], node, filter_strict=True)
        skip_future = None
        while True:
            try:
                view = views.send(skip_future)
            except StopIteration:
                break
            if self.match_var_against_type(var, other_type, {}, node,
                                           view) is None:
                bad.append(view)
                # To get complete error messages, we need to collect all bad views, so
                # we can't skip any.
                skip_future = False
            else:
                skip_future = True
        return bad
Exemplo n.º 3
0
 def test_basic(self):
   v1 = self._vm.program.NewVariable(
       [self._vm.convert.unsolvable], [], self._vm.root_cfg_node)
   v2 = self._vm.program.NewVariable(
       [self._vm.convert.int_type, self._vm.convert.str_type], [],
       self._vm.root_cfg_node)
   views = list(abstract_utils.get_views([v1, v2], self._vm.root_cfg_node))
   six.assertCountEqual(self,
                        [{v1: views[0][v1], v2: views[0][v2]},
                         {v1: views[1][v1], v2: views[1][v2]}],
                        [{v1: v1.bindings[0], v2: v2.bindings[0]},
                         {v1: v1.bindings[0], v2: v2.bindings[1]}])
Exemplo n.º 4
0
 def _check_return(self, node, actual, formal):
   if not self.options.report_errors:
     return True
   views = abstract_utils.get_views([actual], node)
   # Check for typevars in the return value first, since bad_matches
   # expects not to get any.
   bad = [view for view in views
          if actual in view and view[actual].data.formal]
   if not bad:
     bad = self.matcher.bad_matches(actual, formal, node)
   if bad:
     self.errorlog.bad_return_type(
         self.frames, node, formal, actual, bad)
   return not bad
Exemplo n.º 5
0
 def _match_all_bindings(self, var, other_type, subst, node, view):
   """Matches all of var's bindings against other_type."""
   new_substs = []
   for new_view in abstract_utils.get_views([var], node):
     # When new_view and view have entries in common, we want to use the
     # entries from the old view.
     new_view.update(view)
     new_subst = self.match_var_against_type(
         var, other_type, subst, node, new_view)
     if new_subst is not None:
       new_substs.append(new_subst)
   if new_substs:
     return self._merge_substs(subst, new_substs)
   else:
     return None
Exemplo n.º 6
0
 def _check_return(self, node, actual, formal):
   if not self.options.report_errors:
     return True
   views = abstract_utils.get_views([actual], node)
   # Check for typevars in the return value first, since bad_matches
   # expects not to get any.
   bad = [view for view in views
          if actual in view and view[actual].data.formal]
   if not bad:
     bad = self.matcher.bad_matches(actual, formal, node)
   if bad:
     with self.convert.pytd_convert.produce_detailed_output():
       combined = pytd_utils.JoinTypes(
           view[actual].data.to_type(node, view=view) for view in bad)
       self.errorlog.bad_return_type(
           self.frames, combined, formal.get_instance_type(node))
   return not bad
Exemplo n.º 7
0
 def _instantiate_and_match(self, left, other_type, subst, node, view,
                            container=None):
   """Instantiate and match an abstract value."""
   instance = left.instantiate(node, container=container)
   new_substs = []
   for new_view in abstract_utils.get_views([instance], node):
     # When new_view and view have entries in common, we want to use the
     # entries from the old view.
     new_view.update(view)
     new_subst = self.match_var_against_type(
         instance, other_type, subst, node, new_view)
     if new_subst is not None:
       new_substs.append(new_subst)
   if new_substs:
     return self._merge_substs(subst, new_substs)
   else:
     return None
Exemplo n.º 8
0
 def _test_optimized(self, skip_future_value, expected_num_views):
     v1 = self._vm.program.NewVariable([self._vm.convert.unsolvable], [],
                                       self._vm.root_cfg_node)
     v2 = self._vm.program.NewVariable(
         [self._vm.convert.int_type, self._vm.convert.str_type], [],
         self._vm.root_cfg_node)
     views = abstract_utils.get_views([v1, v2], self._vm.root_cfg_node)
     skip_future = None
     # To count the number of views. Doesn't matter what we put in here, as long
     # as it's one per view.
     view_markers = []
     while True:
         try:
             view = views.send(skip_future)
         except StopIteration:
             break
         # Accesses v1 only, so the v2 bindings should be deduplicated when
         # `skip_future` is True.
         view_markers.append(view[v1])
         skip_future = skip_future_value
     self.assertEqual(len(view_markers), expected_num_views)
Exemplo n.º 9
0
 def _match_var(self, left, right):
     var = self.vm.program.NewVariable()
     var.AddBinding(left, [], self.vm.root_cfg_node)
     for view in abstract_utils.get_views([var], self.vm.root_cfg_node):
         yield self.vm.matcher.match_var_against_type(
             var, right, {}, self.vm.root_cfg_node, view)