# Buggy code
def check_boolean_op(self, e: OpExpr, context: Context) -> Type:
    """Type check a boolean operation ('and' or 'or')."""

    # A boolean operation can evaluate to either of the operands.

    # We use the current type context to guide the type inference of of
    # the left operand. We also use the left operand type to guide the type
    # inference of the right operand so that expressions such as
    # '[1] or []' are inferred correctly.
    ctx = self.chk.type_context[-1]
    left_type = self.accept(e.left, ctx)

    assert e.op in ("and", "or")  # Checked by visit_op_expr

    if e.op == "and":
        right_map, left_map = mypy.checker.find_isinstance_check(
            e.left, self.chk.type_map
        )
        restricted_left_type = false_only(left_type)
        result_is_left = not left_type.can_be_true
    elif e.op == "or":
        left_map, right_map = mypy.checker.find_isinstance_check(
            e.left, self.chk.type_map
        )
        restricted_left_type = true_only(left_type)
        result_is_left = not left_type.can_be_false

    with self.chk.binder.frame_context():
        if right_map:
            for var, type in right_map.items():
                self.chk.binder.push(var, type)

        right_type = self.accept(e.right, left_type)

    self.check_usable_type(left_type, context)
    self.check_usable_type(right_type, context)

    if right_map is None:
        # The boolean expression is statically known to be the left value
        assert left_map is not None  # find_isinstance_check guarantees this
        return left_type
    if left_map is None:
        # The boolean expression is statically known to be the right value
        assert right_map is not None  # find_isinstance_check guarantees this
        return right_type

    if isinstance(restricted_left_type, UninhabitedType):
        # The left operand can never be the result
        return right_type
    elif result_is_left:
        # The left operand is always the result
        return left_type
    else:
        return UnionType.make_simplified_union([restricted_left_type, right_type])


# Traceback (AttributeError)
Traceback (most recent call last):
File "./scripts/mypy", line 6, in <module>
main(__file__)
File "mypy/mypy/main.py", line 50, in main
type_check_only(sources, bin_dir, options)
File "mypy/mypy/main.py", line 94, in type_check_only
python_path=options.python_path)
File "mypy/mypy/build.py", line 210, in build
result = manager.process(initial_states)
File "mypy/mypy/build.py", line 425, in process
next.process()
File "mypy/mypy/build.py", line 930, in process
self.type_checker().visit_file(self.tree, self.tree.path)
File "mypy/mypy/checker.py", line 409, in visit_file
self.accept(d)
File "mypy/mypy/checker.py", line 450, in accept
typ = node.accept(self)
File "mypy/mypy/nodes.py", line 707, in accept
return visitor.visit_try_stmt(self)
File "mypy/mypy/checker.py", line 1732, in visit_try_stmt
self.accept(s.else_body)
File "mypy/mypy/checker.py", line 450, in accept
typ = node.accept(self)
File "mypy/mypy/nodes.py", line 526, in accept
return visitor.visit_block(self)
File "mypy/mypy/checker.py", line 1113, in visit_block
self.accept(s)
File "mypy/mypy/checker.py", line 450, in accept
typ = node.accept(self)
File "mypy/mypy/nodes.py", line 382, in accept
return visitor.visit_func_def(self)
File "mypy/mypy/checker.py", line 594, in visit_func_def
'redefinition with type')
File "mypy/mypy/checker.py", line 2117, in check_subtype
if not is_subtype(subtype, supertype):
File "mypy/mypy/subtypes.py", line 49, in is_subtype
return left.accept(SubtypeVisitor(right, type_parameter_checker))
AttributeError: 'NoneType' object has no attribute 'accept'

# Fixed code
def check_boolean_op(self, e: OpExpr, context: Context) -> Type:
    """Type check a boolean operation ('and' or 'or')."""

    # A boolean operation can evaluate to either of the operands.

    # We use the current type context to guide the type inference of of
    # the left operand. We also use the left operand type to guide the type
    # inference of the right operand so that expressions such as
    # '[1] or []' are inferred correctly.
    ctx = self.chk.type_context[-1]
    left_type = self.accept(e.left, ctx)

    assert e.op in ("and", "or")  # Checked by visit_op_expr

    if e.op == "and":
        right_map, left_map = self.chk.find_isinstance_check(e.left)
        restricted_left_type = false_only(left_type)
        result_is_left = not left_type.can_be_true
    elif e.op == "or":
        left_map, right_map = self.chk.find_isinstance_check(e.left)
        restricted_left_type = true_only(left_type)
        result_is_left = not left_type.can_be_false

    right_type = self.analyze_cond_branch(right_map, e.right, left_type)

    self.check_usable_type(left_type, context)
    self.check_usable_type(right_type, context)

    if right_map is None:
        # The boolean expression is statically known to be the left value
        assert left_map is not None  # find_isinstance_check guarantees this
        return left_type
    if left_map is None:
        # The boolean expression is statically known to be the right value
        assert right_map is not None  # find_isinstance_check guarantees this
        return right_type

    if isinstance(restricted_left_type, UninhabitedType):
        # The left operand can never be the result
        return right_type
    elif result_is_left:
        # The left operand is always the result
        return left_type
    else:
        return UnionType.make_simplified_union([restricted_left_type, right_type])