def join_instances(t: Instance, s: Instance) -> Type: """Calculate the join of two instance types. If allow_interfaces is True, also consider interface-type results for non-interface types. Return ErrorType if the result is ambiguous. """ if t.type == s.type: # Simplest case: join two types with the same base type (but # potentially different arguments). if is_subtype(t, s) or is_subtype(s, t): # Compatible; combine type arguments. args = [] # type: List[Type] for i in range(len(t.args)): args.append(join_types(t.args[i], s.args[i])) return Instance(t.type, args) else: # Incompatible; return trivial result object. return object_from_instance(t) elif t.type.bases and is_subtype_ignoring_tvars(t, s): return join_instances_via_supertype(t, s) else: # Now t is not a subtype of s, and t != s. Now s could be a subtype # of t; alternatively, we need to find a common supertype. This works # in of the both cases. return join_instances_via_supertype(s, t)
def join_instances(self, t: Instance, s: Instance) -> ProperType: if (t, s) in self.seen_instances or (s, t) in self.seen_instances: return object_from_instance(t) self.seen_instances.append((t, s)) # Calculate the join of two instance types if t.type == s.type: # Simplest case: join two types with the same base type (but # potentially different arguments). # Combine type arguments. args: List[Type] = [] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for ta, sa, type_var in zip(t.args, s.args, t.type.defn.type_vars): ta_proper = get_proper_type(ta) sa_proper = get_proper_type(sa) new_type: Optional[Type] = None if isinstance(ta_proper, AnyType): new_type = AnyType(TypeOfAny.from_another_any, ta_proper) elif isinstance(sa_proper, AnyType): new_type = AnyType(TypeOfAny.from_another_any, sa_proper) elif isinstance(type_var, TypeVarType): if type_var.variance == COVARIANT: new_type = join_types(ta, sa, self) if len(type_var.values ) != 0 and new_type not in type_var.values: self.seen_instances.pop() return object_from_instance(t) if not is_subtype(new_type, type_var.upper_bound): self.seen_instances.pop() return object_from_instance(t) # TODO: contravariant case should use meet but pass seen instances as # an argument to keep track of recursive checks. elif type_var.variance in (INVARIANT, CONTRAVARIANT): if not is_equivalent(ta, sa): self.seen_instances.pop() return object_from_instance(t) # If the types are different but equivalent, then an Any is involved # so using a join in the contravariant case is also OK. new_type = join_types(ta, sa, self) else: # ParamSpec type variables behave the same, independent of variance if not is_equivalent(ta, sa): return get_proper_type(type_var.upper_bound) new_type = join_types(ta, sa, self) assert new_type is not None args.append(new_type) result: ProperType = Instance(t.type, args) elif t.type.bases and is_subtype_ignoring_tvars(t, s): result = self.join_instances_via_supertype(t, s) else: # Now t is not a subtype of s, and t != s. Now s could be a subtype # of t; alternatively, we need to find a common supertype. This works # in of the both cases. result = self.join_instances_via_supertype(s, t) self.seen_instances.pop() return result
def join_instances(self, t: Instance, s: Instance) -> ProperType: if (t, s) in self.seen_instances or (s, t) in self.seen_instances: return object_from_instance(t) self.seen_instances.append((t, s)) """Calculate the join of two instance types.""" if t.type == s.type: # Simplest case: join two types with the same base type (but # potentially different arguments). # Combine type arguments. args: List[Type] = [] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for ta, sa, type_var in zip(t.args, s.args, t.type.defn.type_vars): ta_proper = get_proper_type(ta) sa_proper = get_proper_type(sa) new_type: Optional[Type] = None if isinstance(ta_proper, AnyType): new_type = AnyType(TypeOfAny.from_another_any, ta_proper) elif isinstance(sa_proper, AnyType): new_type = AnyType(TypeOfAny.from_another_any, sa_proper) elif type_var.variance == COVARIANT: new_type = join_types(ta, sa, self) if len(type_var.values ) != 0 and new_type not in type_var.values: self.seen_instances.pop() return object_from_instance(t) if not is_subtype(new_type, type_var.upper_bound): self.seen_instances.pop() return object_from_instance(t) elif type_var.variance == CONTRAVARIANT: new_type = meet.meet_types(ta, sa) if len(type_var.values ) != 0 and new_type not in type_var.values: self.seen_instances.pop() return object_from_instance(t) # No need to check subtype, as ta and sa already have to be subtypes of # upper_bound elif type_var.variance == INVARIANT: new_type = join_types(ta, sa) if not is_equivalent(ta, sa): self.seen_instances.pop() return object_from_instance(t) assert new_type is not None args.append(new_type) result: ProperType = Instance(t.type, args) elif t.type.bases and is_subtype_ignoring_tvars(t, s): result = self.join_instances_via_supertype(t, s) else: # Now t is not a subtype of s, and t != s. Now s could be a subtype # of t; alternatively, we need to find a common supertype. This works # in of the both cases. result = self.join_instances_via_supertype(s, t) self.seen_instances.pop() return result
def join_instances(t: Instance, s: Instance) -> ProperType: """Calculate the join of two instance types.""" if t.type == s.type: # Simplest case: join two types with the same base type (but # potentially different arguments). if is_subtype(t, s) or is_subtype(s, t): # Compatible; combine type arguments. args = [] # type: List[Type] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for ta, sa in zip(t.args, s.args): args.append(join_types(ta, sa)) return Instance(t.type, args) else: # Incompatible; return trivial result object. return object_from_instance(t) elif t.type.bases and is_subtype_ignoring_tvars(t, s): return join_instances_via_supertype(t, s) else: # Now t is not a subtype of s, and t != s. Now s could be a subtype # of t; alternatively, we need to find a common supertype. This works # in of the both cases. return join_instances_via_supertype(s, t)