def make_or(inner): return booleq.Or( self.match_Signature_against_Signature( inner, s, subst, skip_self) for s in f.signatures)
def match_Signature_against_Function(self, sig, f, subst, skip_self=False): # pylint: disable=invalid-name return booleq.And( booleq.Or( self.match_Signature_against_Signature( inner, s, subst, skip_self) for s in f.signatures) for inner in sig.Visit(visitors.ExpandSignatures()))
def _match_type_against_type(self, t1, t2, subst): """Match a pytd.Type against another pytd.Type.""" t1 = self.maybe_lookup_type_param(t1, subst) t2 = self.maybe_lookup_type_param(t2, subst) # TODO(kramm): Use utils:TypeMatcher to simplify this? if isinstance(t2, pytd.AnythingType): # We can match anything against AnythingType. (It's like top) return booleq.TRUE elif isinstance(t1, pytd.AnythingType): if self.any_also_is_bottom: # We can match AnythingType against everything. (It's like bottom) return booleq.TRUE else: return booleq.FALSE elif isinstance(t1, pytd.NothingType): # nothing as an actual type matches against everything, since it # represents an empty value. return booleq.TRUE elif isinstance(t2, pytd.NothingType): # We can't match anything against nothing as an expected type (except # nothing itself, above). return booleq.FALSE elif isinstance(t1, pytd.UnionType): return booleq.And( self.match_type_against_type(u, t2, subst) for u in t1.type_list) elif isinstance(t2, pytd.UnionType): return booleq.Or( self.match_type_against_type(t1, u, subst) for u in t2.type_list) elif (isinstance(t1, pytd.ClassType) and isinstance(t2, StrictType) or isinstance(t1, StrictType) and isinstance(t2, pytd.ClassType)): # For strict types, avoid subclasses of the left side. return booleq.Eq(self._full_name(t1), self._full_name(t2)) elif (isinstance(t1, pytd.ClassType) and hasattr(t2, "name") and t2.name == "__builtin__.object"): return booleq.TRUE elif (hasattr(t1, "name") and hasattr(t2, "name") and t1.name in ("__builtin__.type", "typing.Callable") and t2.name in ("__builtin__.type", "typing.Callable")): return booleq.TRUE elif isinstance(t1, pytd.ClassType): # ClassTypes are similar to Unions, except they're disjunctions: We can # match the type or any of its base classes against the formal parameter. return booleq.Or( self.match_type_against_type(t, t2, subst) for t in self.expand_superclasses(t1)) elif isinstance(t2, pytd.ClassType): # ClassTypes on the right are exactly like Unions: We can match against # this type or any of its subclasses. return booleq.Or( self.match_type_against_type(t1, t, subst) for t in self.expand_subclasses(t2)) assert not isinstance(t1, pytd.ClassType) assert not isinstance(t2, pytd.ClassType) if is_unknown(t1) and isinstance(t2, pytd.GenericType): return self.match_Unknown_against_Generic(t1, t2, subst) elif isinstance(t1, pytd.GenericType) and is_unknown(t2): return self.match_Generic_against_Unknown(t1, t2, subst) elif isinstance(t1, pytd.GenericType) and isinstance( t2, pytd.GenericType): return self.match_Generic_against_Generic(t1, t2, subst) elif isinstance(t1, pytd.GenericType): # E.g. list[...] matches against list, or even object. return self.match_type_against_type(t1.base_type, t2, subst) elif isinstance(t2, pytd.GenericType): if self.any_also_is_bottom: # E.g. list (a.k.a. list[Any]) matches against list[str] return self.match_type_against_type(t1, t2.base_type, subst) else: return booleq.FALSE elif is_unknown(t1) and is_unknown(t2): return booleq.Eq(t1.name, t2.name) elif (isinstance(t1, (pytd.NamedType, StrictType)) and isinstance(t2, (pytd.NamedType, StrictType))): if is_complete(t1) and is_complete(t2) and t1.name != t2.name: # Optimization: If we know these two can never be equal, just return # false right away. return booleq.FALSE else: return booleq.Eq(t1.name, t2.name) elif isinstance(t1, pytd.LateType) or isinstance(t2, pytd.LateType): # Unresolved types never match against anything. return booleq.FALSE else: raise AssertionError("Don't know how to match %s against %s" % (type(t1), type(t2)))
def _match_type_against_type(self, t1, t2, subst): """Match a pytd.TYPE against another pytd.TYPE.""" t1 = self.maybe_lookup_type_param(t1, subst) t2 = self.maybe_lookup_type_param(t2, subst) # TODO(kramm): Use utils:TypeMatcher to simplify this? if isinstance(t1, pytd.AnythingType) or isinstance( t2, pytd.AnythingType): # We can match anything against AnythingType return booleq.TRUE elif isinstance(t1, pytd.NothingType) and isinstance( t2, pytd.NothingType): # nothing matches against nothing. return booleq.TRUE elif isinstance(t1, pytd.NothingType) or isinstance( t2, pytd.NothingType): # We can't match anything against nothing. (Except nothing itself, above) return booleq.FALSE elif isinstance(t1, pytd.UnionType): return booleq.And( self.match_type_against_type(u, t2, subst) for u in t1.type_list) elif isinstance(t2, pytd.UnionType): return booleq.Or( self.match_type_against_type(t1, u, subst) for u in t2.type_list) elif (isinstance(t1, pytd.ClassType) and isinstance(t2, StrictType) or isinstance(t1, StrictType) and isinstance(t2, pytd.ClassType)): # For strict types, avoid subclasses of the left side. return booleq.Eq(self._full_name(t1), self._full_name(t2)) elif isinstance(t1, pytd.ClassType): # ClassTypes are similar to Unions, except they're disjunctions: We can # match the type or any of its base classes against the formal parameter. return booleq.Or( self.match_type_against_type(t, t2, subst) for t in self.expand_superclasses(t1)) elif isinstance(t2, pytd.ClassType): # ClassTypes on the right are exactly like Unions: We can match against # this type or any of its subclasses. return booleq.Or( self.match_type_against_type(t1, t, subst) for t in self.expand_subclasses(t2)) assert not isinstance(t1, pytd.ClassType) assert not isinstance(t2, pytd.ClassType) if is_unknown(t1) and isinstance(t2, pytd.GenericType): return self.match_Unknown_against_Generic(t1, t2, subst) elif isinstance(t1, pytd.GenericType) and is_unknown(t2): return self.match_Generic_against_Unknown(t1, t2, subst) elif isinstance(t1, pytd.GenericType) and isinstance( t2, pytd.GenericType): return self.match_Generic_against_Generic(t1, t2, subst) elif isinstance(t1, pytd.GenericType): # E.g. list[...] matches against list, or even object. return self.match_type_against_type(t1.base_type, t2, subst) elif isinstance(t2, pytd.GenericType): assert t1 != t2.base_type return booleq.FALSE elif is_unknown(t1) and is_unknown(t2): return booleq.Eq(t1.name, t2.name) elif (isinstance(t1, (pytd.NamedType, StrictType)) and isinstance(t2, (pytd.NamedType, StrictType))): if is_complete(t1) and is_complete(t2) and t1.name != t2.name: # Optimization: If we know these two can never be equal, just return # false right away. return booleq.FALSE else: return booleq.Eq(t1.name, t2.name) else: raise AssertionError("Don't know how to match %s against %s" % (type(t1), type(t2)))