def visit_callable_type(self, t: CallableType) -> ProperType: if isinstance(self.s, CallableType) and is_similar_callables( t, self.s): if is_equivalent(t, self.s): return combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) # We set the from_type_type flag to suppress error when a collection of # concrete class objects gets inferred as their common abstract superclass. if not ( (t.is_type_obj() and t.type_object().is_abstract) or (self.s.is_type_obj() and self.s.type_object().is_abstract)): result.from_type_type = True if isinstance(get_proper_type(result.ret_type), UninhabitedType): # Return a plain None or <uninhabited> instead of a weird function. return self.default(self.s) return result elif isinstance(self.s, TypeType) and t.is_type_obj() and not t.is_generic(): # In this case we are able to potentially produce a better meet. res = meet_types(self.s.item, t.ret_type) if not isinstance(res, (NoneType, UninhabitedType)): return TypeType.make_normalized(res) return self.default(self.s) elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s)
def visit_callable_type(self, t: CallableType) -> Type: if isinstance(self.s, CallableType) and is_similar_callables(t, self.s): if is_equivalent(t, self.s): return combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) if isinstance(result.ret_type, UninhabitedType): # Return a plain None or <uninhabited> instead of a weird function. return self.default(self.s) return result elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s)
def visit_callable_type(self, t: CallableType) -> Type: if isinstance(self.s, CallableType) and is_similar_callables(t, self.s): if is_equivalent(t, self.s): return combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) if isinstance(result.ret_type, UninhabitedType): # Return a plain None or <uninhabited> instead of a weird function. return self.default(self.s) return result elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s)
def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): si = self.s if t.type == si.type: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. args = [] # type: List[Type] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for ta, sia in zip(t.args, si.args): args.append(self.meet(ta, sia)) return Instance(t.type, args) else: if state.strict_optional: return UninhabitedType() else: return NoneType() else: if is_subtype(t, self.s): return t elif is_subtype(self.s, t): # See also above comment. return self.s else: if state.strict_optional: return UninhabitedType() else: return NoneType() elif isinstance(self.s, FunctionLike) and t.type.is_protocol: call = unpack_callback_protocol(t) if call: return meet_types(call, self.s) elif isinstance(self.s, FunctionLike) and self.s.is_type_obj( ) and t.type.is_metaclass(): if is_subtype(self.s.fallback, t): return self.s return self.default(self.s) elif isinstance(self.s, TypeType): return meet_types(t, self.s) elif isinstance(self.s, TupleType): return meet_types(t, self.s) elif isinstance(self.s, LiteralType): return meet_types(t, self.s) elif isinstance(self.s, TypedDictType): return meet_types(t, self.s) return self.default(self.s)
def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): si = self.s if t.type == si.type: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. args = [] # type: List[Type] for i in range(len(t.args)): args.append(self.meet(t.args[i], si.args[i])) return Instance(t.type, args) else: if state.strict_optional: return UninhabitedType() else: return NoneType() else: if is_subtype(t, self.s): return t elif is_subtype(self.s, t): # See also above comment. return self.s else: if state.strict_optional: return UninhabitedType() else: return NoneType() elif isinstance(self.s, FunctionLike) and t.type.is_protocol: call = unpack_callback_protocol(t) if call: return meet_types(call, self.s) elif isinstance(self.s, FunctionLike) and self.s.is_type_obj( ) and t.type.is_metaclass(): if is_subtype(self.s.fallback, t): return self.s return self.default(self.s) elif isinstance(self.s, TypeType): return meet_types(t, self.s) elif isinstance(self.s, TupleType): return meet_types(t, self.s) elif isinstance(self.s, LiteralType): return meet_types(t, self.s) elif isinstance(self.s, TypedDictType): return meet_types(t, self.s) return self.default(self.s)
def visit_overloaded(self, t: Overloaded) -> ProperType: # TODO: Implement a better algorithm that covers at least the same cases # as TypeJoinVisitor.visit_overloaded(). s = self.s if isinstance(s, FunctionLike): if s.items() == t.items(): return Overloaded(t.items()) elif is_subtype(s, t): return s elif is_subtype(t, s): return t else: return meet_types(t.fallback, s.fallback) elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return meet_types(t.fallback, s)
def visit_overloaded(self, t: Overloaded) -> Type: # TODO: Implement a better algorithm that covers at least the same cases # as TypeJoinVisitor.visit_overloaded(). s = self.s if isinstance(s, FunctionLike): if s.items() == t.items(): return Overloaded(t.items()) elif is_subtype(s, t): return s elif is_subtype(t, s): return t else: return meet_types(t.fallback, s.fallback) elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return meet_types(t.fallback, s)
def visit_callable_type(self, t: CallableType) -> Type: if isinstance(self.s, CallableType) and is_similar_callables(t, self.s): if is_equivalent(t, self.s): return combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) if isinstance(result.ret_type, UninhabitedType): # Return a plain None or <uninhabited> instead of a weird function. return self.default(self.s) return result elif isinstance(self.s, TypeType) and t.is_type_obj() and not t.is_generic(): # In this case we are able to potentially produce a better meet. res = meet_types(self.s.item, t.ret_type) if not isinstance(res, (NoneType, UninhabitedType)): return TypeType.make_normalized(res) return self.default(self.s) elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s)
def visit_callable_type(self, t: CallableType) -> Type: if isinstance(self.s, CallableType) and is_similar_callables(t, self.s): if is_equivalent(t, self.s): return combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) if isinstance(result.ret_type, UninhabitedType): # Return a plain None or <uninhabited> instead of a weird function. return self.default(self.s) return result elif isinstance(self.s, TypeType) and t.is_type_obj() and not t.is_generic(): # In this case we are able to potentially produce a better meet. res = meet_types(self.s.item, t.ret_type) if not isinstance(res, (NoneType, UninhabitedType)): return TypeType.make_normalized(res) return self.default(self.s) elif isinstance(self.s, Instance) and self.s.type.is_protocol: call = unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s)
def visit_instance(self, t: Instance) -> Type: if isinstance(self.s, Instance): si = self.s if t.type == si.type: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. args = [] # type: List[Type] for i in range(len(t.args)): args.append(self.meet(t.args[i], si.args[i])) return Instance(t.type, args) else: if state.strict_optional: return UninhabitedType() else: return NoneTyp() else: if is_subtype(t, self.s): return t elif is_subtype(self.s, t): # See also above comment. return self.s else: if state.strict_optional: return UninhabitedType() else: return NoneTyp() elif isinstance(self.s, FunctionLike) and t.type.is_protocol: call = unpack_callback_protocol(t) if call: return meet_types(call, self.s) elif isinstance(self.s, TypeType): return meet_types(t, self.s) elif isinstance(self.s, TupleType): return meet_types(t, self.s) elif isinstance(self.s, LiteralType): return meet_types(t, self.s) return self.default(self.s)
def visit_instance(self, t: Instance) -> Type: if isinstance(self.s, Instance): si = self.s if t.type == si.type: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. args = [] # type: List[Type] for i in range(len(t.args)): args.append(self.meet(t.args[i], si.args[i])) return Instance(t.type, args) else: if experiments.STRICT_OPTIONAL: return UninhabitedType() else: return NoneTyp() else: if is_subtype(t, self.s): return t elif is_subtype(self.s, t): # See also above comment. return self.s else: if experiments.STRICT_OPTIONAL: return UninhabitedType() else: return NoneTyp() elif isinstance(self.s, FunctionLike) and t.type.is_protocol: call = unpack_callback_protocol(t) if call: return meet_types(call, self.s) elif isinstance(self.s, TypeType): return meet_types(t, self.s) elif isinstance(self.s, TupleType): return meet_types(t, self.s) elif isinstance(self.s, LiteralType): return meet_types(t, self.s) return self.default(self.s)