[ty] Infer `bool` for `not` applied to dynamic values (#25445)
## Summary
Prior to this change, we treated all unary operations applied to a
dynamic value as producing the same dynamic type. This is appropriate
for `+`, `-`, and `~`, whose dunder implementations may return arbitrary
values, but not for `not`: Python always produces a `bool` after
evaluating its operand's truthiness.
```python
from typing import Any, reveal_type
def check(value: Any) -> None:
result = reveal_type(not value) # bool
result.nonexistent() # error: `bool` has no attribute `nonexistent`
```
We now allow `not` on dynamic operands to use the existing
truthiness-inference path, while retaining dynamic propagation for the
other unary operators. This restores downstream checking of the
resulting boolean value.
Closes https://github.com/astral-sh/ty/issues/3572. C
Charlie Marsh committed
47d742f520dc6352209710dcad9b40d55c0f3b44
Parent: ae44d57
Committed by GitHub <noreply@github.com>
on 5/29/2026, 7:29:56 AM