Skip to content

Fix augmented assignment on properties with asymmetric getter and setter - #22312

Open
quetzal-china wants to merge 1 commit into
python:masterfrom
quetzal-china:fix-augmented-assignment-asymmetric-property
Open

quetzal-china wants to merge 1 commit into
python:masterfrom
quetzal-china:fix-augmented-assignment-asymmetric-property

Conversation

@quetzal-china

Copy link
Copy Markdown

Fixes #22273

obj.prop += x evaluates as tmp = obj.prop (getter type), tmp = tmp.__iadd__(x) (or tmp = tmp + x), then obj.prop = tmp (checked against the setter type). Mypy resolved the operator from the lvalue type, which for a member lvalue is the setter type:

  • a setter type that does not implement the in-place method silently fell back to plain + on the getter type — Unsupported operand types for + even though the getter defines __iadd__
  • a union setter skipped the in-place path entirely (the in-place probe only handles Instance/TypedDictType), which is the exact repro from the issue
  • descriptors whose __set__ value type differs from their __get__ return type hit the same problem

This resolves the operator on the getter type and keeps the setter type for the read-only/final diagnostics and for the final Result type of + incompatible in assignment check.

Test cases in check-statements.test:

  • testInplaceOperatorAsymmetricProperty — the issue repro, now clean
  • testInplaceOperatorAsymmetricPropertyBadResult — a __iadd__ result not assignable to the setter still errors
  • testInplaceOperatorReadOnlyProperty — read-only property diagnostics preserved

The affected check suites pass on this Windows machine with the same six pre-existing stub-related failures as an unmodified checkout; self-check on mypy/checker.py is clean.

The runtime evaluates obj.prop += x by reading the attribute (getter
type), mutating it in place, and storing the result through the setter.
Mypy resolved the operator method from the lvalue type, which for a
member is the setter type: a setter without the in-place method fell
back to plain + on the getter type, and a union setter skipped the
in-place path entirely, producing false positives.

Resolve the operator on the getter type and keep the setter type for
the read-only/final diagnostics and the final assignment check.
@github-actions

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Augmented assignment on asymmetric property uses setter type to resolve __iadd__

1 participant