langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 3778 38a70273507b
parent 3140 15a274b13051
child 5489 e7af65bf7577
equal deleted inserted replaced
3777:9d8c7669df64 3778:38a70273507b
    27 
    27 
    28 import com.sun.tools.javac.util.*;
    28 import com.sun.tools.javac.util.*;
    29 import com.sun.tools.javac.util.List;
    29 import com.sun.tools.javac.util.List;
    30 import com.sun.tools.javac.code.*;
    30 import com.sun.tools.javac.code.*;
    31 import com.sun.tools.javac.code.Type.*;
    31 import com.sun.tools.javac.code.Type.*;
       
    32 import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
    32 import com.sun.tools.javac.code.Symbol.*;
    33 import com.sun.tools.javac.code.Symbol.*;
    33 import com.sun.tools.javac.util.JCDiagnostic;
    34 import com.sun.tools.javac.util.JCDiagnostic;
    34 
    35 
    35 import static com.sun.tools.javac.code.TypeTags.*;
    36 import static com.sun.tools.javac.code.TypeTags.*;
    36 
    37 
    48     /** A value for prototypes that admit any type, including polymorphic ones. */
    49     /** A value for prototypes that admit any type, including polymorphic ones. */
    49     public static final Type anyPoly = new Type(NONE, null);
    50     public static final Type anyPoly = new Type(NONE, null);
    50 
    51 
    51     Symtab syms;
    52     Symtab syms;
    52     Types types;
    53     Types types;
       
    54     Check chk;
    53     Resolve rs;
    55     Resolve rs;
    54     JCDiagnostic.Factory diags;
    56     JCDiagnostic.Factory diags;
    55 
    57 
    56     public static Infer instance(Context context) {
    58     public static Infer instance(Context context) {
    57         Infer instance = context.get(inferKey);
    59         Infer instance = context.get(inferKey);
    63     protected Infer(Context context) {
    65     protected Infer(Context context) {
    64         context.put(inferKey, this);
    66         context.put(inferKey, this);
    65         syms = Symtab.instance(context);
    67         syms = Symtab.instance(context);
    66         types = Types.instance(context);
    68         types = Types.instance(context);
    67         rs = Resolve.instance(context);
    69         rs = Resolve.instance(context);
       
    70         chk = Check.instance(context);
    68         diags = JCDiagnostic.Factory.instance(context);
    71         diags = JCDiagnostic.Factory.instance(context);
    69         ambiguousNoInstanceException =
    72         ambiguousNoInstanceException =
    70             new NoInstanceException(true, diags);
    73             new NoInstanceException(true, diags);
    71         unambiguousNoInstanceException =
    74         unambiguousNoInstanceException =
    72             new NoInstanceException(false, diags);
    75             new NoInstanceException(false, diags);
   248     public Type instantiateExpr(ForAll that,
   251     public Type instantiateExpr(ForAll that,
   249                                 Type to,
   252                                 Type to,
   250                                 Warner warn) throws InferenceException {
   253                                 Warner warn) throws InferenceException {
   251         List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun);
   254         List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun);
   252         for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
   255         for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
   253             UndetVar v = (UndetVar) l.head;
   256             UndetVar uv = (UndetVar) l.head;
       
   257             TypeVar tv = (TypeVar)uv.qtype;
   254             ListBuffer<Type> hibounds = new ListBuffer<Type>();
   258             ListBuffer<Type> hibounds = new ListBuffer<Type>();
   255             for (List<Type> l1 = types.getBounds((TypeVar) v.qtype); l1.nonEmpty(); l1 = l1.tail) {
   259             for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS).prependList(types.getBounds(tv))) {
   256                 if (!l1.head.containsSome(that.tvars)) {
   260                 if (!t.containsSome(that.tvars) && t.tag != BOT) {
   257                     hibounds.append(l1.head);
   261                     hibounds.append(t);
   258                 }
   262                 }
   259             }
   263             }
   260             v.hibounds = hibounds.toList();
   264             List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL);
       
   265             if (inst.nonEmpty() && inst.head.tag != BOT) {
       
   266                 uv.inst = inst.head;
       
   267             }
       
   268             uv.hibounds = hibounds.toList();
   261         }
   269         }
   262         Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
   270         Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
   263         if (!types.isSubtype(qtype1, to)) {
   271         if (!types.isSubtype(qtype1, to)) {
   264             throw unambiguousNoInstanceException
   272             throw unambiguousNoInstanceException
   265                 .setMessage("no.conforming.instance.exists",
   273                 .setMessage("no.conforming.instance.exists",
   271 
   279 
   272         // check bounds
   280         // check bounds
   273         List<Type> targs = Type.map(undetvars, getInstFun);
   281         List<Type> targs = Type.map(undetvars, getInstFun);
   274         targs = types.subst(targs, that.tvars, targs);
   282         targs = types.subst(targs, that.tvars, targs);
   275         checkWithinBounds(that.tvars, targs, warn);
   283         checkWithinBounds(that.tvars, targs, warn);
   276         return that.inst(targs, types);
   284         return chk.checkType(warn.pos(), that.inst(targs, types), to);
   277     }
   285     }
   278 
   286 
   279     /** Instantiate method type `mt' by finding instantiations of
   287     /** Instantiate method type `mt' by finding instantiations of
   280      *  `tvars' so that method can be applied to `argtypes'.
   288      *  `tvars' so that method can be applied to `argtypes'.
   281      */
   289      */
   347             minimizeInst((UndetVar) t, warn);
   355             minimizeInst((UndetVar) t, warn);
   348 
   356 
   349         /** Type variables instantiated to bottom */
   357         /** Type variables instantiated to bottom */
   350         ListBuffer<Type> restvars = new ListBuffer<Type>();
   358         ListBuffer<Type> restvars = new ListBuffer<Type>();
   351 
   359 
       
   360         /** Undet vars instantiated to bottom */
       
   361         final ListBuffer<Type> restundet = new ListBuffer<Type>();
       
   362 
   352         /** Instantiated types or TypeVars if under-constrained */
   363         /** Instantiated types or TypeVars if under-constrained */
   353         ListBuffer<Type> insttypes = new ListBuffer<Type>();
   364         ListBuffer<Type> insttypes = new ListBuffer<Type>();
   354 
   365 
   355         /** Instantiated types or UndetVars if under-constrained */
   366         /** Instantiated types or UndetVars if under-constrained */
   356         ListBuffer<Type> undettypes = new ListBuffer<Type>();
   367         ListBuffer<Type> undettypes = new ListBuffer<Type>();
   357 
   368 
   358         for (Type t : undetvars) {
   369         for (Type t : undetvars) {
   359             UndetVar uv = (UndetVar)t;
   370             UndetVar uv = (UndetVar)t;
   360             if (uv.inst.tag == BOT) {
   371             if (uv.inst.tag == BOT) {
   361                 restvars.append(uv.qtype);
   372                 restvars.append(uv.qtype);
       
   373                 restundet.append(uv);
   362                 insttypes.append(uv.qtype);
   374                 insttypes.append(uv.qtype);
   363                 undettypes.append(uv);
   375                 undettypes.append(uv);
   364                 uv.inst = null;
   376                 uv.inst = null;
   365             } else {
   377             } else {
   366                 insttypes.append(uv.inst);
   378                 insttypes.append(uv.inst);
   377             final List<Type> inferredTypes = insttypes.toList();
   389             final List<Type> inferredTypes = insttypes.toList();
   378             final List<Type> all_tvars = tvars; //this is the wrong tvars
   390             final List<Type> all_tvars = tvars; //this is the wrong tvars
   379             final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass);
   391             final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass);
   380             mt2.restype = new ForAll(restvars.toList(), mt.restype) {
   392             mt2.restype = new ForAll(restvars.toList(), mt.restype) {
   381                 @Override
   393                 @Override
       
   394                 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
       
   395                     for (Type t : restundet.toList()) {
       
   396                         UndetVar uv = (UndetVar)t;
       
   397                         if (uv.qtype == tv) {
       
   398                             switch (ck) {
       
   399                                 case EXTENDS: return uv.hibounds;
       
   400                                 case SUPER: return uv.lobounds;
       
   401                                 case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil();
       
   402                             }
       
   403                         }
       
   404                     }
       
   405                     return List.nil();
       
   406                 }
       
   407 
       
   408                 @Override
   382                 public Type inst(List<Type> inferred, Types types) throws NoInstanceException {
   409                 public Type inst(List<Type> inferred, Types types) throws NoInstanceException {
   383                     List<Type> formals = types.subst(mt2.argtypes, tvars, inferred);
   410                     List<Type> formals = types.subst(mt2.argtypes, tvars, inferred);
   384                    if (!rs.argumentsAcceptable(capturedArgs, formals,
   411                     if (!rs.argumentsAcceptable(capturedArgs, formals,
   385                            allowBoxing, useVarargs, warn)) {
   412                            allowBoxing, useVarargs, warn)) {
   386                       // inferred method is not applicable
   413                       // inferred method is not applicable
   387                       throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes);
   414                       throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes);
   388                    }
   415                     }
   389                    // check that inferred bounds conform to their bounds
   416                     // check that inferred bounds conform to their bounds
   390                    checkWithinBounds(all_tvars,
   417                     checkWithinBounds(all_tvars,
   391                            types.subst(inferredTypes, tvars, inferred), warn);
   418                            types.subst(inferredTypes, tvars, inferred), warn);
   392                    return super.inst(inferred, types);
   419                     return super.inst(inferred, types);
   393             }};
   420             }};
   394             return mt2;
   421             return mt2;
   395         }
   422         }
   396         else if (!rs.argumentsAcceptable(capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn)) {
   423         else if (!rs.argumentsAcceptable(capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn)) {
   397             // inferred method is not applicable
   424             // inferred method is not applicable