In this case it's not true. They are equivalent. The assert can't possibly fire. The bounds checks can't possibly fail. The compiler is just not smart enough to figure it out.
We know that len > 0 (because of the is_empty() check), therefore len - 1 doesn't overflow. i < len - 1. Therefore len - i > 1 and the slice can't be empty.
Of course if we ignore surrounding context they might not be equivalent, which is probably what you meant, but that's a different story. Many optimizations have to look at some information from the context.
I'm a bit disappointed with the compiler failing at analyzing such simple inequalities. This sort of never failing bounds checks are pretty common, it would help optimize a lot of code if the compiler could get rid of them.
Of course, the concrete code OP posted is written correctly so the assert can't fire. But in general, what I wrote is true: an upfront assertion doesn't necessarily behave the same as a failing bounds check in the middle of the loop. It is also true that the very obvious structure of the assertion is easier for the compiler to optimize.