Because they don't. Your link even has an answer that highlights one way which they differ in expressivity - namely, that associated types don't appear in the instance head, so they can produce orphan instances where generics would not.
Consider the example of Rust's Iterator trait[0]. It has an associated type for the iteration item. It could have a generic type argument instead, but the two implementations would be different:
1. The associated type is a direct consequence of the instance head. That means that, for the type that Iterator is being implemented on, the associated type is known entirely from that type. If you have an iterable value, you know it only produces one kind of iterator item.
2. As a result, the associated-type version can only be implemented at most once. The generic version would be implementable any number of times, for any number of choices of type argument - and as a result, you would have to specify that you are iterating over an iterator with a particular choice of iterator item type, every time you iterate.
[0]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
You can still do similarly hellish impls with `Index` - especially if you mix `Deref` into it. IIRC, the compiler will perform automatic recursive derefs when you try to use the indexing operator `[]`, until it finds a deref target which matches the index you're using. I doubt anything relies on that search behaviour outside of the compiler code itself.
I imagine abuse of specialisation could also increase the confusion, if you were so inclined.
Consider the example of Rust's Iterator trait[0]. It has an associated type for the iteration item. It could have a generic type argument instead, but the two implementations would be different: