We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
When `a` has type `Any`, after `assert a is None`, the rest of the block is considered dead code
Steps to reproduce:

1. Check out [this repo](https://github.com/benkuhn/mypy-repro)
2. Install the packages from `requirements.txt`
3. Run `mypy repro.py` from the repo root.

Expected output:
```
repro.py:4: error: Revealed type is 'Any'
repro.py:6: error: Revealed type is 'builtins.None'
```

Actual output:
```
repro.py:4: error: Revealed type is 'Any'
```

The issue goes away if you disable strict Optional checking.

This is preventing a significant amount of our codebase from being checked right now, so I would appreciate any suggestions for a workaround!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mypy/meet.py`
Content:
```
1 from collections import OrderedDict
2 from typing import List, Optional
3 
4 from mypy.join import is_similar_callables, combine_similar_callables, join_type_list
5 from mypy.types import (
6     Type, AnyType, TypeVisitor, UnboundType, Void, ErrorType, NoneTyp, TypeVarType,
7     Instance, CallableType, TupleType, TypedDictType, ErasedType, TypeList, UnionType, PartialType,
8     DeletedType, UninhabitedType, TypeType
9 )
10 from mypy.subtypes import is_equivalent, is_subtype
11 
12 from mypy import experiments
13 
14 # TODO Describe this module.
15 
16 
17 def meet_types(s: Type, t: Type) -> Type:
18     """Return the greatest lower bound of two types."""
19     if isinstance(s, ErasedType):
20         return s
21     if isinstance(s, AnyType):
22         return t
23     if isinstance(s, UnionType) and not isinstance(t, UnionType):
24         s, t = t, s
25     return t.accept(TypeMeetVisitor(s))
26 
27 
28 def meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:
29     if s == t:
30         return s
31     if isinstance(s, UnionType):
32         return UnionType.make_simplified_union([meet_types(x, t) for x in s.items])
33     elif not is_overlapping_types(s, t, use_promotions=True):
34         if experiments.STRICT_OPTIONAL:
35             return UninhabitedType()
36         else:
37             return NoneTyp()
38     else:
39         if default_right:
40             return t
41         else:
42             return s
43 
44 
45 def is_overlapping_types(t: Type, s: Type, use_promotions: bool = False) -> bool:
46     """Can a value of type t be a value of type s, or vice versa?
47 
48     Note that this effectively checks against erased types, since type
49     variables are erased at runtime and the overlapping check is based
50     on runtime behavior.
51 
52     If use_promotions is True, also consider type promotions (int and
53     float would only be overlapping if it's True).
54 
55     This does not consider multiple inheritance. For example, A and B in
56     the following example are not considered overlapping, even though
57     via C they can be overlapping:
58 
59         class A: ...
60         class B: ...
61         class C(A, B): ...
62 
63     The rationale is that this case is usually very unlikely as multiple
64     inheritance is rare. Also, we can't reliably determine whether
65     multiple inheritance actually occurs somewhere in a program, due to
66     stub files hiding implementation details, dynamic loading etc.
67 
68     TODO: Don't consider tuples always overlapping.
69     TODO: Don't consider callables always overlapping.
70     TODO: Don't consider type variables with values always overlapping.
71     """
72     # Since we are effectively working with the erased types, we only
73     # need to handle occurrences of TypeVarType at the top level.
74     if isinstance(t, TypeVarType):
75         t = t.erase_to_union_or_bound()
76     if isinstance(s, TypeVarType):
77         s = s.erase_to_union_or_bound()
78     if isinstance(t, Instance):
79         if isinstance(s, Instance):
80             # Consider two classes non-disjoint if one is included in the mro
81             # of another.
82             if use_promotions:
83                 # Consider cases like int vs float to be overlapping where
84                 # there is only a type promotion relationship but not proper
85                 # subclassing.
86                 if t.type._promote and is_overlapping_types(t.type._promote, s):
87                     return True
88                 if s.type._promote and is_overlapping_types(s.type._promote, t):
89                     return True
90             return t.type in s.type.mro or s.type in t.type.mro
91     if isinstance(t, UnionType):
92         return any(is_overlapping_types(item, s)
93                    for item in t.items)
94     if isinstance(s, UnionType):
95         return any(is_overlapping_types(t, item)
96                    for item in s.items)
97     if isinstance(t, TypeType) and isinstance(s, TypeType):
98         # If both types are TypeType, compare their inner types.
99         return is_overlapping_types(t.item, s.item, use_promotions)
100     elif isinstance(t, TypeType) or isinstance(s, TypeType):
101         # If exactly only one of t or s is a TypeType, check if one of them
102         # is an `object` or a `type` and otherwise assume no overlap.
103         other = s if isinstance(t, TypeType) else t
104         if isinstance(other, Instance):
105             return other.type.fullname() in {'builtins.object', 'builtins.type'}
106         else:
107             return False
108     if experiments.STRICT_OPTIONAL:
109         if isinstance(t, NoneTyp) != isinstance(s, NoneTyp):
110             # NoneTyp does not overlap with other non-Union types under strict Optional checking
111             return False
112     # We conservatively assume that non-instance, non-union, and non-TypeType types can overlap
113     # any other types.
114     return True
115 
116 
117 class TypeMeetVisitor(TypeVisitor[Type]):
118     def __init__(self, s: Type) -> None:
119         self.s = s
120 
121     def visit_unbound_type(self, t: UnboundType) -> Type:
122         if isinstance(self.s, Void) or isinstance(self.s, ErrorType):
123             return ErrorType()
124         elif isinstance(self.s, NoneTyp):
125             if experiments.STRICT_OPTIONAL:
126                 return AnyType()
127             else:
128                 return self.s
129         elif isinstance(self.s, UninhabitedType):
130             return self.s
131         else:
132             return AnyType()
133 
134     def visit_error_type(self, t: ErrorType) -> Type:
135         return t
136 
137     def visit_type_list(self, t: TypeList) -> Type:
138         assert False, 'Not supported'
139 
140     def visit_any(self, t: AnyType) -> Type:
141         return self.s
142 
143     def visit_union_type(self, t: UnionType) -> Type:
144         if isinstance(self.s, UnionType):
145             meets = []  # type: List[Type]
146             for x in t.items:
147                 for y in self.s.items:
148                     meets.append(meet_types(x, y))
149         else:
150             meets = [meet_types(x, self.s)
151                      for x in t.items]
152         return UnionType.make_simplified_union(meets)
153 
154     def visit_void(self, t: Void) -> Type:
155         if isinstance(self.s, Void):
156             return t
157         else:
158             return ErrorType()
159 
160     def visit_none_type(self, t: NoneTyp) -> Type:
161         if experiments.STRICT_OPTIONAL:
162             if isinstance(self.s, NoneTyp) or (isinstance(self.s, Instance) and
163                                                self.s.type.fullname() == 'builtins.object'):
164                 return t
165             else:
166                 return UninhabitedType()
167         else:
168             if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):
169                 return t
170             else:
171                 return ErrorType()
172 
173     def visit_uninhabited_type(self, t: UninhabitedType) -> Type:
174         if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):
175             return t
176         else:
177             return ErrorType()
178 
179     def visit_deleted_type(self, t: DeletedType) -> Type:
180         if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):
181             if isinstance(self.s, NoneTyp):
182                 if experiments.STRICT_OPTIONAL:
183                     return t
184                 else:
185                     return self.s
186             elif isinstance(self.s, UninhabitedType):
187                 return self.s
188             else:
189                 return t
190         else:
191             return ErrorType()
192 
193     def visit_erased_type(self, t: ErasedType) -> Type:
194         return self.s
195 
196     def visit_type_var(self, t: TypeVarType) -> Type:
197         if isinstance(self.s, TypeVarType) and self.s.id == t.id:
198             return self.s
199         else:
200             return self.default(self.s)
201 
202     def visit_instance(self, t: Instance) -> Type:
203         if isinstance(self.s, Instance):
204             si = self.s
205             if t.type == si.type:
206                 if is_subtype(t, self.s) or is_subtype(self.s, t):
207                     # Combine type arguments. We could have used join below
208                     # equivalently.
209                     args = []  # type: List[Type]
210                     for i in range(len(t.args)):
211                         args.append(self.meet(t.args[i], si.args[i]))
212                     return Instance(t.type, args)
213                 else:
214                     if experiments.STRICT_OPTIONAL:
215                         return UninhabitedType()
216                     else:
217                         return NoneTyp()
218             else:
219                 if is_subtype(t, self.s):
220                     return t
221                 elif is_subtype(self.s, t):
222                     # See also above comment.
223                     return self.s
224                 else:
225                     if experiments.STRICT_OPTIONAL:
226                         return UninhabitedType()
227                     else:
228                         return NoneTyp()
229         elif isinstance(self.s, TypeType):
230             return meet_types(t, self.s)
231         elif isinstance(self.s, TupleType):
232             return meet_types(t, self.s)
233         else:
234             return self.default(self.s)
235 
236     def visit_callable_type(self, t: CallableType) -> Type:
237         if isinstance(self.s, CallableType) and is_similar_callables(t, self.s):
238             return combine_similar_callables(t, self.s)
239         else:
240             return self.default(self.s)
241 
242     def visit_tuple_type(self, t: TupleType) -> Type:
243         if isinstance(self.s, TupleType) and self.s.length() == t.length():
244             items = []  # type: List[Type]
245             for i in range(t.length()):
246                 items.append(self.meet(t.items[i], self.s.items[i]))
247             # TODO: What if the fallbacks are different?
248             return TupleType(items, t.fallback)
249         # meet(Tuple[t1, t2, <...>], Tuple[s, ...]) == Tuple[meet(t1, s), meet(t2, s), <...>].
250         elif (isinstance(self.s, Instance) and
251               self.s.type.fullname() == 'builtins.tuple' and self.s.args):
252             return t.copy_modified(items=[meet_types(it, self.s.args[0]) for it in t.items])
253         else:
254             return self.default(self.s)
255 
256     def visit_typeddict_type(self, t: TypedDictType) -> Type:
257         if isinstance(self.s, TypedDictType):
258             for (_, l, r) in self.s.zip(t):
259                 if not is_equivalent(l, r):
260                     return self.default(self.s)
261             items = OrderedDict([
262                 (item_name, s_item_type or t_item_type)
263                 for (item_name, s_item_type, t_item_type) in self.s.zipall(t)
264             ])
265             mapping_value_type = join_type_list(list(items.values()))
266             fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type)
267             return TypedDictType(items, fallback)
268         else:
269             return self.default(self.s)
270 
271     def visit_partial_type(self, t: PartialType) -> Type:
272         # We can't determine the meet of partial types. We should never get here.
273         assert False, 'Internal error'
274 
275     def visit_type_type(self, t: TypeType) -> Type:
276         if isinstance(self.s, TypeType):
277             typ = self.meet(t.item, self.s.item)
278             if not isinstance(typ, NoneTyp):
279                 typ = TypeType(typ, line=t.line)
280             return typ
281         elif isinstance(self.s, Instance) and self.s.type.fullname() == 'builtins.type':
282             return t
283         else:
284             return self.default(self.s)
285 
286     def meet(self, s: Type, t: Type) -> Type:
287         return meet_types(s, t)
288 
289     def default(self, typ: Type) -> Type:
290         if isinstance(typ, UnboundType):
291             return AnyType()
292         elif isinstance(typ, Void) or isinstance(typ, ErrorType):
293             return ErrorType()
294         else:
295             if experiments.STRICT_OPTIONAL:
296                 return UninhabitedType()
297             else:
298                 return NoneTyp()
299
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mypy/meet.py b/mypy/meet.py
--- a/mypy/meet.py
+++ b/mypy/meet.py
@@ -69,6 +69,10 @@
     TODO: Don't consider callables always overlapping.
     TODO: Don't consider type variables with values always overlapping.
     """
+    # Any overlaps with everything
+    if isinstance(t, AnyType) or isinstance(s, AnyType):
+        return True
+
     # Since we are effectively working with the erased types, we only
     # need to handle occurrences of TypeVarType at the top level.
     if isinstance(t, TypeVarType):

{"golden_diff": "diff --git a/mypy/meet.py b/mypy/meet.py\n--- a/mypy/meet.py\n+++ b/mypy/meet.py\n@@ -69,6 +69,10 @@\n     TODO: Don't consider callables always overlapping.\n     TODO: Don't consider type variables with values always overlapping.\n     \"\"\"\n+    # Any overlaps with everything\n+    if isinstance(t, AnyType) or isinstance(s, AnyType):\n+        return True\n+\n     # Since we are effectively working with the erased types, we only\n     # need to handle occurrences of TypeVarType at the top level.\n     if isinstance(t, TypeVarType):\n", "issue": "When `a` has type `Any`, after `assert a is None`, the rest of the block is considered dead code\nSteps to reproduce:\r\n\r\n1. Check out [this repo](https://github.com/benkuhn/mypy-repro)\r\n2. Install the packages from `requirements.txt`\r\n3. Run `mypy repro.py` from the repo root.\r\n\r\nExpected output:\r\n```\r\nrepro.py:4: error: Revealed type is 'Any'\r\nrepro.py:6: error: Revealed type is 'builtins.None'\r\n```\r\n\r\nActual output:\r\n```\r\nrepro.py:4: error: Revealed type is 'Any'\r\n```\r\n\r\nThe issue goes away if you disable strict Optional checking.\r\n\r\nThis is preventing a significant amount of our codebase from being checked right now, so I would appreciate any suggestions for a workaround!\n", "before_files": [{"content": "from collections import OrderedDict\nfrom typing import List, Optional\n\nfrom mypy.join import is_similar_callables, combine_similar_callables, join_type_list\nfrom mypy.types import (\n    Type, AnyType, TypeVisitor, UnboundType, Void, ErrorType, NoneTyp, TypeVarType,\n    Instance, CallableType, TupleType, TypedDictType, ErasedType, TypeList, UnionType, PartialType,\n    DeletedType, UninhabitedType, TypeType\n)\nfrom mypy.subtypes import is_equivalent, is_subtype\n\nfrom mypy import experiments\n\n# TODO Describe this module.\n\n\ndef meet_types(s: Type, t: Type) -> Type:\n    \"\"\"Return the greatest lower bound of two types.\"\"\"\n    if isinstance(s, ErasedType):\n        return s\n    if isinstance(s, AnyType):\n        return t\n    if isinstance(s, UnionType) and not isinstance(t, UnionType):\n        s, t = t, s\n    return t.accept(TypeMeetVisitor(s))\n\n\ndef meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:\n    if s == t:\n        return s\n    if isinstance(s, UnionType):\n        return UnionType.make_simplified_union([meet_types(x, t) for x in s.items])\n    elif not is_overlapping_types(s, t, use_promotions=True):\n        if experiments.STRICT_OPTIONAL:\n            return UninhabitedType()\n        else:\n            return NoneTyp()\n    else:\n        if default_right:\n            return t\n        else:\n            return s\n\n\ndef is_overlapping_types(t: Type, s: Type, use_promotions: bool = False) -> bool:\n    \"\"\"Can a value of type t be a value of type s, or vice versa?\n\n    Note that this effectively checks against erased types, since type\n    variables are erased at runtime and the overlapping check is based\n    on runtime behavior.\n\n    If use_promotions is True, also consider type promotions (int and\n    float would only be overlapping if it's True).\n\n    This does not consider multiple inheritance. For example, A and B in\n    the following example are not considered overlapping, even though\n    via C they can be overlapping:\n\n        class A: ...\n        class B: ...\n        class C(A, B): ...\n\n    The rationale is that this case is usually very unlikely as multiple\n    inheritance is rare. Also, we can't reliably determine whether\n    multiple inheritance actually occurs somewhere in a program, due to\n    stub files hiding implementation details, dynamic loading etc.\n\n    TODO: Don't consider tuples always overlapping.\n    TODO: Don't consider callables always overlapping.\n    TODO: Don't consider type variables with values always overlapping.\n    \"\"\"\n    # Since we are effectively working with the erased types, we only\n    # need to handle occurrences of TypeVarType at the top level.\n    if isinstance(t, TypeVarType):\n        t = t.erase_to_union_or_bound()\n    if isinstance(s, TypeVarType):\n        s = s.erase_to_union_or_bound()\n    if isinstance(t, Instance):\n        if isinstance(s, Instance):\n            # Consider two classes non-disjoint if one is included in the mro\n            # of another.\n            if use_promotions:\n                # Consider cases like int vs float to be overlapping where\n                # there is only a type promotion relationship but not proper\n                # subclassing.\n                if t.type._promote and is_overlapping_types(t.type._promote, s):\n                    return True\n                if s.type._promote and is_overlapping_types(s.type._promote, t):\n                    return True\n            return t.type in s.type.mro or s.type in t.type.mro\n    if isinstance(t, UnionType):\n        return any(is_overlapping_types(item, s)\n                   for item in t.items)\n    if isinstance(s, UnionType):\n        return any(is_overlapping_types(t, item)\n                   for item in s.items)\n    if isinstance(t, TypeType) and isinstance(s, TypeType):\n        # If both types are TypeType, compare their inner types.\n        return is_overlapping_types(t.item, s.item, use_promotions)\n    elif isinstance(t, TypeType) or isinstance(s, TypeType):\n        # If exactly only one of t or s is a TypeType, check if one of them\n        # is an `object` or a `type` and otherwise assume no overlap.\n        other = s if isinstance(t, TypeType) else t\n        if isinstance(other, Instance):\n            return other.type.fullname() in {'builtins.object', 'builtins.type'}\n        else:\n            return False\n    if experiments.STRICT_OPTIONAL:\n        if isinstance(t, NoneTyp) != isinstance(s, NoneTyp):\n            # NoneTyp does not overlap with other non-Union types under strict Optional checking\n            return False\n    # We conservatively assume that non-instance, non-union, and non-TypeType types can overlap\n    # any other types.\n    return True\n\n\nclass TypeMeetVisitor(TypeVisitor[Type]):\n    def __init__(self, s: Type) -> None:\n        self.s = s\n\n    def visit_unbound_type(self, t: UnboundType) -> Type:\n        if isinstance(self.s, Void) or isinstance(self.s, ErrorType):\n            return ErrorType()\n        elif isinstance(self.s, NoneTyp):\n            if experiments.STRICT_OPTIONAL:\n                return AnyType()\n            else:\n                return self.s\n        elif isinstance(self.s, UninhabitedType):\n            return self.s\n        else:\n            return AnyType()\n\n    def visit_error_type(self, t: ErrorType) -> Type:\n        return t\n\n    def visit_type_list(self, t: TypeList) -> Type:\n        assert False, 'Not supported'\n\n    def visit_any(self, t: AnyType) -> Type:\n        return self.s\n\n    def visit_union_type(self, t: UnionType) -> Type:\n        if isinstance(self.s, UnionType):\n            meets = []  # type: List[Type]\n            for x in t.items:\n                for y in self.s.items:\n                    meets.append(meet_types(x, y))\n        else:\n            meets = [meet_types(x, self.s)\n                     for x in t.items]\n        return UnionType.make_simplified_union(meets)\n\n    def visit_void(self, t: Void) -> Type:\n        if isinstance(self.s, Void):\n            return t\n        else:\n            return ErrorType()\n\n    def visit_none_type(self, t: NoneTyp) -> Type:\n        if experiments.STRICT_OPTIONAL:\n            if isinstance(self.s, NoneTyp) or (isinstance(self.s, Instance) and\n                                               self.s.type.fullname() == 'builtins.object'):\n                return t\n            else:\n                return UninhabitedType()\n        else:\n            if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n                return t\n            else:\n                return ErrorType()\n\n    def visit_uninhabited_type(self, t: UninhabitedType) -> Type:\n        if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n            return t\n        else:\n            return ErrorType()\n\n    def visit_deleted_type(self, t: DeletedType) -> Type:\n        if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n            if isinstance(self.s, NoneTyp):\n                if experiments.STRICT_OPTIONAL:\n                    return t\n                else:\n                    return self.s\n            elif isinstance(self.s, UninhabitedType):\n                return self.s\n            else:\n                return t\n        else:\n            return ErrorType()\n\n    def visit_erased_type(self, t: ErasedType) -> Type:\n        return self.s\n\n    def visit_type_var(self, t: TypeVarType) -> Type:\n        if isinstance(self.s, TypeVarType) and self.s.id == t.id:\n            return self.s\n        else:\n            return self.default(self.s)\n\n    def visit_instance(self, t: Instance) -> Type:\n        if isinstance(self.s, Instance):\n            si = self.s\n            if t.type == si.type:\n                if is_subtype(t, self.s) or is_subtype(self.s, t):\n                    # Combine type arguments. We could have used join below\n                    # equivalently.\n                    args = []  # type: List[Type]\n                    for i in range(len(t.args)):\n                        args.append(self.meet(t.args[i], si.args[i]))\n                    return Instance(t.type, args)\n                else:\n                    if experiments.STRICT_OPTIONAL:\n                        return UninhabitedType()\n                    else:\n                        return NoneTyp()\n            else:\n                if is_subtype(t, self.s):\n                    return t\n                elif is_subtype(self.s, t):\n                    # See also above comment.\n                    return self.s\n                else:\n                    if experiments.STRICT_OPTIONAL:\n                        return UninhabitedType()\n                    else:\n                        return NoneTyp()\n        elif isinstance(self.s, TypeType):\n            return meet_types(t, self.s)\n        elif isinstance(self.s, TupleType):\n            return meet_types(t, self.s)\n        else:\n            return self.default(self.s)\n\n    def visit_callable_type(self, t: CallableType) -> Type:\n        if isinstance(self.s, CallableType) and is_similar_callables(t, self.s):\n            return combine_similar_callables(t, self.s)\n        else:\n            return self.default(self.s)\n\n    def visit_tuple_type(self, t: TupleType) -> Type:\n        if isinstance(self.s, TupleType) and self.s.length() == t.length():\n            items = []  # type: List[Type]\n            for i in range(t.length()):\n                items.append(self.meet(t.items[i], self.s.items[i]))\n            # TODO: What if the fallbacks are different?\n            return TupleType(items, t.fallback)\n        # meet(Tuple[t1, t2, <...>], Tuple[s, ...]) == Tuple[meet(t1, s), meet(t2, s), <...>].\n        elif (isinstance(self.s, Instance) and\n              self.s.type.fullname() == 'builtins.tuple' and self.s.args):\n            return t.copy_modified(items=[meet_types(it, self.s.args[0]) for it in t.items])\n        else:\n            return self.default(self.s)\n\n    def visit_typeddict_type(self, t: TypedDictType) -> Type:\n        if isinstance(self.s, TypedDictType):\n            for (_, l, r) in self.s.zip(t):\n                if not is_equivalent(l, r):\n                    return self.default(self.s)\n            items = OrderedDict([\n                (item_name, s_item_type or t_item_type)\n                for (item_name, s_item_type, t_item_type) in self.s.zipall(t)\n            ])\n            mapping_value_type = join_type_list(list(items.values()))\n            fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type)\n            return TypedDictType(items, fallback)\n        else:\n            return self.default(self.s)\n\n    def visit_partial_type(self, t: PartialType) -> Type:\n        # We can't determine the meet of partial types. We should never get here.\n        assert False, 'Internal error'\n\n    def visit_type_type(self, t: TypeType) -> Type:\n        if isinstance(self.s, TypeType):\n            typ = self.meet(t.item, self.s.item)\n            if not isinstance(typ, NoneTyp):\n                typ = TypeType(typ, line=t.line)\n            return typ\n        elif isinstance(self.s, Instance) and self.s.type.fullname() == 'builtins.type':\n            return t\n        else:\n            return self.default(self.s)\n\n    def meet(self, s: Type, t: Type) -> Type:\n        return meet_types(s, t)\n\n    def default(self, typ: Type) -> Type:\n        if isinstance(typ, UnboundType):\n            return AnyType()\n        elif isinstance(typ, Void) or isinstance(typ, ErrorType):\n            return ErrorType()\n        else:\n            if experiments.STRICT_OPTIONAL:\n                return UninhabitedType()\n            else:\n                return NoneTyp()\n", "path": "mypy/meet.py"}], "after_files": [{"content": "from collections import OrderedDict\nfrom typing import List, Optional\n\nfrom mypy.join import is_similar_callables, combine_similar_callables, join_type_list\nfrom mypy.types import (\n    Type, AnyType, TypeVisitor, UnboundType, Void, ErrorType, NoneTyp, TypeVarType,\n    Instance, CallableType, TupleType, TypedDictType, ErasedType, TypeList, UnionType, PartialType,\n    DeletedType, UninhabitedType, TypeType\n)\nfrom mypy.subtypes import is_equivalent, is_subtype\n\nfrom mypy import experiments\n\n# TODO Describe this module.\n\n\ndef meet_types(s: Type, t: Type) -> Type:\n    \"\"\"Return the greatest lower bound of two types.\"\"\"\n    if isinstance(s, ErasedType):\n        return s\n    if isinstance(s, AnyType):\n        return t\n    if isinstance(s, UnionType) and not isinstance(t, UnionType):\n        s, t = t, s\n    return t.accept(TypeMeetVisitor(s))\n\n\ndef meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:\n    if s == t:\n        return s\n    if isinstance(s, UnionType):\n        return UnionType.make_simplified_union([meet_types(x, t) for x in s.items])\n    elif not is_overlapping_types(s, t, use_promotions=True):\n        if experiments.STRICT_OPTIONAL:\n            return UninhabitedType()\n        else:\n            return NoneTyp()\n    else:\n        if default_right:\n            return t\n        else:\n            return s\n\n\ndef is_overlapping_types(t: Type, s: Type, use_promotions: bool = False) -> bool:\n    \"\"\"Can a value of type t be a value of type s, or vice versa?\n\n    Note that this effectively checks against erased types, since type\n    variables are erased at runtime and the overlapping check is based\n    on runtime behavior.\n\n    If use_promotions is True, also consider type promotions (int and\n    float would only be overlapping if it's True).\n\n    This does not consider multiple inheritance. For example, A and B in\n    the following example are not considered overlapping, even though\n    via C they can be overlapping:\n\n        class A: ...\n        class B: ...\n        class C(A, B): ...\n\n    The rationale is that this case is usually very unlikely as multiple\n    inheritance is rare. Also, we can't reliably determine whether\n    multiple inheritance actually occurs somewhere in a program, due to\n    stub files hiding implementation details, dynamic loading etc.\n\n    TODO: Don't consider tuples always overlapping.\n    TODO: Don't consider callables always overlapping.\n    TODO: Don't consider type variables with values always overlapping.\n    \"\"\"\n    # Any overlaps with everything\n    if isinstance(t, AnyType) or isinstance(s, AnyType):\n        return True\n\n    # Since we are effectively working with the erased types, we only\n    # need to handle occurrences of TypeVarType at the top level.\n    if isinstance(t, TypeVarType):\n        t = t.erase_to_union_or_bound()\n    if isinstance(s, TypeVarType):\n        s = s.erase_to_union_or_bound()\n    if isinstance(t, Instance):\n        if isinstance(s, Instance):\n            # Consider two classes non-disjoint if one is included in the mro\n            # of another.\n            if use_promotions:\n                # Consider cases like int vs float to be overlapping where\n                # there is only a type promotion relationship but not proper\n                # subclassing.\n                if t.type._promote and is_overlapping_types(t.type._promote, s):\n                    return True\n                if s.type._promote and is_overlapping_types(s.type._promote, t):\n                    return True\n            return t.type in s.type.mro or s.type in t.type.mro\n    if isinstance(t, UnionType):\n        return any(is_overlapping_types(item, s)\n                   for item in t.items)\n    if isinstance(s, UnionType):\n        return any(is_overlapping_types(t, item)\n                   for item in s.items)\n    if isinstance(t, TypeType) and isinstance(s, TypeType):\n        # If both types are TypeType, compare their inner types.\n        return is_overlapping_types(t.item, s.item, use_promotions)\n    elif isinstance(t, TypeType) or isinstance(s, TypeType):\n        # If exactly only one of t or s is a TypeType, check if one of them\n        # is an `object` or a `type` and otherwise assume no overlap.\n        other = s if isinstance(t, TypeType) else t\n        if isinstance(other, Instance):\n            return other.type.fullname() in {'builtins.object', 'builtins.type'}\n        else:\n            return False\n    if experiments.STRICT_OPTIONAL:\n        if isinstance(t, NoneTyp) != isinstance(s, NoneTyp):\n            # NoneTyp does not overlap with other non-Union types under strict Optional checking\n            return False\n    # We conservatively assume that non-instance, non-union, and non-TypeType types can overlap\n    # any other types.\n    return True\n\n\nclass TypeMeetVisitor(TypeVisitor[Type]):\n    def __init__(self, s: Type) -> None:\n        self.s = s\n\n    def visit_unbound_type(self, t: UnboundType) -> Type:\n        if isinstance(self.s, Void) or isinstance(self.s, ErrorType):\n            return ErrorType()\n        elif isinstance(self.s, NoneTyp):\n            if experiments.STRICT_OPTIONAL:\n                return AnyType()\n            else:\n                return self.s\n        elif isinstance(self.s, UninhabitedType):\n            return self.s\n        else:\n            return AnyType()\n\n    def visit_error_type(self, t: ErrorType) -> Type:\n        return t\n\n    def visit_type_list(self, t: TypeList) -> Type:\n        assert False, 'Not supported'\n\n    def visit_any(self, t: AnyType) -> Type:\n        return self.s\n\n    def visit_union_type(self, t: UnionType) -> Type:\n        if isinstance(self.s, UnionType):\n            meets = []  # type: List[Type]\n            for x in t.items:\n                for y in self.s.items:\n                    meets.append(meet_types(x, y))\n        else:\n            meets = [meet_types(x, self.s)\n                     for x in t.items]\n        return UnionType.make_simplified_union(meets)\n\n    def visit_void(self, t: Void) -> Type:\n        if isinstance(self.s, Void):\n            return t\n        else:\n            return ErrorType()\n\n    def visit_none_type(self, t: NoneTyp) -> Type:\n        if experiments.STRICT_OPTIONAL:\n            if isinstance(self.s, NoneTyp) or (isinstance(self.s, Instance) and\n                                               self.s.type.fullname() == 'builtins.object'):\n                return t\n            else:\n                return UninhabitedType()\n        else:\n            if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n                return t\n            else:\n                return ErrorType()\n\n    def visit_uninhabited_type(self, t: UninhabitedType) -> Type:\n        if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n            return t\n        else:\n            return ErrorType()\n\n    def visit_deleted_type(self, t: DeletedType) -> Type:\n        if not isinstance(self.s, Void) and not isinstance(self.s, ErrorType):\n            if isinstance(self.s, NoneTyp):\n                if experiments.STRICT_OPTIONAL:\n                    return t\n                else:\n                    return self.s\n            elif isinstance(self.s, UninhabitedType):\n                return self.s\n            else:\n                return t\n        else:\n            return ErrorType()\n\n    def visit_erased_type(self, t: ErasedType) -> Type:\n        return self.s\n\n    def visit_type_var(self, t: TypeVarType) -> Type:\n        if isinstance(self.s, TypeVarType) and self.s.id == t.id:\n            return self.s\n        else:\n            return self.default(self.s)\n\n    def visit_instance(self, t: Instance) -> Type:\n        if isinstance(self.s, Instance):\n            si = self.s\n            if t.type == si.type:\n                if is_subtype(t, self.s) or is_subtype(self.s, t):\n                    # Combine type arguments. We could have used join below\n                    # equivalently.\n                    args = []  # type: List[Type]\n                    for i in range(len(t.args)):\n                        args.append(self.meet(t.args[i], si.args[i]))\n                    return Instance(t.type, args)\n                else:\n                    if experiments.STRICT_OPTIONAL:\n                        return UninhabitedType()\n                    else:\n                        return NoneTyp()\n            else:\n                if is_subtype(t, self.s):\n                    return t\n                elif is_subtype(self.s, t):\n                    # See also above comment.\n                    return self.s\n                else:\n                    if experiments.STRICT_OPTIONAL:\n                        return UninhabitedType()\n                    else:\n                        return NoneTyp()\n        elif isinstance(self.s, TypeType):\n            return meet_types(t, self.s)\n        elif isinstance(self.s, TupleType):\n            return meet_types(t, self.s)\n        else:\n            return self.default(self.s)\n\n    def visit_callable_type(self, t: CallableType) -> Type:\n        if isinstance(self.s, CallableType) and is_similar_callables(t, self.s):\n            return combine_similar_callables(t, self.s)\n        else:\n            return self.default(self.s)\n\n    def visit_tuple_type(self, t: TupleType) -> Type:\n        if isinstance(self.s, TupleType) and self.s.length() == t.length():\n            items = []  # type: List[Type]\n            for i in range(t.length()):\n                items.append(self.meet(t.items[i], self.s.items[i]))\n            # TODO: What if the fallbacks are different?\n            return TupleType(items, t.fallback)\n        # meet(Tuple[t1, t2, <...>], Tuple[s, ...]) == Tuple[meet(t1, s), meet(t2, s), <...>].\n        elif (isinstance(self.s, Instance) and\n              self.s.type.fullname() == 'builtins.tuple' and self.s.args):\n            return t.copy_modified(items=[meet_types(it, self.s.args[0]) for it in t.items])\n        else:\n            return self.default(self.s)\n\n    def visit_typeddict_type(self, t: TypedDictType) -> Type:\n        if isinstance(self.s, TypedDictType):\n            for (_, l, r) in self.s.zip(t):\n                if not is_equivalent(l, r):\n                    return self.default(self.s)\n            items = OrderedDict([\n                (item_name, s_item_type or t_item_type)\n                for (item_name, s_item_type, t_item_type) in self.s.zipall(t)\n            ])\n            mapping_value_type = join_type_list(list(items.values()))\n            fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type)\n            return TypedDictType(items, fallback)\n        else:\n            return self.default(self.s)\n\n    def visit_partial_type(self, t: PartialType) -> Type:\n        # We can't determine the meet of partial types. We should never get here.\n        assert False, 'Internal error'\n\n    def visit_type_type(self, t: TypeType) -> Type:\n        if isinstance(self.s, TypeType):\n            typ = self.meet(t.item, self.s.item)\n            if not isinstance(typ, NoneTyp):\n                typ = TypeType(typ, line=t.line)\n            return typ\n        elif isinstance(self.s, Instance) and self.s.type.fullname() == 'builtins.type':\n            return t\n        else:\n            return self.default(self.s)\n\n    def meet(self, s: Type, t: Type) -> Type:\n        return meet_types(s, t)\n\n    def default(self, typ: Type) -> Type:\n        if isinstance(typ, UnboundType):\n            return AnyType()\n        elif isinstance(typ, Void) or isinstance(typ, ErrorType):\n            return ErrorType()\n        else:\n            if experiments.STRICT_OPTIONAL:\n                return UninhabitedType()\n            else:\n                return NoneTyp()\n", "path": "mypy/meet.py"}]}