Programming with generics is not always easy, but it does make your code extremely flexible. When you use something such as generics, you are always making a trade-off between the simplicity of your program and the flexibility of your code. Sometimes it's worth it to introduce a little bit of complexity to allow your code to be written in ways that were otherwise impossible.
For instance, consider the Cow struct you saw before. To specify the generic associated type on the HerbivoreType protocol, a type alias was added to the Cow struct. Now imagine that not all cows like to eat grass. Maybe some cows prefer flowers, corn, or something else. You would not be able to express this using the type alias.
To represent a case where you might want to use a different type of PlantType for every cow instance, you can add a generic to the Cow itself...