Type Inference is Causing Verification Error

Ming-Yee Iu mingyeeiu+lambda at gmail.com
Fri Sep 3 09:58:25 PDT 2010


I have a piece of code that seems to compile fine, but when I run it,
it generates a verification error.

I'm putting together a LINQish system for Java7, but the my system is
based only on bytecode analysis and uses no bytecode rewriting, so it
looks like a compiler problem (in fact, I haven't implemented nested
queries yet, so this piece of code was not successfully translated
into SQL by my system and was simply running directly).

Here is the code fragment that fails:

DBSet<Pair<Tuple3<Integer, String, String>, Integer>> matches =
 db.allDBOrderLine()
   .group(
     #(ol)
     {
       DBItem i = ol.getItem();
       DBAuthor a = i.getAuthor();
       return new Tuple3<Integer, String, String>(i.getItemId(),
i.getTitle(), a.getFirstName());
     },
     #(key, olset) {
       new Pair<Tuple3<Integer, String, String>, Integer>(
         key, olset.sumInt(#(ol){ol.getQuantity()}))}
   );

------
The definition of the group() method is

interface DBSet<T> extends Collection<T> {
...
  public static interface AggregateInteger<U> {
     public int aggregate(U val);
  }
  public int sumInt(AggregateInteger<T> aggregate);

 ...
  public static interface AggregateSelect<U, V> {
     public V aggregateSelect(DBSet<U> val);
  }
  public static interface AggregateGroup<W, U, V> {
     public V aggregateSelect(W key, DBSet<U> val);
  }
  public <U, V> DBSet<Pair<U, V>> group(Select<T, U> select,
AggregateGroup<U, T, V> aggregate);
}

------
The verification error is

Exception in thread "main" java.lang.VerifyError: Bad return type in
method Test$2.aggregateSelect(Lch/epfl/labos/iu/orm/Tuple3;Lch/epfl/labos/iu/orm/DBSet;)Ljava/lang/Integer;
at offset 25
       at Test.main(Test.java:12)


-----
The javap of Test$2 is


class Test$2 extends java.lang.Object implements
ch.epfl.labos.iu.orm.DBSet$AggregateGroup<ch.epfl.labos.iu.orm.Tuple3<java.lang.Integer,
java.lang.String, java.lang.String>,
ch.epfl.labos.iu.tpcw.entities.DBOrderLine, java.lang.Integer> {
 public java.lang.Integer
aggregateSelect(ch.epfl.labos.iu.orm.Tuple3<java.lang.Integer,
java.lang.String, java.lang.String>,
ch.epfl.labos.iu.orm.DBSet<ch.epfl.labos.iu.tpcw.entities.DBOrderLine>);
   Code:
      0: new           #2                  // class ch/epfl/labos/iu/orm/Pair
      3: dup
      4: aload_1
      5: aload_2
      6: new           #3                  // class Test$2$1
      9: dup
     10: aload_0
     11: invokespecial #4                  // Method
Test$2$1."<init>":(LTest$2;)V
     14: invokeinterface #5,  2            // InterfaceMethod
ch/epfl/labos/iu/orm/DBSet.sumInt:(Lch/epfl/labos/iu/orm/DBSet$AggregateInteger;)I
     19: invokestatic  #6                  // Method
java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     22: invokespecial #7                  // Method
ch/epfl/labos/iu/orm/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     25: areturn

 Test$2();
   Code:
      0: aload_0
      1: invokespecial #1                  // Method
java/lang/Object."<init>":()V
      4: return

 public java.lang.Object aggregateSelect(java.lang.Object,
ch.epfl.labos.iu.orm.DBSet);
   Code:
      0: aload_0
      1: aload_1
      2: checkcast     #8                  // class ch/epfl/labos/iu/orm/Tuple3
      5: aload_2
      6: invokevirtual #9                  // Method
aggregateSelect:(Lch/epfl/labos/iu/orm/Tuple3;Lch/epfl/labos/iu/orm/DBSet;)Ljava/lang/Integer;
      9: areturn
}

----

I may have gotten the generics in my definition of group() mixed up,
but my intention was for Test$2.aggregateSelect() to return a Pair and
not an Integer (in any case, the compiler should not generate code
that does not verify).

-Ming


More information about the lambda-dev mailing list