[ty] Treat non-empty `range` calls as non-empty for reachability (#25220)
## Summary
This PR productionizes one of @AlexWaygood's suggestions whereby we
special-case `range` to detect that certain loops must trigger at least
one iteration, which in turn allows us to avoid false positives around
"possibly unbound" variables defined within that loop.
For example:
```python
for x in range(42):
pass
reveal_type(x) # revealed: int
```
This PR handles two- and three-argument ranges like `range(1, 3)` and
`range(3, 0, -1)`, while leaving other
iterables and dynamic `range(count)` loops on the existing
possibly-empty path.