JDK-7143880 : Attr.java has an unsoundness in method arguments attribution
  • Type: Sub-task
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: unknown
  • Submitted: 2012-02-08
  • Updated: 2012-09-28
  • Resolved: 2012-03-05
Description
The following code compiles even if it shouldn't:

1)

class Foo<X> {
 X x;
}

class Test {
   void m(int i) {   }

   void test(Foo<? extends Integer> fi) {
      m(fi.x);
   }
}

2) 

class Test<T extends Integer> {
  void i(int arg) {}
  void foo(T arg) { i(arg); }
}

3) 

class CaptureTest {
  <T> List<T> singleton(T arg) { return null; }
  
  void test(List<? extends Number> l) {
    List<Number> ln = singleton(l.get(0));
  }

}

Comments
EVALUATION Fixing this is very hard as it leads to problems w.r.t. capture conversion. If we moved to a fully sound inference scheme, so that it wouldn't be necessary to check argument applicability twice, it would be possible, as a bonus to remove the irregularity described in this CR.
05-03-2012

EVALUATION This is caused by the fact that argument types are computed in a different way than other types - if the type of an expression is E, the type of the same expression occurring in method context is capture(upper(E)). This could have been done for two reasons: *) To avoid creating multiple captures of the same expression *) To help inference inferring types w/o type-variables Unfortunately, this makes the attribution code very irregular, and hard to evolve. However, even fixing the attribution code above, only (3) will be rejected - (1) and (2) will still be accepted as the javac unboxing conversion routine performs a widening followed by unboxing. This means that if we have: T, where T extends Integer and we want to go from T to int, javac allows that, as the boxed type Integer is a supertype of T. So, what javac effectively does is: T -> (widening) Integer -> (unboxing) int
08-02-2012