(self, t: Instance, s: Instance)
| 59 | self.seen_instances: list[tuple[Instance, Instance]] = [] |
| 60 | |
| 61 | def join_instances(self, t: Instance, s: Instance) -> ProperType: |
| 62 | if (t, s) in self.seen_instances or (s, t) in self.seen_instances: |
| 63 | return object_from_instance(t) |
| 64 | |
| 65 | self.seen_instances.append((t, s)) |
| 66 | |
| 67 | # Calculate the join of two instance types |
| 68 | if t.type == s.type: |
| 69 | # Simplest case: join two types with the same base type (but |
| 70 | # potentially different arguments). |
| 71 | |
| 72 | # Combine type arguments. |
| 73 | args: list[Type] = [] |
| 74 | # N.B: We use zip instead of indexing because the lengths might have |
| 75 | # mismatches during daemon reprocessing. |
| 76 | if t.type.has_type_var_tuple_type: |
| 77 | # We handle joins of variadic instances by simply creating correct mapping |
| 78 | # for type arguments and compute the individual joins same as for regular |
| 79 | # instances. All the heavy lifting is done in the join of tuple types. |
| 80 | assert s.type.type_var_tuple_prefix is not None |
| 81 | assert s.type.type_var_tuple_suffix is not None |
| 82 | prefix = s.type.type_var_tuple_prefix |
| 83 | suffix = s.type.type_var_tuple_suffix |
| 84 | tvt = s.type.defn.type_vars[prefix] |
| 85 | assert isinstance(tvt, TypeVarTupleType) |
| 86 | fallback = tvt.tuple_fallback |
| 87 | s_prefix, s_middle, s_suffix = split_with_prefix_and_suffix(s.args, prefix, suffix) |
| 88 | t_prefix, t_middle, t_suffix = split_with_prefix_and_suffix(t.args, prefix, suffix) |
| 89 | s_args = s_prefix + (TupleType(list(s_middle), fallback),) + s_suffix |
| 90 | t_args = t_prefix + (TupleType(list(t_middle), fallback),) + t_suffix |
| 91 | else: |
| 92 | t_args = t.args |
| 93 | s_args = s.args |
| 94 | for ta, sa, type_var in zip(t_args, s_args, t.type.defn.type_vars): |
| 95 | ta_proper = get_proper_type(ta) |
| 96 | sa_proper = get_proper_type(sa) |
| 97 | new_type: Type | None = None |
| 98 | if isinstance(ta_proper, AnyType): |
| 99 | new_type = AnyType(TypeOfAny.from_another_any, ta_proper) |
| 100 | elif isinstance(sa_proper, AnyType): |
| 101 | new_type = AnyType(TypeOfAny.from_another_any, sa_proper) |
| 102 | elif isinstance(type_var, TypeVarType): |
| 103 | if type_var.variance in (COVARIANT, VARIANCE_NOT_READY): |
| 104 | new_type = join_types(ta, sa, self) |
| 105 | if len(type_var.values) != 0 and new_type not in type_var.values: |
| 106 | self.seen_instances.pop() |
| 107 | return object_from_instance(t) |
| 108 | if not is_subtype(new_type, type_var.upper_bound): |
| 109 | self.seen_instances.pop() |
| 110 | return object_from_instance(t) |
| 111 | # TODO: contravariant case should use meet but pass seen instances as |
| 112 | # an argument to keep track of recursive checks. |
| 113 | elif type_var.variance in (INVARIANT, CONTRAVARIANT): |
| 114 | if isinstance(ta_proper, UninhabitedType) and ta_proper.ambiguous: |
| 115 | new_type = sa |
| 116 | elif isinstance(sa_proper, UninhabitedType) and sa_proper.ambiguous: |
| 117 | new_type = ta |
| 118 | elif not is_equivalent(ta, sa): |
no test coverage detected