langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 14047 7c7a5611cf76
parent 13440 1ea85052f98d
child 14048 308d1cf8fe46
equal deleted inserted replaced
14046:8ef5d5b19998 14047:7c7a5611cf76
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.javac.comp;
    26 package com.sun.tools.javac.comp;
    27 
    27 
       
    28 import com.sun.tools.javac.code.*;
       
    29 import com.sun.tools.javac.code.Symbol.*;
       
    30 import com.sun.tools.javac.code.Type.*;
       
    31 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
       
    32 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
    28 import com.sun.tools.javac.tree.JCTree;
    33 import com.sun.tools.javac.tree.JCTree;
    29 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
    34 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
    30 import com.sun.tools.javac.tree.TreeInfo;
    35 import com.sun.tools.javac.tree.TreeInfo;
    31 import com.sun.tools.javac.util.*;
    36 import com.sun.tools.javac.util.*;
    32 import com.sun.tools.javac.util.List;
    37 import com.sun.tools.javac.util.List;
    33 import com.sun.tools.javac.code.*;
       
    34 import com.sun.tools.javac.code.Type.*;
       
    35 import com.sun.tools.javac.code.Symbol.*;
       
    36 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
       
    37 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
       
    38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
       
    39 
       
    40 import java.util.HashMap;
       
    41 import java.util.Map;
    39 
    42 
    40 import static com.sun.tools.javac.code.TypeTags.*;
    43 import static com.sun.tools.javac.code.TypeTags.*;
    41 
    44 
    42 /** Helper class for type parameter inference, used by the attribution phase.
    45 /** Helper class for type parameter inference, used by the attribution phase.
    43  *
    46  *
    74         rs = Resolve.instance(context);
    77         rs = Resolve.instance(context);
    75         log = Log.instance(context);
    78         log = Log.instance(context);
    76         chk = Check.instance(context);
    79         chk = Check.instance(context);
    77         diags = JCDiagnostic.Factory.instance(context);
    80         diags = JCDiagnostic.Factory.instance(context);
    78         inferenceException = new InferenceException(diags);
    81         inferenceException = new InferenceException(diags);
    79 
    82     }
    80     }
    83 
    81 
    84    /**
       
    85     * This exception class is design to store a list of diagnostics corresponding
       
    86     * to inference errors that can arise during a method applicability check.
       
    87     */
    82     public static class InferenceException extends InapplicableMethodException {
    88     public static class InferenceException extends InapplicableMethodException {
    83         private static final long serialVersionUID = 0;
    89         private static final long serialVersionUID = 0;
    84 
    90 
       
    91         List<JCDiagnostic> messages = List.nil();
       
    92 
    85         InferenceException(JCDiagnostic.Factory diags) {
    93         InferenceException(JCDiagnostic.Factory diags) {
    86             super(diags);
    94             super(diags);
    87         }
    95         }
       
    96 
       
    97         @Override
       
    98         InapplicableMethodException setMessage(JCDiagnostic diag) {
       
    99             messages = messages.append(diag);
       
   100             return this;
       
   101         }
       
   102 
       
   103         @Override
       
   104         public JCDiagnostic getDiagnostic() {
       
   105             return messages.head;
       
   106         }
       
   107 
       
   108         void clear() {
       
   109             messages = List.nil();
       
   110         }
    88     }
   111     }
    89 
   112 
    90     private final InferenceException inferenceException;
   113     private final InferenceException inferenceException;
    91 
       
    92 /***************************************************************************
       
    93  * Auxiliary type values and classes
       
    94  ***************************************************************************/
       
    95 
       
    96     /** A mapping that turns type variables into undetermined type variables.
       
    97      */
       
    98     List<Type> makeUndetvars(List<Type> tvars) {
       
    99         List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
       
   100         for (Type t : undetvars) {
       
   101             UndetVar uv = (UndetVar)t;
       
   102             uv.hibounds = types.getBounds((TypeVar)uv.qtype);
       
   103         }
       
   104         return undetvars;
       
   105     }
       
   106     //where
       
   107             Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
       
   108                 public Type apply(Type t) {
       
   109                     if (t.tag == TYPEVAR) return new UndetVar(t);
       
   110                     else return t.map(this);
       
   111                 }
       
   112             };
       
   113 
   114 
   114 /***************************************************************************
   115 /***************************************************************************
   115  * Mini/Maximization of UndetVars
   116  * Mini/Maximization of UndetVars
   116  ***************************************************************************/
   117  ***************************************************************************/
   117 
   118 
   118     /** Instantiate undetermined type variable to its minimal upper bound.
   119     /** Instantiate undetermined type variable to its minimal upper bound.
   119      *  Throw a NoInstanceException if this not possible.
   120      *  Throw a NoInstanceException if this not possible.
   120      */
   121      */
   121     void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
   122    void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
   122         List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
   123         List<Type> hibounds = Type.filter(that.hibounds, boundFilter);
   123         if (that.eq.isEmpty()) {
   124         if (that.eq.isEmpty()) {
   124             if (hibounds.isEmpty())
   125             if (hibounds.isEmpty())
   125                 that.inst = syms.objectType;
   126                 that.inst = syms.objectType;
   126             else if (hibounds.tail.isEmpty())
   127             else if (hibounds.tail.isEmpty())
   127                 that.inst = hibounds.head;
   128                 that.inst = hibounds.head;
   135             throw inferenceException
   136             throw inferenceException
   136                 .setMessage("no.unique.maximal.instance.exists",
   137                 .setMessage("no.unique.maximal.instance.exists",
   137                             that.qtype, hibounds);
   138                             that.qtype, hibounds);
   138     }
   139     }
   139 
   140 
   140     private Filter<Type> errorFilter = new Filter<Type>() {
   141     private Filter<Type> boundFilter = new Filter<Type>() {
   141         @Override
   142         @Override
   142         public boolean accepts(Type t) {
   143         public boolean accepts(Type t) {
   143             return !t.isErroneous();
   144             return !t.isErroneous() && t.tag != BOT;
   144         }
   145         }
   145     };
   146     };
   146 
   147 
   147     /** Instantiate undetermined type variable to the lub of all its lower bounds.
   148     /** Instantiate undetermined type variable to the lub of all its lower bounds.
   148      *  Throw a NoInstanceException if this not possible.
   149      *  Throw a NoInstanceException if this not possible.
   149      */
   150      */
   150     void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
   151     void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
   151         List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
   152         List<Type> lobounds = Type.filter(that.lobounds, boundFilter);
   152         if (that.eq.isEmpty()) {
   153         if (that.eq.isEmpty()) {
   153             if (lobounds.isEmpty())
   154             if (lobounds.isEmpty()) {
   154                 that.inst = syms.botType;
   155                 //do nothing - the inference variable is under-constrained
   155             else if (lobounds.tail.isEmpty())
   156                 return;
       
   157             } else if (lobounds.tail.isEmpty())
   156                 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
   158                 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
   157             else {
   159             else {
   158                 that.inst = types.lub(lobounds);
   160                 that.inst = types.lub(lobounds);
   159             }
   161             }
   160             if (that.inst == null || that.inst.tag == ERROR)
   162             if (that.inst == null || that.inst.tag == ERROR)
   164         } else {
   166         } else {
   165             that.inst = that.eq.head;
   167             that.inst = that.eq.head;
   166         }
   168         }
   167     }
   169     }
   168 
   170 
   169     Type asUndetType(Type t, List<Type> undetvars) {
       
   170         return types.subst(t, inferenceVars(undetvars), undetvars);
       
   171     }
       
   172 
       
   173     List<Type> inferenceVars(List<Type> undetvars) {
       
   174         ListBuffer<Type> tvars = ListBuffer.lb();
       
   175         for (Type uv : undetvars) {
       
   176             tvars.append(((UndetVar)uv).qtype);
       
   177         }
       
   178         return tvars.toList();
       
   179     }
       
   180 
       
   181 /***************************************************************************
   171 /***************************************************************************
   182  * Exported Methods
   172  * Exported Methods
   183  ***************************************************************************/
   173  ***************************************************************************/
   184 
   174 
   185     /** Try to instantiate expression type `that' to given type `to'.
   175     /**
   186      *  If a maximal instantiation exists which makes this type
   176      * Instantiate uninferred inference variables (JLS 15.12.2.8). First
   187      *  a subtype of type `to', return the instantiated type.
   177      * if the method return type is non-void, we derive constraints from the
   188      *  If no instantiation exists, or if several incomparable
   178      * expected type - then we use declared bound well-formedness to derive additional
   189      *  best instantiations exist throw a NoInstanceException.
   179      * constraints. If no instantiation exists, or if several incomparable
   190      */
   180      * best instantiations exist throw a NoInstanceException.
   191     public List<Type> instantiateUninferred(DiagnosticPosition pos,
   181      */
   192                                 List<Type> undetvars,
   182     public void instantiateUninferred(DiagnosticPosition pos,
   193                                 List<Type> tvars,
   183             InferenceContext inferenceContext,
   194                                 MethodType mtype,
   184             MethodType mtype,
   195                                 Attr.ResultInfo resultInfo,
   185             Attr.ResultInfo resultInfo,
   196                                 Warner warn) throws InferenceException {
   186             Warner warn) throws InferenceException {
   197         Type to = resultInfo.pt;
   187         Type to = resultInfo.pt;
   198         if (to.tag == NONE) {
   188         if (to.tag == NONE) {
   199             to = mtype.getReturnType().tag <= VOID ?
   189             to = mtype.getReturnType().tag <= VOID ?
   200                     mtype.getReturnType() : syms.objectType;
   190                     mtype.getReturnType() : syms.objectType;
   201         }
   191         }
   202         Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
   192         Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
   203         if (!types.isSubtype(qtype1,
   193         if (!types.isSubtype(qtype1,
   204                 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
   194                 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
   205             throw inferenceException
   195             throw inferenceException
   206                 .setMessage("infer.no.conforming.instance.exists",
   196                     .setMessage("infer.no.conforming.instance.exists",
   207                             tvars, mtype.getReturnType(), to);
   197                     inferenceContext.restvars(), mtype.getReturnType(), to);
   208         }
   198         }
   209 
   199 
   210         List<Type> insttypes;
       
   211         while (true) {
   200         while (true) {
   212             boolean stuck = true;
   201             boolean stuck = true;
   213             insttypes = List.nil();
   202             for (Type t : inferenceContext.undetvars) {
   214             for (Type t : undetvars) {
       
   215                 UndetVar uv = (UndetVar)t;
   203                 UndetVar uv = (UndetVar)t;
   216                 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
   204                 if (uv.inst == null && (uv.eq.nonEmpty() || !inferenceContext.free(uv.hibounds))) {
   217                     maximizeInst((UndetVar)t, warn);
   205                     maximizeInst((UndetVar)t, warn);
   218                     stuck = false;
   206                     stuck = false;
   219                 }
   207                 }
   220                 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
   208             }
   221             }
   209             if (inferenceContext.restvars().isEmpty()) {
   222             if (!Type.containsAny(insttypes, tvars)) {
       
   223                 //all variables have been instantiated - exit
   210                 //all variables have been instantiated - exit
   224                 break;
   211                 break;
   225             } else if (stuck) {
   212             } else if (stuck) {
   226                 //some variables could not be instantiated because of cycles in
   213                 //some variables could not be instantiated because of cycles in
   227                 //upper bounds - provide a (possibly recursive) default instantiation
   214                 //upper bounds - provide a (possibly recursive) default instantiation
   228                 insttypes = types.subst(insttypes,
   215                 instantiateAsUninferredVars(inferenceContext);
   229                     tvars,
       
   230                     instantiateAsUninferredVars(undetvars, tvars));
       
   231                 break;
   216                 break;
   232             } else {
   217             } else {
   233                 //some variables have been instantiated - replace newly instantiated
   218                 //some variables have been instantiated - replace newly instantiated
   234                 //variables in remaining upper bounds and continue
   219                 //variables in remaining upper bounds and continue
   235                 for (Type t : undetvars) {
   220                 for (Type t : inferenceContext.undetvars) {
   236                     UndetVar uv = (UndetVar)t;
   221                     UndetVar uv = (UndetVar)t;
   237                     uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
   222                     uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
   238                 }
   223                 }
   239             }
   224             }
   240         }
   225         }
   241         return insttypes;
       
   242     }
   226     }
   243 
   227 
   244     /**
   228     /**
   245      * Infer cyclic inference variables as described in 15.12.2.8.
   229      * Infer cyclic inference variables as described in 15.12.2.8.
   246      */
   230      */
   247     private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
   231     private void instantiateAsUninferredVars(InferenceContext inferenceContext) {
   248         Assert.check(undetvars.length() == tvars.length());
       
   249         ListBuffer<Type> insttypes = ListBuffer.lb();
       
   250         ListBuffer<Type> todo = ListBuffer.lb();
   232         ListBuffer<Type> todo = ListBuffer.lb();
   251         //step 1 - create fresh tvars
   233         //step 1 - create fresh tvars
   252         for (Type t : undetvars) {
   234         for (Type t : inferenceContext.undetvars) {
   253             UndetVar uv = (UndetVar)t;
   235             UndetVar uv = (UndetVar)t;
   254             if (uv.inst == null) {
   236             if (uv.inst == null) {
   255                 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
   237                 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
   256                 fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
   238                 fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
   257                 todo.append(uv);
   239                 todo.append(uv);
   258                 uv.inst = fresh_tvar.type;
   240                 uv.inst = fresh_tvar.type;
   259             }
   241             }
   260             insttypes.append(uv.inst);
       
   261         }
   242         }
   262         //step 2 - replace fresh tvars in their bounds
   243         //step 2 - replace fresh tvars in their bounds
   263         List<Type> formals = tvars;
   244         List<Type> formals = inferenceContext.inferenceVars();
   264         for (Type t : todo) {
   245         for (Type t : todo) {
   265             UndetVar uv = (UndetVar)t;
   246             UndetVar uv = (UndetVar)t;
   266             TypeVar ct = (TypeVar)uv.inst;
   247             TypeVar ct = (TypeVar)uv.inst;
   267             ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
   248             ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct), types));
   268             if (ct.bound.isErroneous()) {
   249             if (ct.bound.isErroneous()) {
   269                 //report inference error if glb fails
   250                 //report inference error if glb fails
   270                 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   251                 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   271             }
   252             }
   272             formals = formals.tail;
   253             formals = formals.tail;
   273         }
   254         }
   274         return insttypes.toList();
   255     }
   275     }
   256 
   276 
   257     /** Instantiate a generic method type by finding instantiations for all its
   277     /** Instantiate method type `mt' by finding instantiations of
   258      * inference variables so that it can be applied to a given argument type list.
   278      *  `tvars' so that method can be applied to `argtypes'.
       
   279      */
   259      */
   280     public Type instantiateMethod(Env<AttrContext> env,
   260     public Type instantiateMethod(Env<AttrContext> env,
   281                                   List<Type> tvars,
   261                                   List<Type> tvars,
   282                                   MethodType mt,
   262                                   MethodType mt,
   283                                   Attr.ResultInfo resultInfo,
   263                                   Attr.ResultInfo resultInfo,
   285                                   List<Type> argtypes,
   265                                   List<Type> argtypes,
   286                                   boolean allowBoxing,
   266                                   boolean allowBoxing,
   287                                   boolean useVarargs,
   267                                   boolean useVarargs,
   288                                   Warner warn) throws InferenceException {
   268                                   Warner warn) throws InferenceException {
   289         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   269         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   290         List<Type> undetvars =  makeUndetvars(tvars);
   270         final InferenceContext inferenceContext = new InferenceContext(tvars, types);
   291 
   271         inferenceException.clear();
   292         List<Type> capturedArgs =
   272 
   293                 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
   273         try {
   294                     allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
   274             rs.checkRawArgumentsAcceptable(env, inferenceContext, argtypes, mt.getParameterTypes(),
   295 
   275                     allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
   296         // minimize as yet undetermined type variables
   276 
   297         for (Type t : undetvars)
   277             // minimize as yet undetermined type variables
   298             minimizeInst((UndetVar) t, warn);
   278             for (Type t : inferenceContext.undetvars) {
   299 
   279                 minimizeInst((UndetVar)t, warn);
   300         /** Type variables instantiated to bottom */
   280             }
   301         ListBuffer<Type> restvars = new ListBuffer<Type>();
   281 
   302 
   282             checkWithinBounds(inferenceContext, warn);
   303         /** Undet vars instantiated to bottom */
   283 
   304         final ListBuffer<Type> restundet = new ListBuffer<Type>();
   284             mt = (MethodType)inferenceContext.asInstType(mt, types);
   305 
   285 
   306         /** Instantiated types or TypeVars if under-constrained */
   286             List<Type> restvars = inferenceContext.restvars();
   307         ListBuffer<Type> insttypes = new ListBuffer<Type>();
   287 
   308 
   288             if (!restvars.isEmpty()) {
   309         /** Instantiated types or UndetVars if under-constrained */
   289                 if (resultInfo != null) {
   310         ListBuffer<Type> undettypes = new ListBuffer<Type>();
   290                     instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
   311 
   291                     checkWithinBounds(inferenceContext, warn);
   312         for (Type t : undetvars) {
   292                     mt = (MethodType)inferenceContext.asInstType(mt, types);
   313             UndetVar uv = (UndetVar)t;
   293                     if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   314             if (uv.inst.tag == BOT) {
   294                         log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   315                 restvars.append(uv.qtype);
   295                     }
   316                 restundet.append(uv);
   296                 }
   317                 insttypes.append(uv.qtype);
   297             }
   318                 undettypes.append(uv);
   298 
   319                 uv.inst = null;
   299             // return instantiated version of method type
   320             } else {
   300             return mt;
   321                 insttypes.append(uv.inst);
   301         } finally {
   322                 undettypes.append(uv.inst);
   302             inferenceContext.notifyChange(types);
   323             }
   303         }
   324         }
       
   325         checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
       
   326 
       
   327         mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
       
   328 
       
   329         if (!restvars.isEmpty() && resultInfo != null) {
       
   330             List<Type> restInferred =
       
   331                     instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
       
   332             checkWithinBounds(tvars, undetvars,
       
   333                            types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
       
   334             mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
       
   335             if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
       
   336                 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
       
   337             }
       
   338         }
       
   339 
       
   340         if (restvars.isEmpty() || resultInfo != null) {
       
   341             // check that actuals conform to inferred formals
       
   342             checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
       
   343         }
       
   344         // return instantiated version of method type
       
   345         return mt;
       
   346     }
   304     }
   347     //where
   305     //where
   348 
   306 
   349         /** inference check handler **/
   307         /** inference check handler **/
   350         class InferenceCheckHandler implements Resolve.MethodCheckHandler {
   308         class InferenceCheckHandler implements Resolve.MethodCheckHandler {
   351 
   309 
   352             List<Type> undetvars;
   310             InferenceContext inferenceContext;
   353 
   311 
   354             public InferenceCheckHandler(List<Type> undetvars) {
   312             public InferenceCheckHandler(InferenceContext inferenceContext) {
   355                 this.undetvars = undetvars;
   313                 this.inferenceContext = inferenceContext;
   356             }
   314             }
   357 
   315 
   358             public InapplicableMethodException arityMismatch() {
   316             public InapplicableMethodException arityMismatch() {
   359                 return inferenceException.setMessage("infer.arg.length.mismatch", inferenceVars(undetvars));
   317                 return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
   360             }
   318             }
   361             public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
   319             public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
   362                 String key = varargs ?
   320                 String key = varargs ?
   363                         "infer.varargs.argument.mismatch" :
   321                         "infer.varargs.argument.mismatch" :
   364                         "infer.no.conforming.assignment.exists";
   322                         "infer.no.conforming.assignment.exists";
   365                 return inferenceException.setMessage(key,
   323                 return inferenceException.setMessage(key,
   366                         inferenceVars(undetvars), details);
   324                         inferenceContext.inferenceVars(), details);
   367             }
   325             }
   368             public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
   326             public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
   369                 return inferenceException.setMessage("inaccessible.varargs.type",
   327                 return inferenceException.setMessage("inaccessible.varargs.type",
   370                         expected, Kinds.kindName(location), location);
   328                         expected, Kinds.kindName(location), location);
   371             }
   329             }
   372         }
   330         }
   373 
   331 
   374         private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
       
   375                 boolean allowBoxing, boolean useVarargs, Warner warn) {
       
   376             try {
       
   377                 rs.checkRawArgumentsAcceptable(env, actuals, formals,
       
   378                        allowBoxing, useVarargs, warn);
       
   379             }
       
   380             catch (InapplicableMethodException ex) {
       
   381                 // inferred method is not applicable
       
   382                 throw inferenceException.setMessage(ex.getDiagnostic());
       
   383             }
       
   384         }
       
   385 
       
   386     /** check that type parameters are within their bounds.
   332     /** check that type parameters are within their bounds.
   387      */
   333      */
   388     void checkWithinBounds(List<Type> tvars,
   334     void checkWithinBounds(InferenceContext inferenceContext,
   389                            List<Type> undetvars,
       
   390                            List<Type> arguments,
       
   391                            Warner warn)
   335                            Warner warn)
   392         throws InferenceException {
   336         throws InferenceException {
   393         List<Type> args = arguments;
   337         List<Type> tvars = inferenceContext.inferenceVars();
   394         for (Type t : undetvars) {
   338         for (Type t : inferenceContext.undetvars) {
   395             UndetVar uv = (UndetVar)t;
   339             UndetVar uv = (UndetVar)t;
   396             uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
   340             uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
   397             uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
   341             uv.lobounds = inferenceContext.asInstTypes(uv.lobounds, types);
   398             uv.eq = types.subst(uv.eq, tvars, arguments);
   342             uv.eq = inferenceContext.asInstTypes(uv.eq, types);
   399             checkCompatibleUpperBounds(uv, tvars);
   343             checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
   400             if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
   344             if (!inferenceContext.restvars().contains(tvars.head)) {
   401                 Type inst = args.head;
   345                 Type inst = inferenceContext.asInstType(t, types);
   402                 for (Type u : uv.hibounds) {
   346                 for (Type u : uv.hibounds) {
   403                     if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
   347                     if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
   404                         reportBoundError(uv, BoundErrorKind.UPPER);
   348                         reportBoundError(uv, BoundErrorKind.UPPER);
   405                     }
   349                     }
   406                 }
   350                 }
   407                 for (Type l : uv.lobounds) {
   351                 for (Type l : uv.lobounds) {
   408                     if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
   352                     if (!types.isSubtypeUnchecked(inferenceContext.asFree(l, types), inst, warn)) {
   409                         reportBoundError(uv, BoundErrorKind.LOWER);
   353                         reportBoundError(uv, BoundErrorKind.LOWER);
   410                     }
   354                     }
   411                 }
   355                 }
   412                 for (Type e : uv.eq) {
   356                 for (Type e : uv.eq) {
   413                     if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
   357                     if (!types.isSameType(inst, inferenceContext.asFree(e, types))) {
   414                         reportBoundError(uv, BoundErrorKind.EQ);
   358                         reportBoundError(uv, BoundErrorKind.EQ);
   415                     }
   359                     }
   416                 }
   360                 }
   417             }
   361             }
   418             args = args.tail;
   362             tvars = tvars.tail;
   419         }
   363         }
   420     }
   364     }
   421 
   365 
   422     void checkCompatibleUpperBounds(UndetVar uv, List<Type> tvars) {
   366     void checkCompatibleUpperBounds(UndetVar uv, List<Type> tvars) {
   423         // VGJ: sort of inlined maximizeInst() below.  Adding
   367         // VGJ: sort of inlined maximizeInst() below.  Adding
   424         // bounds can cause lobounds that are above hibounds.
   368         // bounds can cause lobounds that are above hibounds.
   425         ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
   369         ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
   426         for (Type t : Type.filter(uv.hibounds, errorFilter)) {
   370         for (Type t : Type.filter(uv.hibounds, boundFilter)) {
   427             if (!t.containsAny(tvars)) {
   371             if (!t.containsAny(tvars)) {
   428                 hiboundsNoVars.append(t);
   372                 hiboundsNoVars.append(t);
   429             }
   373             }
   430         }
   374         }
   431         List<Type> hibounds = hiboundsNoVars.toList();
   375         List<Type> hibounds = hiboundsNoVars.toList();
   529                         // infer as java.lang.Void for now
   473                         // infer as java.lang.Void for now
   530                         t = types.boxedClass(syms.voidType).type;
   474                         t = types.boxedClass(syms.voidType).type;
   531                     return t;
   475                     return t;
   532                 }
   476                 }
   533         };
   477         };
   534     }
   478 
       
   479     /**
       
   480      * Mapping that turns inference variables into undet vars
       
   481      * (used by inference context)
       
   482      */
       
   483     static Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
       
   484         public Type apply(Type t) {
       
   485             if (t.tag == TYPEVAR) return new UndetVar(t);
       
   486             else return t.map(this);
       
   487         }
       
   488     };
       
   489 
       
   490     /**
       
   491      * An inference context keeps track of the set of variables that are free
       
   492      * in the current context. It provides utility methods for opening/closing
       
   493      * types to their corresponding free/closed forms. It also provide hooks for
       
   494      * attaching deferred post-inference action (see PendingCheck). Finally,
       
   495      * it can be used as an entry point for performing upper/lower bound inference
       
   496      * (see InferenceKind).
       
   497      */
       
   498     static class InferenceContext {
       
   499 
       
   500         /**
       
   501         * Single-method-interface for defining inference callbacks. Certain actions
       
   502         * (i.e. subtyping checks) might need to be redone after all inference variables
       
   503         * have been fixed.
       
   504         */
       
   505         interface FreeTypeListener {
       
   506             void typesInferred(InferenceContext inferenceContext);
       
   507         }
       
   508 
       
   509         /** list of inference vars as undet vars */
       
   510         List<Type> undetvars;
       
   511 
       
   512         /** list of inference vars in this context */
       
   513         List<Type> inferencevars;
       
   514 
       
   515         java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
       
   516                 new java.util.HashMap<FreeTypeListener, List<Type>>();
       
   517 
       
   518         List<FreeTypeListener> freetypeListeners = List.nil();
       
   519 
       
   520         public InferenceContext(List<Type> inferencevars, Types types) {
       
   521             this.undetvars = Type.map(inferencevars, fromTypeVarFun);
       
   522             this.inferencevars = inferencevars;
       
   523             for (Type t : this.undetvars) {
       
   524                 UndetVar uv = (UndetVar)t;
       
   525                 uv.hibounds = types.getBounds((TypeVar)uv.qtype);
       
   526             }
       
   527         }
       
   528 
       
   529         /**
       
   530          * returns the list of free variables (as type-variables) in this
       
   531          * inference context
       
   532          */
       
   533         List<Type> inferenceVars() {
       
   534             return inferencevars;
       
   535         }
       
   536 
       
   537         /**
       
   538          * returns the list of uninstantiated variables (as type-variables) in this
       
   539          * inference context (usually called after instantiate())
       
   540          */
       
   541         List<Type> restvars() {
       
   542             List<Type> undetvars = this.undetvars;
       
   543             ListBuffer<Type> restvars = ListBuffer.lb();
       
   544             for (Type t : instTypes()) {
       
   545                 UndetVar uv = (UndetVar)undetvars.head;
       
   546                 if (uv.qtype == t) {
       
   547                     restvars.append(t);
       
   548                 }
       
   549                 undetvars = undetvars.tail;
       
   550             }
       
   551             return restvars.toList();
       
   552         }
       
   553 
       
   554         /**
       
   555          * is this type free?
       
   556          */
       
   557         final boolean free(Type t) {
       
   558             return t.containsAny(inferencevars);
       
   559         }
       
   560 
       
   561         final boolean free(List<Type> ts) {
       
   562             for (Type t : ts) {
       
   563                 if (free(t)) return true;
       
   564             }
       
   565             return false;
       
   566         }
       
   567 
       
   568         /**
       
   569          * Returns a list of free variables in a given type
       
   570          */
       
   571         final List<Type> freeVarsIn(Type t) {
       
   572             ListBuffer<Type> buf = ListBuffer.lb();
       
   573             for (Type iv : inferenceVars()) {
       
   574                 if (t.contains(iv)) {
       
   575                     buf.add(iv);
       
   576                 }
       
   577             }
       
   578             return buf.toList();
       
   579         }
       
   580 
       
   581         final List<Type> freeVarsIn(List<Type> ts) {
       
   582             ListBuffer<Type> buf = ListBuffer.lb();
       
   583             for (Type t : ts) {
       
   584                 buf.appendList(freeVarsIn(t));
       
   585             }
       
   586             ListBuffer<Type> buf2 = ListBuffer.lb();
       
   587             for (Type t : buf) {
       
   588                 if (!buf2.contains(t)) {
       
   589                     buf2.add(t);
       
   590                 }
       
   591             }
       
   592             return buf2.toList();
       
   593         }
       
   594 
       
   595         /**
       
   596          * Replace all free variables in a given type with corresponding
       
   597          * undet vars (used ahead of subtyping/compatibility checks to allow propagation
       
   598          * of inference constraints).
       
   599          */
       
   600         final Type asFree(Type t, Types types) {
       
   601             return types.subst(t, inferencevars, undetvars);
       
   602         }
       
   603 
       
   604         final List<Type> asFree(List<Type> ts, Types types) {
       
   605             ListBuffer<Type> buf = ListBuffer.lb();
       
   606             for (Type t : ts) {
       
   607                 buf.append(asFree(t, types));
       
   608             }
       
   609             return buf.toList();
       
   610         }
       
   611 
       
   612         List<Type> instTypes() {
       
   613             ListBuffer<Type> buf = ListBuffer.lb();
       
   614             for (Type t : undetvars) {
       
   615                 UndetVar uv = (UndetVar)t;
       
   616                 buf.append(uv.inst != null ? uv.inst : uv.qtype);
       
   617             }
       
   618             return buf.toList();
       
   619         }
       
   620 
       
   621         /**
       
   622          * Replace all free variables in a given type with corresponding
       
   623          * instantiated types - if one or more free variable has not been
       
   624          * fully instantiated, it will still be available in the resulting type.
       
   625          */
       
   626         Type asInstType(Type t, Types types) {
       
   627             return types.subst(t, inferencevars, instTypes());
       
   628         }
       
   629 
       
   630         List<Type> asInstTypes(List<Type> ts, Types types) {
       
   631             ListBuffer<Type> buf = ListBuffer.lb();
       
   632             for (Type t : ts) {
       
   633                 buf.append(asInstType(t, types));
       
   634             }
       
   635             return buf.toList();
       
   636         }
       
   637 
       
   638         /**
       
   639          * Add custom hook for performing post-inference action
       
   640          */
       
   641         void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) {
       
   642             freeTypeListeners.put(ftl, freeVarsIn(types));
       
   643         }
       
   644 
       
   645         /**
       
   646          * Mark the inference context as complete and trigger evaluation
       
   647          * of all deferred checks.
       
   648          */
       
   649         void notifyChange(Types types) {
       
   650             InferenceException thrownEx = null;
       
   651             for (Map.Entry<FreeTypeListener, List<Type>> entry :
       
   652                     new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
       
   653                 if (!Type.containsAny(entry.getValue(), restvars())) {
       
   654                     try {
       
   655                         entry.getKey().typesInferred(this);
       
   656                         freeTypeListeners.remove(entry.getKey());
       
   657                     } catch (InferenceException ex) {
       
   658                         if (thrownEx == null) {
       
   659                             thrownEx = ex;
       
   660                         }
       
   661                     }
       
   662                 }
       
   663             }
       
   664             //inference exception multiplexing - present any inference exception
       
   665             //thrown when processing listeners as a single one
       
   666             if (thrownEx != null) {
       
   667                 throw thrownEx;
       
   668             }
       
   669         }
       
   670     }
       
   671 
       
   672     final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), types);
       
   673 }