langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 3778 38a70273507b
parent 3140 15a274b13051
child 5489 e7af65bf7577
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Aug 31 19:43:06 2009 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Sep 01 14:53:39 2009 +0100
@@ -29,6 +29,7 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.JCDiagnostic;
 
@@ -50,6 +51,7 @@
 
     Symtab syms;
     Types types;
+    Check chk;
     Resolve rs;
     JCDiagnostic.Factory diags;
 
@@ -65,6 +67,7 @@
         syms = Symtab.instance(context);
         types = Types.instance(context);
         rs = Resolve.instance(context);
+        chk = Check.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         ambiguousNoInstanceException =
             new NoInstanceException(true, diags);
@@ -250,14 +253,19 @@
                                 Warner warn) throws InferenceException {
         List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun);
         for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
-            UndetVar v = (UndetVar) l.head;
+            UndetVar uv = (UndetVar) l.head;
+            TypeVar tv = (TypeVar)uv.qtype;
             ListBuffer<Type> hibounds = new ListBuffer<Type>();
-            for (List<Type> l1 = types.getBounds((TypeVar) v.qtype); l1.nonEmpty(); l1 = l1.tail) {
-                if (!l1.head.containsSome(that.tvars)) {
-                    hibounds.append(l1.head);
+            for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS).prependList(types.getBounds(tv))) {
+                if (!t.containsSome(that.tvars) && t.tag != BOT) {
+                    hibounds.append(t);
                 }
             }
-            v.hibounds = hibounds.toList();
+            List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL);
+            if (inst.nonEmpty() && inst.head.tag != BOT) {
+                uv.inst = inst.head;
+            }
+            uv.hibounds = hibounds.toList();
         }
         Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
         if (!types.isSubtype(qtype1, to)) {
@@ -273,7 +281,7 @@
         List<Type> targs = Type.map(undetvars, getInstFun);
         targs = types.subst(targs, that.tvars, targs);
         checkWithinBounds(that.tvars, targs, warn);
-        return that.inst(targs, types);
+        return chk.checkType(warn.pos(), that.inst(targs, types), to);
     }
 
     /** Instantiate method type `mt' by finding instantiations of
@@ -349,6 +357,9 @@
         /** Type variables instantiated to bottom */
         ListBuffer<Type> restvars = new ListBuffer<Type>();
 
+        /** Undet vars instantiated to bottom */
+        final ListBuffer<Type> restundet = new ListBuffer<Type>();
+
         /** Instantiated types or TypeVars if under-constrained */
         ListBuffer<Type> insttypes = new ListBuffer<Type>();
 
@@ -359,6 +370,7 @@
             UndetVar uv = (UndetVar)t;
             if (uv.inst.tag == BOT) {
                 restvars.append(uv.qtype);
+                restundet.append(uv);
                 insttypes.append(uv.qtype);
                 undettypes.append(uv);
                 uv.inst = null;
@@ -379,17 +391,32 @@
             final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass);
             mt2.restype = new ForAll(restvars.toList(), mt.restype) {
                 @Override
+                public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
+                    for (Type t : restundet.toList()) {
+                        UndetVar uv = (UndetVar)t;
+                        if (uv.qtype == tv) {
+                            switch (ck) {
+                                case EXTENDS: return uv.hibounds;
+                                case SUPER: return uv.lobounds;
+                                case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil();
+                            }
+                        }
+                    }
+                    return List.nil();
+                }
+
+                @Override
                 public Type inst(List<Type> inferred, Types types) throws NoInstanceException {
                     List<Type> formals = types.subst(mt2.argtypes, tvars, inferred);
-                   if (!rs.argumentsAcceptable(capturedArgs, formals,
+                    if (!rs.argumentsAcceptable(capturedArgs, formals,
                            allowBoxing, useVarargs, warn)) {
                       // inferred method is not applicable
                       throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes);
-                   }
-                   // check that inferred bounds conform to their bounds
-                   checkWithinBounds(all_tvars,
+                    }
+                    // check that inferred bounds conform to their bounds
+                    checkWithinBounds(all_tvars,
                            types.subst(inferredTypes, tvars, inferred), warn);
-                   return super.inst(inferred, types);
+                    return super.inst(inferred, types);
             }};
             return mt2;
         }