First, using return in those positions is unidiomatic.
Anyway, the lifetime annotation on RwLockReadGuard<'a, Vec<Connection>> is only an upper bound on how long the read guard can live. The guard is allowed to live shorter than that annotation. This means that you cannot produce a borrow into the insides of the guard annotated by that lifetime, since that borrow could then live longer than the guard, even if the cannot outlive 'a, which would be unsound. Consider reading this. To get around this, your iterator would have to be a borrow of the read guard.
That said, does your Connection type happen to contain IO primitives such as a TcpStream? In that case please be aware that letting IO primitives be owned by a single task and using channels for communication is almost always better than putting it behind some kind of lock.
On the other hand I am thinking about other designs. I could have a function that takes a lambda for_each<F>(mut f: F) where F: FnMut(). Here I probably can not execute async operations in the lambda? But I am more and more convinced that it would not make a lot of sense anyway to do slow IO in a lock.
To your last point: no there are no IO primitives behind the lock in this case, but thanks for the info. I will keep that in mind.
Unfortunately, it is not possible with the exact api you want. This is because the iterator must be a borrow of the guard, and you can't return something and a reference to that something at once. That said, it is possible to return something you can turn into an iterator.