7175433: Inference cleanup: add helper class to handle inference variables

Tue, 25 Sep 2012 11:55:34 +0100

author
mcimadamore
date
Tue, 25 Sep 2012 11:55:34 +0100
changeset 1337
2eca84194807
parent 1336
26d93df3905a
child 1338
ad2ca2a4ab5e

7175433: Inference cleanup: add helper class to handle inference variables
Summary: Add class to handle inference variables instantiation and associated info
Reviewed-by: jjg, dlsmith

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
src/share/classes/com/sun/tools/javac/comp/Resolve.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6638712/T6638712c.out file | annotate | diff | comparison | revisions
test/tools/javac/varargs/6313164/T7175433.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Sep 25 11:53:18 2012 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Sep 25 11:55:34 2012 +0100
     1.3 @@ -40,6 +40,8 @@
     1.4  import com.sun.tools.javac.code.Lint.LintCategory;
     1.5  import com.sun.tools.javac.code.Type.*;
     1.6  import com.sun.tools.javac.code.Symbol.*;
     1.7 +import com.sun.tools.javac.comp.Infer.InferenceContext;
     1.8 +import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
     1.9  
    1.10  import static com.sun.tools.javac.code.Flags.*;
    1.11  import static com.sun.tools.javac.code.Flags.ANNOTATION;
    1.12 @@ -429,6 +431,8 @@
    1.13           * Obtain a warner for this check context
    1.14           */
    1.15          public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
    1.16 +
    1.17 +        public Infer.InferenceContext inferenceContext();
    1.18      }
    1.19  
    1.20      /**
    1.21 @@ -455,6 +459,10 @@
    1.22          public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
    1.23              return enclosingContext.checkWarner(pos, found, req);
    1.24          }
    1.25 +
    1.26 +        public Infer.InferenceContext inferenceContext() {
    1.27 +            return enclosingContext.inferenceContext();
    1.28 +        }
    1.29      }
    1.30  
    1.31      /**
    1.32 @@ -471,6 +479,10 @@
    1.33          public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
    1.34              return convertWarner(pos, found, req);
    1.35          }
    1.36 +
    1.37 +        public InferenceContext inferenceContext() {
    1.38 +            return infer.emptyContext;
    1.39 +        }
    1.40      };
    1.41  
    1.42      /** Check that a given type is assignable to a given proto-type.
    1.43 @@ -483,7 +495,16 @@
    1.44          return checkType(pos, found, req, basicHandler);
    1.45      }
    1.46  
    1.47 -    Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
    1.48 +    Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
    1.49 +        final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
    1.50 +        if (inferenceContext.free(req)) {
    1.51 +            inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
    1.52 +                @Override
    1.53 +                public void typesInferred(InferenceContext inferenceContext) {
    1.54 +                    checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
    1.55 +                }
    1.56 +            });
    1.57 +        }
    1.58          if (req.tag == ERROR)
    1.59              return req;
    1.60          if (req.tag == NONE)
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Sep 25 11:53:18 2012 +0100
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Sep 25 11:55:34 2012 +0100
     2.3 @@ -25,18 +25,21 @@
     2.4  
     2.5  package com.sun.tools.javac.comp;
     2.6  
     2.7 +import com.sun.tools.javac.code.*;
     2.8 +import com.sun.tools.javac.code.Symbol.*;
     2.9 +import com.sun.tools.javac.code.Type.*;
    2.10 +import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
    2.11 +import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
    2.12  import com.sun.tools.javac.tree.JCTree;
    2.13  import com.sun.tools.javac.tree.JCTree.JCTypeCast;
    2.14  import com.sun.tools.javac.tree.TreeInfo;
    2.15  import com.sun.tools.javac.util.*;
    2.16  import com.sun.tools.javac.util.List;
    2.17 -import com.sun.tools.javac.code.*;
    2.18 -import com.sun.tools.javac.code.Type.*;
    2.19 -import com.sun.tools.javac.code.Symbol.*;
    2.20 -import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
    2.21 -import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
    2.22  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    2.23  
    2.24 +import java.util.HashMap;
    2.25 +import java.util.Map;
    2.26 +
    2.27  import static com.sun.tools.javac.code.TypeTags.*;
    2.28  
    2.29  /** Helper class for type parameter inference, used by the attribution phase.
    2.30 @@ -76,50 +79,48 @@
    2.31          chk = Check.instance(context);
    2.32          diags = JCDiagnostic.Factory.instance(context);
    2.33          inferenceException = new InferenceException(diags);
    2.34 -
    2.35      }
    2.36  
    2.37 +   /**
    2.38 +    * This exception class is design to store a list of diagnostics corresponding
    2.39 +    * to inference errors that can arise during a method applicability check.
    2.40 +    */
    2.41      public static class InferenceException extends InapplicableMethodException {
    2.42          private static final long serialVersionUID = 0;
    2.43  
    2.44 +        List<JCDiagnostic> messages = List.nil();
    2.45 +
    2.46          InferenceException(JCDiagnostic.Factory diags) {
    2.47              super(diags);
    2.48          }
    2.49 +
    2.50 +        @Override
    2.51 +        InapplicableMethodException setMessage(JCDiagnostic diag) {
    2.52 +            messages = messages.append(diag);
    2.53 +            return this;
    2.54 +        }
    2.55 +
    2.56 +        @Override
    2.57 +        public JCDiagnostic getDiagnostic() {
    2.58 +            return messages.head;
    2.59 +        }
    2.60 +
    2.61 +        void clear() {
    2.62 +            messages = List.nil();
    2.63 +        }
    2.64      }
    2.65  
    2.66      private final InferenceException inferenceException;
    2.67  
    2.68  /***************************************************************************
    2.69 - * Auxiliary type values and classes
    2.70 - ***************************************************************************/
    2.71 -
    2.72 -    /** A mapping that turns type variables into undetermined type variables.
    2.73 -     */
    2.74 -    List<Type> makeUndetvars(List<Type> tvars) {
    2.75 -        List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
    2.76 -        for (Type t : undetvars) {
    2.77 -            UndetVar uv = (UndetVar)t;
    2.78 -            uv.hibounds = types.getBounds((TypeVar)uv.qtype);
    2.79 -        }
    2.80 -        return undetvars;
    2.81 -    }
    2.82 -    //where
    2.83 -            Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
    2.84 -                public Type apply(Type t) {
    2.85 -                    if (t.tag == TYPEVAR) return new UndetVar(t);
    2.86 -                    else return t.map(this);
    2.87 -                }
    2.88 -            };
    2.89 -
    2.90 -/***************************************************************************
    2.91   * Mini/Maximization of UndetVars
    2.92   ***************************************************************************/
    2.93  
    2.94      /** Instantiate undetermined type variable to its minimal upper bound.
    2.95       *  Throw a NoInstanceException if this not possible.
    2.96       */
    2.97 -    void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
    2.98 -        List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
    2.99 +   void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
   2.100 +        List<Type> hibounds = Type.filter(that.hibounds, boundFilter);
   2.101          if (that.eq.isEmpty()) {
   2.102              if (hibounds.isEmpty())
   2.103                  that.inst = syms.objectType;
   2.104 @@ -137,10 +138,10 @@
   2.105                              that.qtype, hibounds);
   2.106      }
   2.107  
   2.108 -    private Filter<Type> errorFilter = new Filter<Type>() {
   2.109 +    private Filter<Type> boundFilter = new Filter<Type>() {
   2.110          @Override
   2.111          public boolean accepts(Type t) {
   2.112 -            return !t.isErroneous();
   2.113 +            return !t.isErroneous() && t.tag != BOT;
   2.114          }
   2.115      };
   2.116  
   2.117 @@ -148,11 +149,12 @@
   2.118       *  Throw a NoInstanceException if this not possible.
   2.119       */
   2.120      void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
   2.121 -        List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
   2.122 +        List<Type> lobounds = Type.filter(that.lobounds, boundFilter);
   2.123          if (that.eq.isEmpty()) {
   2.124 -            if (lobounds.isEmpty())
   2.125 -                that.inst = syms.botType;
   2.126 -            else if (lobounds.tail.isEmpty())
   2.127 +            if (lobounds.isEmpty()) {
   2.128 +                //do nothing - the inference variable is under-constrained
   2.129 +                return;
   2.130 +            } else if (lobounds.tail.isEmpty())
   2.131                  that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
   2.132              else {
   2.133                  that.inst = types.lub(lobounds);
   2.134 @@ -166,90 +168,70 @@
   2.135          }
   2.136      }
   2.137  
   2.138 -    Type asUndetType(Type t, List<Type> undetvars) {
   2.139 -        return types.subst(t, inferenceVars(undetvars), undetvars);
   2.140 -    }
   2.141 -
   2.142 -    List<Type> inferenceVars(List<Type> undetvars) {
   2.143 -        ListBuffer<Type> tvars = ListBuffer.lb();
   2.144 -        for (Type uv : undetvars) {
   2.145 -            tvars.append(((UndetVar)uv).qtype);
   2.146 -        }
   2.147 -        return tvars.toList();
   2.148 -    }
   2.149 -
   2.150  /***************************************************************************
   2.151   * Exported Methods
   2.152   ***************************************************************************/
   2.153  
   2.154 -    /** Try to instantiate expression type `that' to given type `to'.
   2.155 -     *  If a maximal instantiation exists which makes this type
   2.156 -     *  a subtype of type `to', return the instantiated type.
   2.157 -     *  If no instantiation exists, or if several incomparable
   2.158 -     *  best instantiations exist throw a NoInstanceException.
   2.159 +    /**
   2.160 +     * Instantiate uninferred inference variables (JLS 15.12.2.8). First
   2.161 +     * if the method return type is non-void, we derive constraints from the
   2.162 +     * expected type - then we use declared bound well-formedness to derive additional
   2.163 +     * constraints. If no instantiation exists, or if several incomparable
   2.164 +     * best instantiations exist throw a NoInstanceException.
   2.165       */
   2.166 -    public List<Type> instantiateUninferred(DiagnosticPosition pos,
   2.167 -                                List<Type> undetvars,
   2.168 -                                List<Type> tvars,
   2.169 -                                MethodType mtype,
   2.170 -                                Attr.ResultInfo resultInfo,
   2.171 -                                Warner warn) throws InferenceException {
   2.172 +    public void instantiateUninferred(DiagnosticPosition pos,
   2.173 +            InferenceContext inferenceContext,
   2.174 +            MethodType mtype,
   2.175 +            Attr.ResultInfo resultInfo,
   2.176 +            Warner warn) throws InferenceException {
   2.177          Type to = resultInfo.pt;
   2.178          if (to.tag == NONE) {
   2.179              to = mtype.getReturnType().tag <= VOID ?
   2.180                      mtype.getReturnType() : syms.objectType;
   2.181          }
   2.182 -        Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
   2.183 +        Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
   2.184          if (!types.isSubtype(qtype1,
   2.185                  qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
   2.186              throw inferenceException
   2.187 -                .setMessage("infer.no.conforming.instance.exists",
   2.188 -                            tvars, mtype.getReturnType(), to);
   2.189 +                    .setMessage("infer.no.conforming.instance.exists",
   2.190 +                    inferenceContext.restvars(), mtype.getReturnType(), to);
   2.191          }
   2.192  
   2.193 -        List<Type> insttypes;
   2.194          while (true) {
   2.195              boolean stuck = true;
   2.196 -            insttypes = List.nil();
   2.197 -            for (Type t : undetvars) {
   2.198 +            for (Type t : inferenceContext.undetvars) {
   2.199                  UndetVar uv = (UndetVar)t;
   2.200 -                if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
   2.201 +                if (uv.inst == null && (uv.eq.nonEmpty() || !inferenceContext.free(uv.hibounds))) {
   2.202                      maximizeInst((UndetVar)t, warn);
   2.203                      stuck = false;
   2.204                  }
   2.205 -                insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
   2.206              }
   2.207 -            if (!Type.containsAny(insttypes, tvars)) {
   2.208 +            if (inferenceContext.restvars().isEmpty()) {
   2.209                  //all variables have been instantiated - exit
   2.210                  break;
   2.211              } else if (stuck) {
   2.212                  //some variables could not be instantiated because of cycles in
   2.213                  //upper bounds - provide a (possibly recursive) default instantiation
   2.214 -                insttypes = types.subst(insttypes,
   2.215 -                    tvars,
   2.216 -                    instantiateAsUninferredVars(undetvars, tvars));
   2.217 +                instantiateAsUninferredVars(inferenceContext);
   2.218                  break;
   2.219              } else {
   2.220                  //some variables have been instantiated - replace newly instantiated
   2.221                  //variables in remaining upper bounds and continue
   2.222 -                for (Type t : undetvars) {
   2.223 +                for (Type t : inferenceContext.undetvars) {
   2.224                      UndetVar uv = (UndetVar)t;
   2.225 -                    uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
   2.226 +                    uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
   2.227                  }
   2.228              }
   2.229          }
   2.230 -        return insttypes;
   2.231      }
   2.232  
   2.233      /**
   2.234       * Infer cyclic inference variables as described in 15.12.2.8.
   2.235       */
   2.236 -    private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
   2.237 -        Assert.check(undetvars.length() == tvars.length());
   2.238 -        ListBuffer<Type> insttypes = ListBuffer.lb();
   2.239 +    private void instantiateAsUninferredVars(InferenceContext inferenceContext) {
   2.240          ListBuffer<Type> todo = ListBuffer.lb();
   2.241          //step 1 - create fresh tvars
   2.242 -        for (Type t : undetvars) {
   2.243 +        for (Type t : inferenceContext.undetvars) {
   2.244              UndetVar uv = (UndetVar)t;
   2.245              if (uv.inst == null) {
   2.246                  TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
   2.247 @@ -257,25 +239,23 @@
   2.248                  todo.append(uv);
   2.249                  uv.inst = fresh_tvar.type;
   2.250              }
   2.251 -            insttypes.append(uv.inst);
   2.252          }
   2.253          //step 2 - replace fresh tvars in their bounds
   2.254 -        List<Type> formals = tvars;
   2.255 +        List<Type> formals = inferenceContext.inferenceVars();
   2.256          for (Type t : todo) {
   2.257              UndetVar uv = (UndetVar)t;
   2.258              TypeVar ct = (TypeVar)uv.inst;
   2.259 -            ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
   2.260 +            ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct), types));
   2.261              if (ct.bound.isErroneous()) {
   2.262                  //report inference error if glb fails
   2.263                  reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   2.264              }
   2.265              formals = formals.tail;
   2.266          }
   2.267 -        return insttypes.toList();
   2.268      }
   2.269  
   2.270 -    /** Instantiate method type `mt' by finding instantiations of
   2.271 -     *  `tvars' so that method can be applied to `argtypes'.
   2.272 +    /** Instantiate a generic method type by finding instantiations for all its
   2.273 +     * inference variables so that it can be applied to a given argument type list.
   2.274       */
   2.275      public Type instantiateMethod(Env<AttrContext> env,
   2.276                                    List<Type> tvars,
   2.277 @@ -287,83 +267,61 @@
   2.278                                    boolean useVarargs,
   2.279                                    Warner warn) throws InferenceException {
   2.280          //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   2.281 -        List<Type> undetvars =  makeUndetvars(tvars);
   2.282 +        final InferenceContext inferenceContext = new InferenceContext(tvars, types);
   2.283 +        inferenceException.clear();
   2.284  
   2.285 -        List<Type> capturedArgs =
   2.286 -                rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
   2.287 -                    allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
   2.288 +        try {
   2.289 +            rs.checkRawArgumentsAcceptable(env, inferenceContext, argtypes, mt.getParameterTypes(),
   2.290 +                    allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
   2.291  
   2.292 -        // minimize as yet undetermined type variables
   2.293 -        for (Type t : undetvars)
   2.294 -            minimizeInst((UndetVar) t, warn);
   2.295 +            // minimize as yet undetermined type variables
   2.296 +            for (Type t : inferenceContext.undetvars) {
   2.297 +                minimizeInst((UndetVar)t, warn);
   2.298 +            }
   2.299  
   2.300 -        /** Type variables instantiated to bottom */
   2.301 -        ListBuffer<Type> restvars = new ListBuffer<Type>();
   2.302 +            checkWithinBounds(inferenceContext, warn);
   2.303  
   2.304 -        /** Undet vars instantiated to bottom */
   2.305 -        final ListBuffer<Type> restundet = new ListBuffer<Type>();
   2.306 +            mt = (MethodType)inferenceContext.asInstType(mt, types);
   2.307  
   2.308 -        /** Instantiated types or TypeVars if under-constrained */
   2.309 -        ListBuffer<Type> insttypes = new ListBuffer<Type>();
   2.310 +            List<Type> restvars = inferenceContext.restvars();
   2.311  
   2.312 -        /** Instantiated types or UndetVars if under-constrained */
   2.313 -        ListBuffer<Type> undettypes = new ListBuffer<Type>();
   2.314 +            if (!restvars.isEmpty()) {
   2.315 +                if (resultInfo != null) {
   2.316 +                    instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
   2.317 +                    checkWithinBounds(inferenceContext, warn);
   2.318 +                    mt = (MethodType)inferenceContext.asInstType(mt, types);
   2.319 +                    if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   2.320 +                        log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   2.321 +                    }
   2.322 +                }
   2.323 +            }
   2.324  
   2.325 -        for (Type t : undetvars) {
   2.326 -            UndetVar uv = (UndetVar)t;
   2.327 -            if (uv.inst.tag == BOT) {
   2.328 -                restvars.append(uv.qtype);
   2.329 -                restundet.append(uv);
   2.330 -                insttypes.append(uv.qtype);
   2.331 -                undettypes.append(uv);
   2.332 -                uv.inst = null;
   2.333 -            } else {
   2.334 -                insttypes.append(uv.inst);
   2.335 -                undettypes.append(uv.inst);
   2.336 -            }
   2.337 +            // return instantiated version of method type
   2.338 +            return mt;
   2.339 +        } finally {
   2.340 +            inferenceContext.notifyChange(types);
   2.341          }
   2.342 -        checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
   2.343 -
   2.344 -        mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
   2.345 -
   2.346 -        if (!restvars.isEmpty() && resultInfo != null) {
   2.347 -            List<Type> restInferred =
   2.348 -                    instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
   2.349 -            checkWithinBounds(tvars, undetvars,
   2.350 -                           types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
   2.351 -            mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
   2.352 -            if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   2.353 -                log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   2.354 -            }
   2.355 -        }
   2.356 -
   2.357 -        if (restvars.isEmpty() || resultInfo != null) {
   2.358 -            // check that actuals conform to inferred formals
   2.359 -            checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
   2.360 -        }
   2.361 -        // return instantiated version of method type
   2.362 -        return mt;
   2.363      }
   2.364      //where
   2.365  
   2.366          /** inference check handler **/
   2.367          class InferenceCheckHandler implements Resolve.MethodCheckHandler {
   2.368  
   2.369 -            List<Type> undetvars;
   2.370 +            InferenceContext inferenceContext;
   2.371  
   2.372 -            public InferenceCheckHandler(List<Type> undetvars) {
   2.373 -                this.undetvars = undetvars;
   2.374 +            public InferenceCheckHandler(InferenceContext inferenceContext) {
   2.375 +                this.inferenceContext = inferenceContext;
   2.376              }
   2.377  
   2.378              public InapplicableMethodException arityMismatch() {
   2.379 -                return inferenceException.setMessage("infer.arg.length.mismatch", inferenceVars(undetvars));
   2.380 +                return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
   2.381              }
   2.382              public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
   2.383                  String key = varargs ?
   2.384                          "infer.varargs.argument.mismatch" :
   2.385                          "infer.no.conforming.assignment.exists";
   2.386                  return inferenceException.setMessage(key,
   2.387 -                        inferenceVars(undetvars), details);
   2.388 +                        inferenceContext.inferenceVars(), details);
   2.389              }
   2.390              public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
   2.391                  return inferenceException.setMessage("inaccessible.varargs.type",
   2.392 @@ -371,51 +329,37 @@
   2.393              }
   2.394          }
   2.395  
   2.396 -        private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
   2.397 -                boolean allowBoxing, boolean useVarargs, Warner warn) {
   2.398 -            try {
   2.399 -                rs.checkRawArgumentsAcceptable(env, actuals, formals,
   2.400 -                       allowBoxing, useVarargs, warn);
   2.401 -            }
   2.402 -            catch (InapplicableMethodException ex) {
   2.403 -                // inferred method is not applicable
   2.404 -                throw inferenceException.setMessage(ex.getDiagnostic());
   2.405 -            }
   2.406 -        }
   2.407 -
   2.408      /** check that type parameters are within their bounds.
   2.409       */
   2.410 -    void checkWithinBounds(List<Type> tvars,
   2.411 -                           List<Type> undetvars,
   2.412 -                           List<Type> arguments,
   2.413 +    void checkWithinBounds(InferenceContext inferenceContext,
   2.414                             Warner warn)
   2.415          throws InferenceException {
   2.416 -        List<Type> args = arguments;
   2.417 -        for (Type t : undetvars) {
   2.418 +        List<Type> tvars = inferenceContext.inferenceVars();
   2.419 +        for (Type t : inferenceContext.undetvars) {
   2.420              UndetVar uv = (UndetVar)t;
   2.421 -            uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
   2.422 -            uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
   2.423 -            uv.eq = types.subst(uv.eq, tvars, arguments);
   2.424 -            checkCompatibleUpperBounds(uv, tvars);
   2.425 -            if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
   2.426 -                Type inst = args.head;
   2.427 +            uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
   2.428 +            uv.lobounds = inferenceContext.asInstTypes(uv.lobounds, types);
   2.429 +            uv.eq = inferenceContext.asInstTypes(uv.eq, types);
   2.430 +            checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
   2.431 +            if (!inferenceContext.restvars().contains(tvars.head)) {
   2.432 +                Type inst = inferenceContext.asInstType(t, types);
   2.433                  for (Type u : uv.hibounds) {
   2.434 -                    if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
   2.435 +                    if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
   2.436                          reportBoundError(uv, BoundErrorKind.UPPER);
   2.437                      }
   2.438                  }
   2.439                  for (Type l : uv.lobounds) {
   2.440 -                    if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
   2.441 +                    if (!types.isSubtypeUnchecked(inferenceContext.asFree(l, types), inst, warn)) {
   2.442                          reportBoundError(uv, BoundErrorKind.LOWER);
   2.443                      }
   2.444                  }
   2.445                  for (Type e : uv.eq) {
   2.446 -                    if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
   2.447 +                    if (!types.isSameType(inst, inferenceContext.asFree(e, types))) {
   2.448                          reportBoundError(uv, BoundErrorKind.EQ);
   2.449                      }
   2.450                  }
   2.451              }
   2.452 -            args = args.tail;
   2.453 +            tvars = tvars.tail;
   2.454          }
   2.455      }
   2.456  
   2.457 @@ -423,7 +367,7 @@
   2.458          // VGJ: sort of inlined maximizeInst() below.  Adding
   2.459          // bounds can cause lobounds that are above hibounds.
   2.460          ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
   2.461 -        for (Type t : Type.filter(uv.hibounds, errorFilter)) {
   2.462 +        for (Type t : Type.filter(uv.hibounds, boundFilter)) {
   2.463              if (!t.containsAny(tvars)) {
   2.464                  hiboundsNoVars.append(t);
   2.465              }
   2.466 @@ -531,4 +475,199 @@
   2.467                      return t;
   2.468                  }
   2.469          };
   2.470 +
   2.471 +    /**
   2.472 +     * Mapping that turns inference variables into undet vars
   2.473 +     * (used by inference context)
   2.474 +     */
   2.475 +    static Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
   2.476 +        public Type apply(Type t) {
   2.477 +            if (t.tag == TYPEVAR) return new UndetVar(t);
   2.478 +            else return t.map(this);
   2.479 +        }
   2.480 +    };
   2.481 +
   2.482 +    /**
   2.483 +     * An inference context keeps track of the set of variables that are free
   2.484 +     * in the current context. It provides utility methods for opening/closing
   2.485 +     * types to their corresponding free/closed forms. It also provide hooks for
   2.486 +     * attaching deferred post-inference action (see PendingCheck). Finally,
   2.487 +     * it can be used as an entry point for performing upper/lower bound inference
   2.488 +     * (see InferenceKind).
   2.489 +     */
   2.490 +    static class InferenceContext {
   2.491 +
   2.492 +        /**
   2.493 +        * Single-method-interface for defining inference callbacks. Certain actions
   2.494 +        * (i.e. subtyping checks) might need to be redone after all inference variables
   2.495 +        * have been fixed.
   2.496 +        */
   2.497 +        interface FreeTypeListener {
   2.498 +            void typesInferred(InferenceContext inferenceContext);
   2.499 +        }
   2.500 +
   2.501 +        /** list of inference vars as undet vars */
   2.502 +        List<Type> undetvars;
   2.503 +
   2.504 +        /** list of inference vars in this context */
   2.505 +        List<Type> inferencevars;
   2.506 +
   2.507 +        java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
   2.508 +                new java.util.HashMap<FreeTypeListener, List<Type>>();
   2.509 +
   2.510 +        List<FreeTypeListener> freetypeListeners = List.nil();
   2.511 +
   2.512 +        public InferenceContext(List<Type> inferencevars, Types types) {
   2.513 +            this.undetvars = Type.map(inferencevars, fromTypeVarFun);
   2.514 +            this.inferencevars = inferencevars;
   2.515 +            for (Type t : this.undetvars) {
   2.516 +                UndetVar uv = (UndetVar)t;
   2.517 +                uv.hibounds = types.getBounds((TypeVar)uv.qtype);
   2.518 +            }
   2.519 +        }
   2.520 +
   2.521 +        /**
   2.522 +         * returns the list of free variables (as type-variables) in this
   2.523 +         * inference context
   2.524 +         */
   2.525 +        List<Type> inferenceVars() {
   2.526 +            return inferencevars;
   2.527 +        }
   2.528 +
   2.529 +        /**
   2.530 +         * returns the list of uninstantiated variables (as type-variables) in this
   2.531 +         * inference context (usually called after instantiate())
   2.532 +         */
   2.533 +        List<Type> restvars() {
   2.534 +            List<Type> undetvars = this.undetvars;
   2.535 +            ListBuffer<Type> restvars = ListBuffer.lb();
   2.536 +            for (Type t : instTypes()) {
   2.537 +                UndetVar uv = (UndetVar)undetvars.head;
   2.538 +                if (uv.qtype == t) {
   2.539 +                    restvars.append(t);
   2.540 +                }
   2.541 +                undetvars = undetvars.tail;
   2.542 +            }
   2.543 +            return restvars.toList();
   2.544 +        }
   2.545 +
   2.546 +        /**
   2.547 +         * is this type free?
   2.548 +         */
   2.549 +        final boolean free(Type t) {
   2.550 +            return t.containsAny(inferencevars);
   2.551 +        }
   2.552 +
   2.553 +        final boolean free(List<Type> ts) {
   2.554 +            for (Type t : ts) {
   2.555 +                if (free(t)) return true;
   2.556 +            }
   2.557 +            return false;
   2.558 +        }
   2.559 +
   2.560 +        /**
   2.561 +         * Returns a list of free variables in a given type
   2.562 +         */
   2.563 +        final List<Type> freeVarsIn(Type t) {
   2.564 +            ListBuffer<Type> buf = ListBuffer.lb();
   2.565 +            for (Type iv : inferenceVars()) {
   2.566 +                if (t.contains(iv)) {
   2.567 +                    buf.add(iv);
   2.568 +                }
   2.569 +            }
   2.570 +            return buf.toList();
   2.571 +        }
   2.572 +
   2.573 +        final List<Type> freeVarsIn(List<Type> ts) {
   2.574 +            ListBuffer<Type> buf = ListBuffer.lb();
   2.575 +            for (Type t : ts) {
   2.576 +                buf.appendList(freeVarsIn(t));
   2.577 +            }
   2.578 +            ListBuffer<Type> buf2 = ListBuffer.lb();
   2.579 +            for (Type t : buf) {
   2.580 +                if (!buf2.contains(t)) {
   2.581 +                    buf2.add(t);
   2.582 +                }
   2.583 +            }
   2.584 +            return buf2.toList();
   2.585 +        }
   2.586 +
   2.587 +        /**
   2.588 +         * Replace all free variables in a given type with corresponding
   2.589 +         * undet vars (used ahead of subtyping/compatibility checks to allow propagation
   2.590 +         * of inference constraints).
   2.591 +         */
   2.592 +        final Type asFree(Type t, Types types) {
   2.593 +            return types.subst(t, inferencevars, undetvars);
   2.594 +        }
   2.595 +
   2.596 +        final List<Type> asFree(List<Type> ts, Types types) {
   2.597 +            ListBuffer<Type> buf = ListBuffer.lb();
   2.598 +            for (Type t : ts) {
   2.599 +                buf.append(asFree(t, types));
   2.600 +            }
   2.601 +            return buf.toList();
   2.602 +        }
   2.603 +
   2.604 +        List<Type> instTypes() {
   2.605 +            ListBuffer<Type> buf = ListBuffer.lb();
   2.606 +            for (Type t : undetvars) {
   2.607 +                UndetVar uv = (UndetVar)t;
   2.608 +                buf.append(uv.inst != null ? uv.inst : uv.qtype);
   2.609 +            }
   2.610 +            return buf.toList();
   2.611 +        }
   2.612 +
   2.613 +        /**
   2.614 +         * Replace all free variables in a given type with corresponding
   2.615 +         * instantiated types - if one or more free variable has not been
   2.616 +         * fully instantiated, it will still be available in the resulting type.
   2.617 +         */
   2.618 +        Type asInstType(Type t, Types types) {
   2.619 +            return types.subst(t, inferencevars, instTypes());
   2.620 +        }
   2.621 +
   2.622 +        List<Type> asInstTypes(List<Type> ts, Types types) {
   2.623 +            ListBuffer<Type> buf = ListBuffer.lb();
   2.624 +            for (Type t : ts) {
   2.625 +                buf.append(asInstType(t, types));
   2.626 +            }
   2.627 +            return buf.toList();
   2.628 +        }
   2.629 +
   2.630 +        /**
   2.631 +         * Add custom hook for performing post-inference action
   2.632 +         */
   2.633 +        void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) {
   2.634 +            freeTypeListeners.put(ftl, freeVarsIn(types));
   2.635 +        }
   2.636 +
   2.637 +        /**
   2.638 +         * Mark the inference context as complete and trigger evaluation
   2.639 +         * of all deferred checks.
   2.640 +         */
   2.641 +        void notifyChange(Types types) {
   2.642 +            InferenceException thrownEx = null;
   2.643 +            for (Map.Entry<FreeTypeListener, List<Type>> entry :
   2.644 +                    new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
   2.645 +                if (!Type.containsAny(entry.getValue(), restvars())) {
   2.646 +                    try {
   2.647 +                        entry.getKey().typesInferred(this);
   2.648 +                        freeTypeListeners.remove(entry.getKey());
   2.649 +                    } catch (InferenceException ex) {
   2.650 +                        if (thrownEx == null) {
   2.651 +                            thrownEx = ex;
   2.652 +                        }
   2.653 +                    }
   2.654 +                }
   2.655 +            }
   2.656 +            //inference exception multiplexing - present any inference exception
   2.657 +            //thrown when processing listeners as a single one
   2.658 +            if (thrownEx != null) {
   2.659 +                throw thrownEx;
   2.660 +            }
   2.661 +        }
   2.662      }
   2.663 +
   2.664 +    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), types);
   2.665 +}
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Sep 25 11:53:18 2012 +0100
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Sep 25 11:55:34 2012 +0100
     3.3 @@ -31,6 +31,8 @@
     3.4  import com.sun.tools.javac.code.Symbol.*;
     3.5  import com.sun.tools.javac.comp.Attr.ResultInfo;
     3.6  import com.sun.tools.javac.comp.Check.CheckContext;
     3.7 +import com.sun.tools.javac.comp.Infer.InferenceContext;
     3.8 +import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
     3.9  import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
    3.10  import com.sun.tools.javac.jvm.*;
    3.11  import com.sun.tools.javac.tree.*;
    3.12 @@ -586,7 +588,7 @@
    3.13                                  boolean allowBoxing,
    3.14                                  boolean useVarargs,
    3.15                                  Warner warn) {
    3.16 -        checkRawArgumentsAcceptable(env, List.<Type>nil(), argtypes, formals,
    3.17 +        checkRawArgumentsAcceptable(env, infer.emptyContext, argtypes, formals,
    3.18                  allowBoxing, useVarargs, warn, resolveHandler);
    3.19      }
    3.20  
    3.21 @@ -606,8 +608,8 @@
    3.22       *
    3.23       * A method check handler (see above) is used in order to report errors.
    3.24       */
    3.25 -    List<Type> checkRawArgumentsAcceptable(Env<AttrContext> env,
    3.26 -                                List<Type> undetvars,
    3.27 +    void checkRawArgumentsAcceptable(final Env<AttrContext> env,
    3.28 +                                final Infer.InferenceContext inferenceContext,
    3.29                                  List<Type> argtypes,
    3.30                                  List<Type> formals,
    3.31                                  boolean allowBoxing,
    3.32 @@ -623,7 +625,7 @@
    3.33          }
    3.34  
    3.35          while (argtypes.nonEmpty() && formals.head != varargsFormal) {
    3.36 -            ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, undetvars, handler, warn);
    3.37 +            ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, handler, warn);
    3.38              checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
    3.39              argtypes = argtypes.tail;
    3.40              formals = formals.tail;
    3.41 @@ -638,17 +640,29 @@
    3.42              //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
    3.43              Type elt = types.elemtype(varargsFormal);
    3.44              while (argtypes.nonEmpty()) {
    3.45 -                ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn);
    3.46 +                ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, inferenceContext, handler, warn);
    3.47                  checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
    3.48                  argtypes = argtypes.tail;
    3.49              }
    3.50              //check varargs element type accessibility
    3.51 -            if (undetvars.isEmpty() && !isAccessible(env, elt)) {
    3.52 +            varargsAccessible(env, elt, handler, inferenceContext);
    3.53 +        }
    3.54 +    }
    3.55 +
    3.56 +    void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
    3.57 +        if (inferenceContext.free(t)) {
    3.58 +            inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
    3.59 +                @Override
    3.60 +                public void typesInferred(InferenceContext inferenceContext) {
    3.61 +                    varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
    3.62 +                }
    3.63 +            });
    3.64 +        } else {
    3.65 +            if (!isAccessible(env, t)) {
    3.66                  Symbol location = env.enclClass.sym;
    3.67 -                throw handler.inaccessibleVarargs(location, elt);
    3.68 +                throw handler.inaccessibleVarargs(location, t);
    3.69              }
    3.70          }
    3.71 -        return checkedArgs.toList();
    3.72      }
    3.73  
    3.74      /**
    3.75 @@ -659,13 +673,13 @@
    3.76  
    3.77          MethodCheckHandler handler;
    3.78          boolean useVarargs;
    3.79 -        List<Type> undetvars;
    3.80 +        Infer.InferenceContext inferenceContext;
    3.81          Warner rsWarner;
    3.82  
    3.83 -        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
    3.84 +        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
    3.85              this.handler = handler;
    3.86              this.useVarargs = useVarargs;
    3.87 -            this.undetvars = undetvars;
    3.88 +            this.inferenceContext = inferenceContext;
    3.89              this.rsWarner = rsWarner;
    3.90          }
    3.91  
    3.92 @@ -676,6 +690,10 @@
    3.93          public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
    3.94              return rsWarner;
    3.95          }
    3.96 +
    3.97 +        public InferenceContext inferenceContext() {
    3.98 +            return inferenceContext;
    3.99 +        }
   3.100      }
   3.101  
   3.102      /**
   3.103 @@ -684,12 +702,12 @@
   3.104       */
   3.105      class StrictMethodContext extends MethodCheckContext {
   3.106  
   3.107 -        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
   3.108 -            super(handler, useVarargs, undetvars, rsWarner);
   3.109 +        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
   3.110 +            super(handler, useVarargs, inferenceContext, rsWarner);
   3.111          }
   3.112  
   3.113          public boolean compatible(Type found, Type req, Warner warn) {
   3.114 -            return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn);
   3.115 +            return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
   3.116          }
   3.117      }
   3.118  
   3.119 @@ -699,12 +717,12 @@
   3.120       */
   3.121      class LooseMethodContext extends MethodCheckContext {
   3.122  
   3.123 -        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
   3.124 -            super(handler, useVarargs, undetvars, rsWarner);
   3.125 +        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
   3.126 +            super(handler, useVarargs, inferenceContext, rsWarner);
   3.127          }
   3.128  
   3.129          public boolean compatible(Type found, Type req, Warner warn) {
   3.130 -            return types.isConvertible(found, infer.asUndetType(req, undetvars), warn);
   3.131 +            return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
   3.132          }
   3.133      }
   3.134  
   3.135 @@ -712,10 +730,10 @@
   3.136       * Create a method check context to be used during method applicability check
   3.137       */
   3.138      ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
   3.139 -            List<Type> undetvars, MethodCheckHandler methodHandler, Warner rsWarner) {
   3.140 +            Infer.InferenceContext inferenceContext, MethodCheckHandler methodHandler, Warner rsWarner) {
   3.141          MethodCheckContext checkContext = allowBoxing ?
   3.142 -                new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) :
   3.143 -                new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner);
   3.144 +                new LooseMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner) :
   3.145 +                new StrictMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner);
   3.146          return attr.new ResultInfo(VAL, to, checkContext) {
   3.147              @Override
   3.148              protected Type check(DiagnosticPosition pos, Type found) {
   3.149 @@ -735,16 +753,13 @@
   3.150              this.diags = diags;
   3.151          }
   3.152          InapplicableMethodException setMessage() {
   3.153 -            this.diagnostic = null;
   3.154 -            return this;
   3.155 +            return setMessage((JCDiagnostic)null);
   3.156          }
   3.157          InapplicableMethodException setMessage(String key) {
   3.158 -            this.diagnostic = key != null ? diags.fragment(key) : null;
   3.159 -            return this;
   3.160 +            return setMessage(key != null ? diags.fragment(key) : null);
   3.161          }
   3.162          InapplicableMethodException setMessage(String key, Object... args) {
   3.163 -            this.diagnostic = key != null ? diags.fragment(key, args) : null;
   3.164 -            return this;
   3.165 +            return setMessage(key != null ? diags.fragment(key, args) : null);
   3.166          }
   3.167          InapplicableMethodException setMessage(JCDiagnostic diag) {
   3.168              this.diagnostic = diag;
     4.1 --- a/test/tools/javac/generics/inference/6638712/T6638712c.out	Tue Sep 25 11:53:18 2012 +0100
     4.2 +++ b/test/tools/javac/generics/inference/6638712/T6638712c.out	Tue Sep 25 11:55:34 2012 +0100
     4.3 @@ -1,2 +1,2 @@
     4.4 -T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.util.Comparator<java.lang.Enum<?>>, java.util.Comparator<? super java.lang.Enum>))
     4.5 +T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.Comparator<java.lang.Enum<?>>, java.util.Comparator<? super java.lang.Enum>))
     4.6  1 error
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/tools/javac/varargs/6313164/T7175433.java	Tue Sep 25 11:55:34 2012 +0100
     5.3 @@ -0,0 +1,59 @@
     5.4 +/*
     5.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.
    5.11 + *
    5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.15 + * version 2 for more details (a copy is included in the LICENSE file that
    5.16 + * accompanied this code).
    5.17 + *
    5.18 + * You should have received a copy of the GNU General Public License version
    5.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.21 + *
    5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.23 + * or visit www.oracle.com if you need additional information or have any
    5.24 + * questions.
    5.25 + */
    5.26 +
    5.27 +/*
    5.28 + * @test
    5.29 + * @bug 7175433 6313164
    5.30 + * @summary Inference cleanup: add helper class to handle inference variables
    5.31 + *
    5.32 + */
    5.33 +
    5.34 +import java.util.List;
    5.35 +
    5.36 +class Bar {
    5.37 +
    5.38 +    private class Foo { }
    5.39 +
    5.40 +    <Z> List<Z> m(Object... o) { T7175433.assertTrue(true); return null; }
    5.41 +    <Z> List<Z> m(Foo... o) { T7175433.assertTrue(false); return null; }
    5.42 +
    5.43 +    Foo getFoo() { return null; }
    5.44 +}
    5.45 +
    5.46 +public class T7175433 {
    5.47 +
    5.48 +    static int assertionCount;
    5.49 +
    5.50 +    static void assertTrue(boolean b) {
    5.51 +        assertionCount++;
    5.52 +        if (!b) {
    5.53 +            throw new AssertionError();
    5.54 +        }
    5.55 +    }
    5.56 +
    5.57 +    public static void main(String[] args) {
    5.58 +        Bar b = new Bar();
    5.59 +        b.m(b.getFoo());
    5.60 +        assertTrue(assertionCount == 1);
    5.61 +    }
    5.62 +}

mercurial