## Summary
Support narrowing for a few more already-supported sites, but in the
context of a walrus, as in:
```python
def f(t: tuple[int, int] | tuple[None, None]):
if (first := t[0]) is not None:
reveal_type(first) # int
reveal_type(t) # tuple[int, int]
else:
reveal_type(first) # None
reveal_type(t) # tuple[None, None]
```
Improves https://github.com/astral-sh/ruff/pull/22633 to infer the use
of lambda parameters in a lambda body with type context, e.g.,
```py
x: Callable[[str], str] = lambda x: reveal_type(x) # revealed: str
reveal_type(x) # revealed: (x: str) -> str
```
Unlike other definitions, lambda parameter types cannot be determined
purely syntactically in semantic indexing. Instead, they depend on the
inferred type of the lambda to access its parameter types.
Unfortunately, this makes lambda inference cyclic, as the body of the
lambda depends on the outer lambda type, and there is no obvious way of
splitting out inference of the lambda parameter types from its return
type.
To avoid initiating cycles on the entire scope containing the lambda,
this PR introduces a new inference query — statement-level inference.
Statements are a minimal unit of code that encapsulate any internal type
context. This makes them very useful to infer a given sub-expression
"naturally" without having to provide any external type context. There
are other places where we currently rely on scope-level inference for
this purpose (e.g., see `infer_complete_scope_types`, the current
implementation of https://github.com/astral-sh/ruff/pull/23761, and the
discussion in https://github.com/astral-sh/ty/issues/3124). Note that
statement-level inference is not perfectly fine-grained, e.g., the test
expression of an `if` statement does not require external type context
and is independent from its body, so statement-level inference may lead
to unnecessarily large cycles, but having the unit of code being
generalized to an AST structure allows us to avoid the need for such
special cases, but this can always change in the future.
Additionally, many statements are simply wrappers around definitions or
standalone expressions, so we can avoid extra salsa allocations in the
common case.
## Summary
If a `TypeGuard` is being used to narrow a method, we assume that the
guard applies to the first argument of the call (e.g., `x` in `f(x)`).
But if the call is an unbound method, it needs to be applied to the
_second_ argument, as in `C.f(C(), x)`, since the first argument is the
receiver.