¿Cómo especifica JLS que los comodines no pueden usarse formalmente dentro de los métodos?

Siempre me he preguntado sobre algún aspecto extraño de los genéricos de Java y el uso de comodines. Digamos, tengo la siguiente API:

public interface X<E> {
    E get();
    E set(E e);
}

Y luego, digamos que declaramos los siguientes métodos:

public class Foo {
    public void foo(X<?> x) {
        // This does not compile:
        x.set(x.get());
    }

    public <T> void bar(X<T> x) {
        // This compiles:
        x.set(x.get());
    }
}

De mi comprensión "intuitiva",X<?> es de hecho lo mismo queX<T>, salvo que lo desconocido<T> esformalmente desconocido para el código del cliente. Pero dentro defoo(), Supongo que el compilador podría inferir (pseudo código JLS)<T0> := <?>[0], <T1> := <?>[1], etc.... Esto es lo que hace la mayoría de los programadores de forma explícita e intuitiva. Ellos delegan a un método de ayuda privada, lo que lleva a un montón de código inútil de caldera:

public class Foo {
    public void foo(X<?> x) {
        foo0(x);
    }

    private <T> void foo0(X<T> x) {
        x.set(x.get());
    }
}

Otro ejemplo:

public class Foo {
    public void foo() {
        // Assuming I could instanciate X
        X<?> x = new X<Object>();
        // Here, I cannot simply add a generic type to foo():
        // I have no choice but to introduce a useless foo0() helper method
        x.set(x.get());
    }
}

En otras palabras, el compilador sabe que el comodín enx.set() es formalmente el mismo que el comodín enx.get(). ¿Por qué no puede usar esa información? ¿Hay un aspecto formal en elJLS, eso explica esta falta de compilador "característica"?

Respuestas a la pregunta(3)

Su respuesta a la pregunta