Fix bug mentioned in issue 201 —— bug of contains(contains(any class instance),empty()) #369
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #201
Hi! This description is somewhat verbose but sufficiently detailed. It would be my pleasure if you could read it. I am a student in class Software Engineering and I am trying to fix the bug mentioned in issue 201. After learning @brownian-motion and @tumbarumba's point of view and reading the source code, I found this bug is caused by the improper use of generics.
This bug is caused when we use
contains(contains(<any class instance>),empty()))
whereempty()
is org.hamcrest.Matchers.empty().contains()
has four override methods. Our expectation is that intercontains()
will call methodpublic static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(E... items)
with a calss instance as parameter, outercontains()
will call methodpublic static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E>... itemMatcher)
with two matchers as parameters and outercontains()
should return anorg.hamcrest.Matcher<java.lang.Iterable<? extends E>>
which is used to match.In fact, it is not what we expect. To call
org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E>... itemMatcher)
parameters of outercontains()
should all beMatcher<? super E>
with same generic type E. Howerver, class of return variable of innercontains(<any class instance>)
isMatcher<Iterable<? extends Integer>>
and class of return variable ofempty()
isMatcher<Collection<?>>
. In my IDE, it hints that type parameter E of outercontains()
has incompatible upper bounds, which leads outercontains()
call methodpublic static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(E... items)
and embed parameter Matcher into another Matcher. There are two main ways to fix it without modifying resource code that is usingcontains(contains(<any class instance>),(Matcher)empty()))
orcontains(contains(<any class instance>),Matcher.<Class(corresponding to class instance)>empty()))
. Obviously, it's ugly and unamiable for beginner.Based on all the things above, I fix this bug just by changing the return type of org.hamcrest.Matchers.empty() as
org.hamcrest.Matcher
and the initial return type isorg.hamcrest.Matcher<Collection<? extends E>>
. This won't introduce new bug becauseempty()
is a static method in org.hamcrest.Matchers and has no parameter, which make empty() won't hold a type parameter without explicit declaration such ascontains(contains(<any class instance>),Matcher.<Class(corresponding to class instance)>empty()))
. What's more ,empty()
just return a new InEmptyCollection() without type parameter in essence. In conclusion, I believe this modification can fix this bug and won't introduce new bug.