(
self, lvalue: Lvalue, rvalue: Expression | None = None
)
| 4498 | self.msg.type_not_iterable(rvalue_type, context) |
| 4499 | |
| 4500 | def check_lvalue( |
| 4501 | self, lvalue: Lvalue, rvalue: Expression | None = None |
| 4502 | ) -> tuple[Type | None, IndexExpr | None, Var | None]: |
| 4503 | lvalue_type = None |
| 4504 | index_lvalue = None |
| 4505 | inferred = None |
| 4506 | |
| 4507 | # When revisiting the initial assignment (for example in a loop), |
| 4508 | # treat is as regular if redefinitions are allowed. |
| 4509 | skip_definition = ( |
| 4510 | self.options.allow_redefinition |
| 4511 | and isinstance(lvalue, NameExpr) |
| 4512 | and isinstance(lvalue.node, Var) |
| 4513 | and lvalue.node.is_inferred |
| 4514 | and lvalue.node.type is not None |
| 4515 | and not isinstance(lvalue.node.type, PartialType) |
| 4516 | # Indexes in for loops require special handling, we need to reset them to |
| 4517 | # a literal value on each loop, but binder doesn't work well with literals. |
| 4518 | and not lvalue.node.is_index_var |
| 4519 | ) |
| 4520 | |
| 4521 | if ( |
| 4522 | self.is_definition(lvalue) |
| 4523 | and (not isinstance(lvalue, NameExpr) or isinstance(lvalue.node, Var)) |
| 4524 | and not skip_definition |
| 4525 | ): |
| 4526 | if isinstance(lvalue, NameExpr): |
| 4527 | assert isinstance(lvalue.node, Var) |
| 4528 | inferred = lvalue.node |
| 4529 | else: |
| 4530 | assert isinstance(lvalue, MemberExpr) |
| 4531 | self.expr_checker.accept(lvalue.expr) |
| 4532 | inferred = lvalue.def_var |
| 4533 | elif isinstance(lvalue, IndexExpr): |
| 4534 | index_lvalue = lvalue |
| 4535 | elif isinstance(lvalue, MemberExpr): |
| 4536 | lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, True, rvalue) |
| 4537 | self.store_type(lvalue, lvalue_type) |
| 4538 | elif isinstance(lvalue, NameExpr): |
| 4539 | lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True) |
| 4540 | if ( |
| 4541 | self.options.allow_redefinition |
| 4542 | and isinstance(lvalue.node, Var) |
| 4543 | # We allow redefinition for function arguments inside function body. |
| 4544 | # Although we normally do this for variables without annotation, users |
| 4545 | # don't have a choice to leave a function argument without annotation. |
| 4546 | and (lvalue.node.is_inferred or lvalue.node.is_argument) |
| 4547 | ): |
| 4548 | inferred = lvalue.node |
| 4549 | self.store_type(lvalue, lvalue_type) |
| 4550 | elif isinstance(lvalue, (TupleExpr, ListExpr)): |
| 4551 | types = [ |
| 4552 | self.check_lvalue(sub_expr)[0] or |
| 4553 | # This type will be used as a context for further inference of rvalue, |
| 4554 | # we put Uninhabited if there is no information available from lvalue. |
| 4555 | UninhabitedType() |
| 4556 | for sub_expr in lvalue.items |
| 4557 | ] |
no test coverage detected