1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Sep 25 11:55:34 2012 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Sep 25 11:56:46 2012 +0100 1.3 @@ -28,6 +28,7 @@ 1.4 import com.sun.tools.javac.code.*; 1.5 import com.sun.tools.javac.code.Symbol.*; 1.6 import com.sun.tools.javac.code.Type.*; 1.7 +import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; 1.8 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; 1.9 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; 1.10 import com.sun.tools.javac.tree.JCTree; 1.11 @@ -39,6 +40,7 @@ 1.12 1.13 import java.util.HashMap; 1.14 import java.util.Map; 1.15 +import java.util.Set; 1.16 1.17 import static com.sun.tools.javac.code.TypeTags.*; 1.18 1.19 @@ -120,8 +122,8 @@ 1.20 * Throw a NoInstanceException if this not possible. 1.21 */ 1.22 void maximizeInst(UndetVar that, Warner warn) throws InferenceException { 1.23 - List<Type> hibounds = Type.filter(that.hibounds, boundFilter); 1.24 - if (that.eq.isEmpty()) { 1.25 + List<Type> hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter); 1.26 + if (that.getBounds(InferenceBound.EQ).isEmpty()) { 1.27 if (hibounds.isEmpty()) 1.28 that.inst = syms.objectType; 1.29 else if (hibounds.tail.isEmpty()) 1.30 @@ -129,7 +131,7 @@ 1.31 else 1.32 that.inst = types.glb(hibounds); 1.33 } else { 1.34 - that.inst = that.eq.head; 1.35 + that.inst = that.getBounds(InferenceBound.EQ).head; 1.36 } 1.37 if (that.inst == null || 1.38 that.inst.isErroneous()) 1.39 @@ -149,8 +151,8 @@ 1.40 * Throw a NoInstanceException if this not possible. 1.41 */ 1.42 void minimizeInst(UndetVar that, Warner warn) throws InferenceException { 1.43 - List<Type> lobounds = Type.filter(that.lobounds, boundFilter); 1.44 - if (that.eq.isEmpty()) { 1.45 + List<Type> lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter); 1.46 + if (that.getBounds(InferenceBound.EQ).isEmpty()) { 1.47 if (lobounds.isEmpty()) { 1.48 //do nothing - the inference variable is under-constrained 1.49 return; 1.50 @@ -164,7 +166,7 @@ 1.51 .setMessage("no.unique.minimal.instance.exists", 1.52 that.qtype, lobounds); 1.53 } else { 1.54 - that.inst = that.eq.head; 1.55 + that.inst = that.getBounds(InferenceBound.EQ).head; 1.56 } 1.57 } 1.58 1.59 @@ -201,7 +203,8 @@ 1.60 boolean stuck = true; 1.61 for (Type t : inferenceContext.undetvars) { 1.62 UndetVar uv = (UndetVar)t; 1.63 - if (uv.inst == null && (uv.eq.nonEmpty() || !inferenceContext.free(uv.hibounds))) { 1.64 + if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() || 1.65 + !inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) { 1.66 maximizeInst((UndetVar)t, warn); 1.67 stuck = false; 1.68 } 1.69 @@ -219,7 +222,7 @@ 1.70 //variables in remaining upper bounds and continue 1.71 for (Type t : inferenceContext.undetvars) { 1.72 UndetVar uv = (UndetVar)t; 1.73 - uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types); 1.74 + uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types); 1.75 } 1.76 } 1.77 } 1.78 @@ -235,7 +238,7 @@ 1.79 UndetVar uv = (UndetVar)t; 1.80 if (uv.inst == null) { 1.81 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner); 1.82 - fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null); 1.83 + fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null); 1.84 todo.append(uv); 1.85 uv.inst = fresh_tvar.type; 1.86 } 1.87 @@ -267,7 +270,7 @@ 1.88 boolean useVarargs, 1.89 Warner warn) throws InferenceException { 1.90 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG 1.91 - final InferenceContext inferenceContext = new InferenceContext(tvars, types); 1.92 + final InferenceContext inferenceContext = new InferenceContext(tvars, this); 1.93 inferenceException.clear(); 1.94 1.95 try { 1.96 @@ -286,7 +289,7 @@ 1.97 List<Type> restvars = inferenceContext.restvars(); 1.98 1.99 if (!restvars.isEmpty()) { 1.100 - if (resultInfo != null) { 1.101 + if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { 1.102 instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn); 1.103 checkWithinBounds(inferenceContext, warn); 1.104 mt = (MethodType)inferenceContext.asInstType(mt, types); 1.105 @@ -332,34 +335,58 @@ 1.106 /** check that type parameters are within their bounds. 1.107 */ 1.108 void checkWithinBounds(InferenceContext inferenceContext, 1.109 - Warner warn) 1.110 - throws InferenceException { 1.111 - List<Type> tvars = inferenceContext.inferenceVars(); 1.112 + Warner warn) throws InferenceException { 1.113 + //step 1 - check compatibility of instantiated type w.r.t. initial bounds 1.114 for (Type t : inferenceContext.undetvars) { 1.115 UndetVar uv = (UndetVar)t; 1.116 - uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types); 1.117 - uv.lobounds = inferenceContext.asInstTypes(uv.lobounds, types); 1.118 - uv.eq = inferenceContext.asInstTypes(uv.eq, types); 1.119 + uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types); 1.120 checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars()); 1.121 - if (!inferenceContext.restvars().contains(tvars.head)) { 1.122 + if (!inferenceContext.restvars().contains(uv.qtype)) { 1.123 Type inst = inferenceContext.asInstType(t, types); 1.124 - for (Type u : uv.hibounds) { 1.125 + for (Type u : uv.getBounds(InferenceBound.UPPER)) { 1.126 if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) { 1.127 reportBoundError(uv, BoundErrorKind.UPPER); 1.128 } 1.129 } 1.130 - for (Type l : uv.lobounds) { 1.131 - if (!types.isSubtypeUnchecked(inferenceContext.asFree(l, types), inst, warn)) { 1.132 + for (Type l : uv.getBounds(InferenceBound.LOWER)) { 1.133 + Assert.check(!inferenceContext.free(l)); 1.134 + if (!types.isSubtypeUnchecked(l, inst, warn)) { 1.135 reportBoundError(uv, BoundErrorKind.LOWER); 1.136 } 1.137 } 1.138 - for (Type e : uv.eq) { 1.139 - if (!types.isSameType(inst, inferenceContext.asFree(e, types))) { 1.140 + for (Type e : uv.getBounds(InferenceBound.EQ)) { 1.141 + Assert.check(!inferenceContext.free(e)); 1.142 + if (!types.isSameType(inst, e)) { 1.143 reportBoundError(uv, BoundErrorKind.EQ); 1.144 } 1.145 } 1.146 } 1.147 - tvars = tvars.tail; 1.148 + } 1.149 + 1.150 + //step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds 1.151 + for (Type t : inferenceContext.undetvars) { 1.152 + UndetVar uv = (UndetVar)t; 1.153 + //check eq bounds consistency 1.154 + Type eq = null; 1.155 + for (Type e : uv.getBounds(InferenceBound.EQ)) { 1.156 + Assert.check(!inferenceContext.free(e)); 1.157 + if (eq != null && !types.isSameType(e, eq)) { 1.158 + reportBoundError(uv, BoundErrorKind.EQ); 1.159 + } 1.160 + eq = e; 1.161 + for (Type l : uv.getBounds(InferenceBound.LOWER)) { 1.162 + Assert.check(!inferenceContext.free(l)); 1.163 + if (!types.isSubtypeUnchecked(l, e, warn)) { 1.164 + reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER); 1.165 + } 1.166 + } 1.167 + for (Type u : uv.getBounds(InferenceBound.UPPER)) { 1.168 + if (inferenceContext.free(u)) continue; 1.169 + if (!types.isSubtypeUnchecked(e, u, warn)) { 1.170 + reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); 1.171 + } 1.172 + } 1.173 + } 1.174 } 1.175 } 1.176 1.177 @@ -367,7 +394,7 @@ 1.178 // VGJ: sort of inlined maximizeInst() below. Adding 1.179 // bounds can cause lobounds that are above hibounds. 1.180 ListBuffer<Type> hiboundsNoVars = ListBuffer.lb(); 1.181 - for (Type t : Type.filter(uv.hibounds, boundFilter)) { 1.182 + for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) { 1.183 if (!t.containsAny(tvars)) { 1.184 hiboundsNoVars.append(t); 1.185 } 1.186 @@ -388,25 +415,43 @@ 1.187 BAD_UPPER() { 1.188 @Override 1.189 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.190 - return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds); 1.191 + return ex.setMessage("incompatible.upper.bounds", uv.qtype, 1.192 + uv.getBounds(InferenceBound.UPPER)); 1.193 + } 1.194 + }, 1.195 + BAD_EQ_UPPER() { 1.196 + @Override 1.197 + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.198 + return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype, 1.199 + uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER)); 1.200 + } 1.201 + }, 1.202 + BAD_EQ_LOWER() { 1.203 + @Override 1.204 + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.205 + return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype, 1.206 + uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER)); 1.207 } 1.208 }, 1.209 UPPER() { 1.210 @Override 1.211 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.212 - return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds); 1.213 + return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, 1.214 + uv.getBounds(InferenceBound.UPPER)); 1.215 } 1.216 }, 1.217 LOWER() { 1.218 @Override 1.219 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.220 - return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds); 1.221 + return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, 1.222 + uv.getBounds(InferenceBound.LOWER)); 1.223 } 1.224 }, 1.225 EQ() { 1.226 @Override 1.227 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { 1.228 - return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq); 1.229 + return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, 1.230 + uv.getBounds(InferenceBound.EQ)); 1.231 } 1.232 }; 1.233 1.234 @@ -480,9 +525,9 @@ 1.235 * Mapping that turns inference variables into undet vars 1.236 * (used by inference context) 1.237 */ 1.238 - static Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") { 1.239 + Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") { 1.240 public Type apply(Type t) { 1.241 - if (t.tag == TYPEVAR) return new UndetVar(t); 1.242 + if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types); 1.243 else return t.map(this); 1.244 } 1.245 }; 1.246 @@ -517,13 +562,9 @@ 1.247 1.248 List<FreeTypeListener> freetypeListeners = List.nil(); 1.249 1.250 - public InferenceContext(List<Type> inferencevars, Types types) { 1.251 - this.undetvars = Type.map(inferencevars, fromTypeVarFun); 1.252 + public InferenceContext(List<Type> inferencevars, Infer infer) { 1.253 + this.undetvars = Type.map(inferencevars, infer.fromTypeVarFun); 1.254 this.inferencevars = inferencevars; 1.255 - for (Type t : this.undetvars) { 1.256 - UndetVar uv = (UndetVar)t; 1.257 - uv.hibounds = types.getBounds((TypeVar)uv.qtype); 1.258 - } 1.259 } 1.260 1.261 /** 1.262 @@ -669,5 +710,5 @@ 1.263 } 1.264 } 1.265 1.266 - final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), types); 1.267 + final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this); 1.268 }