# Buggy code
def check_member_assignment(
    self,
    instance_type: Type,
    attribute_type: Type,
    rvalue: Expression,
    context: Context,
) -> Tuple[Type, bool]:
    """Type member assigment.

    This is defers to check_simple_assignment, unless the member expression
    is a descriptor, in which case this checks descriptor semantics as well.

    Return the inferred rvalue_type and whether to infer anything about the attribute type
    """
    # Descriptors don't participate in class-attribute access
    if (
        isinstance(instance_type, FunctionLike) and instance_type.is_type_obj()
    ) or isinstance(instance_type, TypeType):
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    if not isinstance(attribute_type, Instance):
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    if not attribute_type.type.has_readable_member("__set__"):
        # If there is no __set__, we type-check that the assigned value matches
        # the return type of __get__. This doesn't match the python semantics,
        # (which allow you to override the descriptor with any value), but preserves
        # the type of accessing the attribute (even after the override).
        if attribute_type.type.has_readable_member("__get__"):
            attribute_type = self.expr_checker.analyze_descriptor_access(
                instance_type, attribute_type, context
            )
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    dunder_set = attribute_type.type.get_method("__set__")
    if dunder_set is None:
        self.msg.fail("{}.__set__ is not callable".format(attribute_type), context)
        return AnyType(TypeOfAny.from_error), False

    function = function_type(dunder_set, self.named_type("builtins.function"))
    bound_method = bind_self(function, attribute_type)
    typ = map_instance_to_supertype(attribute_type, dunder_set.info)
    dunder_set_type = expand_type_by_instance(bound_method, typ)

    _, inferred_dunder_set_type = self.expr_checker.check_call(
        dunder_set_type,
        [TempNode(instance_type), rvalue],
        [nodes.ARG_POS, nodes.ARG_POS],
        context,
    )

    if not isinstance(inferred_dunder_set_type, CallableType):
        self.fail("__set__ is not callable", context)
        return AnyType(TypeOfAny.from_error), True

    if len(inferred_dunder_set_type.arg_types) < 2:
        # A message already will have been recorded in check_call
        return AnyType(TypeOfAny.from_error), False

    return inferred_dunder_set_type.arg_types[1], False


# Traceback (AssertionError)
mypy --py2 --show-traceback test.py

test.py:6: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.521-858f7512cf3b4e39c0f4e8de5a13eee0e1e138fb-dirty
Traceback (most recent call last):
File "/usr/local/Cellar/mypy/0.521/libexec/bin/mypy", line 11, in <module>
load_entry_point('mypy===0.521-858f7512cf3b4e39c0f4e8de5a13eee0e1e138fb-dirty', 'console_scripts', 'mypy')()
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
main(None)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/main.py", line 50, in main
res = type_check_only(sources, bin_dir, options)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/main.py", line 97, in type_check_only
options=options)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/build.py", line 196, in build
graph = dispatch(sources, manager)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/build.py", line 1801, in dispatch
process_graph(graph, manager)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/build.py", line 2044, in process_graph
process_stale_scc(graph, scc, manager)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/build.py", line 2147, in process_stale_scc
graph[id].type_check_first_pass()
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/build.py", line 1716, in type_check_first_pass
self.type_checker.check_first_pass()
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 185, in check_first_pass
self.accept(d)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
stmt.accept(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/nodes.py", line 565, in accept
return visitor.visit_func_def(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 519, in visit_func_def
self.check_func_item(defn, name=defn.name())
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 578, in check_func_item
self.check_func_def(defn, typ, name)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 738, in check_func_def
self.accept(item.body)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
stmt.accept(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/nodes.py", line 815, in accept
return visitor.visit_block(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1202, in visit_block
self.accept(s)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
stmt.accept(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/nodes.py", line 859, in accept
return visitor.visit_assignment_stmt(self)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1209, in visit_assignment_stmt
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1236, in check_assignment
infer_lvalue_type)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1483, in check_assignment_to_multiple_lvalues
self.check_multi_assignment(lvalues, rvalue, context, infer_lvalue_type)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1522, in check_multi_assignment
context, undefined_rvalue, infer_lvalue_type)
File "/usr/local/Cellar/mypy/0.521/libexec/lib/python3.6/site-packages/mypy/checker.py", line 1550, in check_multi_assignment_from_tuple
assert isinstance(reinferred_rvalue_type, TupleType)
AssertionError:
test.py:6: note: use --pdb to drop into pdb

# Fixed code
def check_member_assignment(
    self,
    instance_type: Type,
    attribute_type: Type,
    rvalue: Expression,
    context: Context,
) -> Tuple[Type, bool]:
    """Type member assigment.

    This defers to check_simple_assignment, unless the member expression
    is a descriptor, in which case this checks descriptor semantics as well.

    Return the inferred rvalue_type and whether to infer anything about the attribute type
    """
    # Descriptors don't participate in class-attribute access
    if (
        isinstance(instance_type, FunctionLike) and instance_type.is_type_obj()
    ) or isinstance(instance_type, TypeType):
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    if not isinstance(attribute_type, Instance):
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    if not attribute_type.type.has_readable_member("__set__"):
        # If there is no __set__, we type-check that the assigned value matches
        # the return type of __get__. This doesn't match the python semantics,
        # (which allow you to override the descriptor with any value), but preserves
        # the type of accessing the attribute (even after the override).
        if attribute_type.type.has_readable_member("__get__"):
            attribute_type = self.expr_checker.analyze_descriptor_access(
                instance_type, attribute_type, context
            )
        rvalue_type = self.check_simple_assignment(attribute_type, rvalue, context)
        return rvalue_type, True

    dunder_set = attribute_type.type.get_method("__set__")
    if dunder_set is None:
        self.msg.fail("{}.__set__ is not callable".format(attribute_type), context)
        return AnyType(TypeOfAny.from_error), False

    function = function_type(dunder_set, self.named_type("builtins.function"))
    bound_method = bind_self(function, attribute_type)
    typ = map_instance_to_supertype(attribute_type, dunder_set.info)
    dunder_set_type = expand_type_by_instance(bound_method, typ)

    _, inferred_dunder_set_type = self.expr_checker.check_call(
        dunder_set_type,
        [TempNode(instance_type), rvalue],
        [nodes.ARG_POS, nodes.ARG_POS],
        context,
    )

    if not isinstance(inferred_dunder_set_type, CallableType):
        self.fail("__set__ is not callable", context)
        return AnyType(TypeOfAny.from_error), True

    if len(inferred_dunder_set_type.arg_types) < 2:
        # A message already will have been recorded in check_call
        return AnyType(TypeOfAny.from_error), False

    return inferred_dunder_set_type.arg_types[1], False