I think that it is compile time determination of what is being called.
In the gen_all case, it is known that it is a VerseRange and that VerseRange has a more specific contains(Verse). So that is called.
In the gen_allKey case, it is no longer a VerseRange but a Key (which should not know anything about a Verse, since it is supposed to work for all kinds of Keys). So it cannot call contains(Verse) but only contains(Key).
There are specific contains() implementations in VerseRange.
The second is being called but returns false because key is not a VerseRange. If the implementation of VerseRange.contains(Key) is the problem then another clause added at the end of the method might be one way to fix it, like:
I've been mulling over whether it is a sufficient solution. There are other "Key"s that hold verses (i.e. Passage and it ilk). A VerseRange can certainly contain all the Verses in a Passage. For example, a VerseRange of Genesis 1 contains a Passage of Gen 1:1-2 and Gen 1:10. I don't think this is at all common in real code, but it is possible.