langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 12915 28cf1e0dafdc
parent 12468 1100643c0209
child 13438 83729994273a
equal deleted inserted replaced
12914:0bbd74229a78 12915:28cf1e0dafdc
   212      *  If a maximal instantiation exists which makes this type
   212      *  If a maximal instantiation exists which makes this type
   213      *  a subtype of type `to', return the instantiated type.
   213      *  a subtype of type `to', return the instantiated type.
   214      *  If no instantiation exists, or if several incomparable
   214      *  If no instantiation exists, or if several incomparable
   215      *  best instantiations exist throw a NoInstanceException.
   215      *  best instantiations exist throw a NoInstanceException.
   216      */
   216      */
   217     public Type instantiateExpr(ForAll that,
   217     public List<Type> instantiateUninferred(DiagnosticPosition pos,
   218                                 Type to,
   218                                 List<Type> undetvars,
       
   219                                 List<Type> tvars,
       
   220                                 MethodType mtype,
       
   221                                 Attr.ResultInfo resultInfo,
   219                                 Warner warn) throws InferenceException {
   222                                 Warner warn) throws InferenceException {
   220         List<Type> undetvars = that.undetvars();
   223         Type to = resultInfo.pt;
   221         Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
   224         if (to.tag == NONE) {
       
   225             to = mtype.getReturnType().tag <= VOID ?
       
   226                     mtype.getReturnType() : syms.objectType;
       
   227         }
       
   228         Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
   222         if (!types.isSubtype(qtype1,
   229         if (!types.isSubtype(qtype1,
   223                 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
   230                 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
   224             throw unambiguousNoInstanceException
   231             throw unambiguousNoInstanceException
   225                 .setMessage("infer.no.conforming.instance.exists",
   232                 .setMessage("infer.no.conforming.instance.exists",
   226                             that.tvars, that.qtype, to);
   233                             tvars, mtype.getReturnType(), to);
   227         }
   234         }
   228 
   235 
   229         List<Type> insttypes;
   236         List<Type> insttypes;
   230         while (true) {
   237         while (true) {
   231             boolean stuck = true;
   238             boolean stuck = true;
   232             insttypes = List.nil();
   239             insttypes = List.nil();
   233             for (Type t : undetvars) {
   240             for (Type t : undetvars) {
   234                 UndetVar uv = (UndetVar)t;
   241                 UndetVar uv = (UndetVar)t;
   235                 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, that.tvars))) {
   242                 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
   236                     maximizeInst((UndetVar)t, warn);
   243                     maximizeInst((UndetVar)t, warn);
   237                     stuck = false;
   244                     stuck = false;
   238                 }
   245                 }
   239                 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
   246                 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
   240             }
   247             }
   241             if (!Type.containsAny(insttypes, that.tvars)) {
   248             if (!Type.containsAny(insttypes, tvars)) {
   242                 //all variables have been instantiated - exit
   249                 //all variables have been instantiated - exit
   243                 break;
   250                 break;
   244             } else if (stuck) {
   251             } else if (stuck) {
   245                 //some variables could not be instantiated because of cycles in
   252                 //some variables could not be instantiated because of cycles in
   246                 //upper bounds - provide a (possibly recursive) default instantiation
   253                 //upper bounds - provide a (possibly recursive) default instantiation
   247                 insttypes = types.subst(insttypes,
   254                 insttypes = types.subst(insttypes,
   248                     that.tvars,
   255                     tvars,
   249                     instantiateAsUninferredVars(undetvars, that.tvars));
   256                     instantiateAsUninferredVars(undetvars, tvars));
   250                 break;
   257                 break;
   251             } else {
   258             } else {
   252                 //some variables have been instantiated - replace newly instantiated
   259                 //some variables have been instantiated - replace newly instantiated
   253                 //variables in remaining upper bounds and continue
   260                 //variables in remaining upper bounds and continue
   254                 for (Type t : undetvars) {
   261                 for (Type t : undetvars) {
   255                     UndetVar uv = (UndetVar)t;
   262                     UndetVar uv = (UndetVar)t;
   256                     uv.hibounds = types.subst(uv.hibounds, that.tvars, insttypes);
   263                     uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
   257                 }
   264                 }
   258             }
   265             }
   259         }
   266         }
   260         return that.inst(insttypes, types);
   267         return insttypes;
   261     }
   268     }
   262 
   269 
   263     /**
   270     /**
   264      * Infer cyclic inference variables as described in 15.12.2.8.
   271      * Infer cyclic inference variables as described in 15.12.2.8.
   265      */
   272      */
   294     }
   301     }
   295 
   302 
   296     /** Instantiate method type `mt' by finding instantiations of
   303     /** Instantiate method type `mt' by finding instantiations of
   297      *  `tvars' so that method can be applied to `argtypes'.
   304      *  `tvars' so that method can be applied to `argtypes'.
   298      */
   305      */
   299     public Type instantiateMethod(final Env<AttrContext> env,
   306     public Type instantiateMethod(Env<AttrContext> env,
   300                                   List<Type> tvars,
   307                                   List<Type> tvars,
   301                                   MethodType mt,
   308                                   MethodType mt,
   302                                   final Symbol msym,
   309                                   Attr.ResultInfo resultInfo,
   303                                   final List<Type> argtypes,
   310                                   Symbol msym,
   304                                   final boolean allowBoxing,
   311                                   List<Type> argtypes,
   305                                   final boolean useVarargs,
   312                                   boolean allowBoxing,
   306                                   final Warner warn) throws InferenceException {
   313                                   boolean useVarargs,
       
   314                                   Warner warn) throws InferenceException {
   307         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   315         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   308         final List<Type> undetvars =  makeUndetvars(tvars);
   316         List<Type> undetvars =  makeUndetvars(tvars);
   309 
   317 
   310         final List<Type> capturedArgs =
   318         List<Type> capturedArgs =
   311                 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
   319                 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
   312                     allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
   320                     allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
   313 
   321 
   314         // minimize as yet undetermined type variables
   322         // minimize as yet undetermined type variables
   315         for (Type t : undetvars)
   323         for (Type t : undetvars)
   342         }
   350         }
   343         checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
   351         checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
   344 
   352 
   345         mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
   353         mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
   346 
   354 
   347         if (!restvars.isEmpty()) {
   355         if (!restvars.isEmpty() && resultInfo != null) {
   348             // if there are uninstantiated variables,
   356             List<Type> restInferred =
   349             // quantify result type with them
   357                     instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
   350             final List<Type> inferredTypes = insttypes.toList();
   358             checkWithinBounds(tvars, undetvars,
   351             final List<Type> all_tvars = tvars; //this is the wrong tvars
   359                            types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
   352             return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) {
   360             mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
   353                 @Override
   361             if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   354                 List<Type> undetvars() {
   362                 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   355                     return restundet.toList();
   363             }
   356                 }
   364         }
   357                 @Override
   365 
   358                 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
   366         if (restvars.isEmpty() || resultInfo != null) {
   359                     Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
       
   360                                        restype,
       
   361                                        types.subst(getThrownTypes(), tvars, inferred),
       
   362                                        qtype.tsym);
       
   363                     // check that actuals conform to inferred formals
       
   364                     warn.clear();
       
   365                     checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn);
       
   366                     // check that inferred bounds conform to their bounds
       
   367                     checkWithinBounds(all_tvars, undetvars,
       
   368                            types.subst(inferredTypes, tvars, inferred), warn);
       
   369                     qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs, warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED));
       
   370                 }
       
   371             };
       
   372         }
       
   373         else {
       
   374             // check that actuals conform to inferred formals
   367             // check that actuals conform to inferred formals
   375             checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
   368             checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
   376             // return instantiated version of method type
   369         }
   377             return mt;
   370         // return instantiated version of method type
   378         }
   371         return mt;
   379     }
   372     }
   380     //where
   373     //where
   381 
   374 
   382         /** inference check handler **/
   375         /** inference check handler **/
   383         class InferenceCheckHandler implements Resolve.MethodCheckHandler {
   376         class InferenceCheckHandler implements Resolve.MethodCheckHandler {
   399                         inferenceVars(undetvars), found, expected);
   392                         inferenceVars(undetvars), found, expected);
   400             }
   393             }
   401             public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
   394             public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
   402                 return unambiguousNoInstanceException.setMessage("inaccessible.varargs.type",
   395                 return unambiguousNoInstanceException.setMessage("inaccessible.varargs.type",
   403                         expected, Kinds.kindName(location), location);
   396                         expected, Kinds.kindName(location), location);
   404             }
       
   405         }
       
   406 
       
   407         /**
       
   408          * A delegated type representing a partially uninferred method type.
       
   409          * The return type of a partially uninferred method type is a ForAll
       
   410          * type - when the return type is instantiated (see Infer.instantiateExpr)
       
   411          * the underlying method type is also updated.
       
   412          */
       
   413         abstract class UninferredMethodType extends DelegatedType {
       
   414 
       
   415             final List<Type> tvars;
       
   416             final Symbol msym;
       
   417             final DiagnosticPosition pos;
       
   418 
       
   419             public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List<Type> tvars) {
       
   420                 super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
       
   421                 this.tvars = tvars;
       
   422                 this.msym = msym;
       
   423                 this.pos = pos;
       
   424                 asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
       
   425             }
       
   426 
       
   427             @Override
       
   428             public MethodType asMethodType() {
       
   429                 return qtype.asMethodType();
       
   430             }
       
   431 
       
   432             @Override
       
   433             public Type map(Mapping f) {
       
   434                 return qtype.map(f);
       
   435             }
       
   436 
       
   437             abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types);
       
   438 
       
   439             abstract List<Type> undetvars();
       
   440 
       
   441             class UninferredReturnType extends ForAll {
       
   442                 public UninferredReturnType(List<Type> tvars, Type restype) {
       
   443                     super(tvars, restype);
       
   444                 }
       
   445                 @Override
       
   446                 public Type inst(List<Type> actuals, Types types) {
       
   447                     Type newRestype = super.inst(actuals, types);
       
   448                     instantiateReturnType(newRestype, actuals, types);
       
   449                     if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
       
   450                         log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
       
   451                     }
       
   452                     return UninferredMethodType.this.qtype.getReturnType();
       
   453                 }
       
   454                 @Override
       
   455                 public List<Type> undetvars() {
       
   456                     return UninferredMethodType.this.undetvars();
       
   457                 }
       
   458             }
   397             }
   459         }
   398         }
   460 
   399 
   461         private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
   400         private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
   462                 boolean allowBoxing, boolean useVarargs, Warner warn) {
   401                 boolean allowBoxing, boolean useVarargs, Warner warn) {