Use binary semantics when __iadd__ et al are unbound (#13987)

## Summary

I noticed that augmented assignments on floats were yielding "not
supported" diagnostics. If the dunder isn't bound at all, we should use
binary operator semantics, rather than treating it as not-callable.
This commit is contained in:
Charlie Marsh 2024-10-30 09:09:22 -04:00 committed by GitHub
parent 71536a43db
commit 262c04f297
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 26 deletions

View file

@ -6,6 +6,10 @@
x = 3
x -= 1
reveal_type(x) # revealed: Literal[2]
x = 1.0
x /= 2
reveal_type(x) # revealed: float
```
## Dunder methods

View file

@ -1425,12 +1425,17 @@ impl<'db> TypeInferenceBuilder<'db> {
};
let value_type = self.infer_expression(value);
// If the target defines, e.g., `__iadd__`, infer the augmented assignment as a call to that
// dunder.
if let Type::Instance(class) = target_type {
let class_member = class.class_member(self.db, op.in_place_dunder());
if !class_member.is_unbound() {
let call = class_member.call(self.db, &[target_type, value_type]);
return match call.return_ty_result(self.db, AnyNodeRef::StmtAugAssign(assignment), self)
{
return match call.return_ty_result(
self.db,
AnyNodeRef::StmtAugAssign(assignment),
self,
) {
Ok(t) => t,
Err(e) => {
self.add_diagnostic(
@ -1446,6 +1451,7 @@ impl<'db> TypeInferenceBuilder<'db> {
}
};
}
}
let left_ty = target_type;
let right_ty = value_type;

View file

@ -28,30 +28,22 @@ static EXPECTED_DIAGNOSTICS: &[&str] = &[
// We don't support terminal statements in control flow yet:
"/src/tomllib/_parser.py:66:18: Name `s` used when possibly not defined",
"/src/tomllib/_parser.py:98:12: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:99:13: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:101:12: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:104:14: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:108:17: Conflicting declared types for `second_char`: Unknown, str | None",
"/src/tomllib/_parser.py:115:14: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:126:12: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:130:9: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:267:9: Conflicting declared types for `char`: Unknown, str | None",
"/src/tomllib/_parser.py:348:20: Name `nest` used when possibly not defined",
"/src/tomllib/_parser.py:353:5: Name `nest` used when possibly not defined",
"/src/tomllib/_parser.py:353:5: Method `__getitem__` of type `Unbound | @Todo` is not callable on object of type `Unbound | @Todo`",
"/src/tomllib/_parser.py:364:9: Conflicting declared types for `char`: Unknown, str | None",
"/src/tomllib/_parser.py:367:5: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:381:13: Conflicting declared types for `char`: Unknown, str | None",
"/src/tomllib/_parser.py:384:9: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:395:9: Conflicting declared types for `char`: Unknown, str | None",
"/src/tomllib/_parser.py:429:9: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:453:24: Name `nest` used when possibly not defined",
"/src/tomllib/_parser.py:455:9: Name `nest` used when possibly not defined",
"/src/tomllib/_parser.py:455:9: Method `__getitem__` of type `Unbound | @Todo` is not callable on object of type `Unbound | @Todo`",
"/src/tomllib/_parser.py:464:9: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:482:16: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:484:13: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:545:5: Operator `+=` is unsupported for type `int` with type `Literal[1]`",
"/src/tomllib/_parser.py:566:12: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:573:12: Name `char` used when possibly not defined",
"/src/tomllib/_parser.py:579:12: Name `char` used when possibly not defined",