Given the following example (using JUnit with Hamcrest matchers):

```
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));  

```

This does not compile with the JUnit `assertThat` method signature of:

```
public static <T> void assertThat(T actual, Matcher<T> matcher)

```

The compiler error message is:

```
Error:Error:line (102)cannot find symbol method
assertThat(java.util.Map<java.lang.String,java.lang.Class<java.util.Date>>,
org.hamcrest.Matcher<java.util.Map<java.lang.String,java.lang.Class
    <? extends java.io.Serializable>>>)

```

However, if I change the `assertThat` method signature to:

```
public static <T> void assertThat(T result, Matcher<? extends T> matcher)

```

Then the compilation works.

So three questions:

1. Why exactly doesn't the current version compile? Although I vaguely understand the covariance issues here, I certainly couldn't explain it if I had to.
2. Is there any downside in changing the `assertThat` method to `Matcher<? extends T>`? Are there other cases that would break if you did that?
3. Is there any point to the genericizing of the `assertThat` method in JUnit? The `Matcher` class doesn't seem to require it, since JUnit calls the matches method, which is not typed with any generic, and just looks like an attempt to force a type safety which doesn't do anything, as the `Matcher` will just not in fact match, and the test will fail regardless. No unsafe operations involved (or so it seems).

For reference, here is the JUnit implementation of `assertThat`:

```
public static <T> void assertThat(T actual, Matcher<T> matcher) {
    assertThat("", actual, matcher);
}

public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
    if (!matcher.matches(actual)) {
        Description description = new StringDescription();
        description.appendText(reason);
        description.appendText("\nExpected: ");
        matcher.describeTo(description);
        description
            .appendText("\n     got: ")
            .appendValue(actual)
            .appendText("\n");

        throw new java.lang.AssertionError(description.toString());
    }
}

```