Skip to content

__iadd__ doesn't work when going through a Dict or List #2046

Closed

Description

@euresti

class A(object):
    def __init__(self):
        self.a = 0

    def __iadd__(self, a):
        # type: (int) -> A
        self.a += 1
        return self

a = A()
a += 1

b = {0: a}
b[0] += 1

c = [a]
c[0] += 1

print(a.a)

Yields the following errors:

rt1.py:15: error: Incompatible types in assignment (expression has type "int", target has type "A")
rt1.py:18: error: No overload variant of "__setitem__" of "list" matches argument types [builtins.int, builtins.int]

Activity

  1. gnprice commented on Aug 24, 2016

    @gnprice
    Collaborator

    Thanks for reporting this bug!

    On a bit of debugging, here's the relevant logic:
    https://github.com/python/mypy/blob/897398eff/mypy/checker.py#L1556

        def visit_operator_assignment_stmt(self,
                                           s: OperatorAssignmentStmt) -> Type:
            """Type check an operator assignment statement, e.g. x += 1."""
            lvalue_type = self.accept(s.lvalue)
            method = infer_operator_assignment_method(lvalue_type, s.op)
            rvalue_type, method_type = self.expr_checker.check_op(
                method, lvalue_type, s.rvalue, s)
    
            if isinstance(s.lvalue, IndexExpr):
                self.check_indexed_assignment(s.lvalue, s.rvalue, s.rvalue)
            else:
                if not is_subtype(rvalue_type, lvalue_type):
                    self.msg.incompatible_operator_assignment(s.op, s)
    

    I think the issue is that when s.lvalue is an IndexExpr, we forget the possibility that the lvalue actually has an in-place method for this operator and we attempt to check an outright assignment. (I'm not convinced it's quite right even when there isn't an in-place method -- that check_indexed_assignment line goes and type-checks it as if we're assigning the type of the actual RHS, rather than rvalue_type which is the type the operator returns -- but that'd be a separate issue.)

    Will see if I can work up an easy fix.

  2. added a commit that references this issue on Aug 24, 2016
    883b8de
  3. added a commit that references this issue on Aug 24, 2016
    3a8aaa1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions