6943278: spurious error message for inference and type-variable with erroneous bound

Mon, 24 Jan 2011 15:44:15 +0000

author
mcimadamore
date
Mon, 24 Jan 2011 15:44:15 +0000
changeset 828
19c900c703c6
parent 827
b6f95173e769
child 829
ce6175cfe11e

6943278: spurious error message for inference and type-variable with erroneous bound
Summary: type-inference should ignore erroneous bounds
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Type.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Infer.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6943278/T6943278.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6943278/T6943278.out file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java	Wed Jan 19 19:01:35 2011 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Jan 24 15:44:15 2011 +0000
     1.3 @@ -365,6 +365,16 @@
     1.4          return false;
     1.5      }
     1.6  
     1.7 +    public static List<Type> filter(List<Type> ts, Filter<Type> tf) {
     1.8 +        ListBuffer<Type> buf = ListBuffer.lb();
     1.9 +        for (Type t : ts) {
    1.10 +            if (tf.accepts(t)) {
    1.11 +                buf.append(t);
    1.12 +            }
    1.13 +        }
    1.14 +        return buf.toList();
    1.15 +    }
    1.16 +
    1.17      public boolean isSuperBound() { return false; }
    1.18      public boolean isExtendsBound() { return false; }
    1.19      public boolean isUnbound() { return false; }
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jan 19 19:01:35 2011 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jan 24 15:44:15 2011 +0000
     2.3 @@ -800,7 +800,8 @@
     2.4                  Type actual = types.subst(args.head,
     2.5                      type.tsym.type.getTypeArguments(),
     2.6                      tvars_buf.toList());
     2.7 -                if (!checkExtends(actual, (TypeVar)tvars.head)) {
     2.8 +                if (!checkExtends(actual, (TypeVar)tvars.head) &&
     2.9 +                        !tvars.head.getUpperBound().isErroneous()) {
    2.10                      return args.head;
    2.11                  }
    2.12                  args = args.tail;
    2.13 @@ -808,11 +809,15 @@
    2.14              }
    2.15  
    2.16              args = type.getTypeArguments();
    2.17 +            tvars = tvars_buf.toList();
    2.18  
    2.19              for (Type arg : types.capture(type).getTypeArguments()) {
    2.20 -                if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
    2.21 +                if (arg.tag == TYPEVAR &&
    2.22 +                        arg.getUpperBound().isErroneous() &&
    2.23 +                        !tvars.head.getUpperBound().isErroneous()) {
    2.24                      return args.head;
    2.25                  }
    2.26 +                tvars = tvars.tail;
    2.27              }
    2.28  
    2.29              return null;
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jan 19 19:01:35 2011 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jan 24 15:44:15 2011 +0000
     3.3 @@ -205,19 +205,20 @@
     3.4       *  Throw a NoInstanceException if this not possible.
     3.5       */
     3.6      void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
     3.7 +        List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
     3.8          if (that.inst == null) {
     3.9 -            if (that.hibounds.isEmpty())
    3.10 +            if (hibounds.isEmpty())
    3.11                  that.inst = syms.objectType;
    3.12 -            else if (that.hibounds.tail.isEmpty())
    3.13 -                that.inst = that.hibounds.head;
    3.14 +            else if (hibounds.tail.isEmpty())
    3.15 +                that.inst = hibounds.head;
    3.16              else
    3.17 -                that.inst = types.glb(that.hibounds);
    3.18 +                that.inst = types.glb(hibounds);
    3.19          }
    3.20          if (that.inst == null ||
    3.21              that.inst.isErroneous())
    3.22              throw ambiguousNoInstanceException
    3.23                  .setMessage("no.unique.maximal.instance.exists",
    3.24 -                            that.qtype, that.hibounds);
    3.25 +                            that.qtype, hibounds);
    3.26      }
    3.27      //where
    3.28          private boolean isSubClass(Type t, final List<Type> ts) {
    3.29 @@ -241,37 +242,46 @@
    3.30              return true;
    3.31          }
    3.32  
    3.33 +    private Filter<Type> errorFilter = new Filter<Type>() {
    3.34 +        @Override
    3.35 +        public boolean accepts(Type t) {
    3.36 +            return !t.isErroneous();
    3.37 +        }
    3.38 +    };
    3.39 +
    3.40      /** Instantiate undetermined type variable to the lub of all its lower bounds.
    3.41       *  Throw a NoInstanceException if this not possible.
    3.42       */
    3.43      void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
    3.44 +        List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
    3.45          if (that.inst == null) {
    3.46 -            if (that.lobounds.isEmpty())
    3.47 +            if (lobounds.isEmpty())
    3.48                  that.inst = syms.botType;
    3.49 -            else if (that.lobounds.tail.isEmpty())
    3.50 -                that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head;
    3.51 +            else if (lobounds.tail.isEmpty())
    3.52 +                that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
    3.53              else {
    3.54 -                that.inst = types.lub(that.lobounds);
    3.55 +                that.inst = types.lub(lobounds);
    3.56              }
    3.57              if (that.inst == null || that.inst.tag == ERROR)
    3.58                      throw ambiguousNoInstanceException
    3.59                          .setMessage("no.unique.minimal.instance.exists",
    3.60 -                                    that.qtype, that.lobounds);
    3.61 +                                    that.qtype, lobounds);
    3.62              // VGJ: sort of inlined maximizeInst() below.  Adding
    3.63              // bounds can cause lobounds that are above hibounds.
    3.64 -            if (that.hibounds.isEmpty())
    3.65 +            List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
    3.66 +            if (hibounds.isEmpty())
    3.67                  return;
    3.68              Type hb = null;
    3.69 -            if (that.hibounds.tail.isEmpty())
    3.70 -                hb = that.hibounds.head;
    3.71 -            else for (List<Type> bs = that.hibounds;
    3.72 +            if (hibounds.tail.isEmpty())
    3.73 +                hb = hibounds.head;
    3.74 +            else for (List<Type> bs = hibounds;
    3.75                        bs.nonEmpty() && hb == null;
    3.76                        bs = bs.tail) {
    3.77 -                if (isSubClass(bs.head, that.hibounds))
    3.78 +                if (isSubClass(bs.head, hibounds))
    3.79                      hb = types.fromUnknownFun.apply(bs.head);
    3.80              }
    3.81              if (hb == null ||
    3.82 -                !types.isSubtypeUnchecked(hb, that.hibounds, warn) ||
    3.83 +                !types.isSubtypeUnchecked(hb, hibounds, warn) ||
    3.84                  !types.isSubtypeUnchecked(that.inst, hb, warn))
    3.85                  throw ambiguousNoInstanceException;
    3.86          }
    3.87 @@ -528,7 +538,8 @@
    3.88          for (List<Type> tvs = tvars, args = arguments;
    3.89               tvs.nonEmpty();
    3.90               tvs = tvs.tail, args = args.tail) {
    3.91 -            if (args.head instanceof UndetVar) continue;
    3.92 +            if (args.head instanceof UndetVar ||
    3.93 +                    tvars.head.getUpperBound().isErroneous()) continue;
    3.94              List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
    3.95              if (!types.isSubtypeUnchecked(args.head, bounds, warn))
    3.96                  throw invalidInstanceException
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/tools/javac/generics/inference/6943278/T6943278.java	Mon Jan 24 15:44:15 2011 +0000
     4.3 @@ -0,0 +1,12 @@
     4.4 +/**
     4.5 + * @test /nodynamiccopyright/
     4.6 + * @bug 6943278
     4.7 + * @summary spurious error message for inference and type-variable with erroneous bound
     4.8 + * @compile/fail/ref=T6943278.out -XDrawDiagnostics -Xlint:unchecked T6943278.java
     4.9 + */
    4.10 +class T6943278<X extends Number & NonExistentInterface> {
    4.11 +    <X> T6943278<X> m() { return null;}
    4.12 +    <X extends Number & NonExistentInterface> T6943278<X> m(X x) { return null;}
    4.13 +    T6943278<?> f1 = m();
    4.14 +    T6943278<?> f2 = m("");
    4.15 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/tools/javac/generics/inference/6943278/T6943278.out	Mon Jan 24 15:44:15 2011 +0000
     5.3 @@ -0,0 +1,3 @@
     5.4 +T6943278.java:7:35: compiler.err.cant.resolve: kindname.class, NonExistentInterface, , 
     5.5 +T6943278.java:9:25: compiler.err.cant.resolve.location: kindname.class, NonExistentInterface, , , kindname.class, T6943278<X>
     5.6 +2 errors

mercurial