[ty] Error context for not-iterable diagnostics (#24944)
## Summary
The iteration protocol (lowercase) is pretty complex, which is why we
cannot simply check if something is iterable by trying assignability to
some Protocol (uppercase). But in some cases, something is not iterable
because it doesn't follow the semantics of the normal `Iterable`
Protocol (again, uppercase).
In those cases, we can use the existing error context machinery to
provide more information about why something is not iterable. One
complication here is that the `typing.Iterable`/`typing.Iterator`
hierarchy in typeshed wants an `__iter__` method on `Iterator`(!), which
is [mandated](https://docs.python.org/3/glossary.html#term-iterator) by
iterator protocol (lowercase), but often not provided in practice. Here,
we solve this by adding new variants of these protocols in
`ty_extensions` for the sole purpose of generating these assignability
error context trees.
## Test Plan
New and updated Markdown tests