src/share/classes/com/sun/tools/javac/comp/Infer.java

changeset 1251
6f0ed5a89c25
parent 1239
2827076dbf64
child 1268
af6a4c24f4e3
equal deleted inserted replaced
1250:c35b158e2290 1251:6f0ed5a89c25
30 import com.sun.tools.javac.tree.TreeInfo; 30 import com.sun.tools.javac.tree.TreeInfo;
31 import com.sun.tools.javac.util.*; 31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.List; 32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.code.*; 33 import com.sun.tools.javac.code.*;
34 import com.sun.tools.javac.code.Type.*; 34 import com.sun.tools.javac.code.Type.*;
35 import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
36 import com.sun.tools.javac.code.Symbol.*; 35 import com.sun.tools.javac.code.Symbol.*;
37 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; 36 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
38 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; 37 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
40 39
120 * Auxiliary type values and classes 119 * Auxiliary type values and classes
121 ***************************************************************************/ 120 ***************************************************************************/
122 121
123 /** A mapping that turns type variables into undetermined type variables. 122 /** A mapping that turns type variables into undetermined type variables.
124 */ 123 */
125 Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") { 124 List<Type> makeUndetvars(List<Type> tvars) {
126 public Type apply(Type t) { 125 List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
127 if (t.tag == TYPEVAR) return new UndetVar(t); 126 for (Type t : undetvars) {
128 else return t.map(this); 127 UndetVar uv = (UndetVar)t;
129 } 128 uv.hibounds = types.getBounds((TypeVar)uv.qtype);
130 }; 129 }
131 130 return undetvars;
132 /** A mapping that returns its type argument with every UndetVar replaced 131 }
133 * by its `inst' field. Throws a NoInstanceException 132 //where
134 * if this not possible because an `inst' field is null. 133 Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
135 * Note: mutually referring undertvars will be left uninstantiated 134 public Type apply(Type t) {
136 * (that is, they will be replaced by the underlying type-variable). 135 if (t.tag == TYPEVAR) return new UndetVar(t);
137 */ 136 else return t.map(this);
138 137 }
139 Mapping getInstFun = new Mapping("getInstFun") { 138 };
140 public Type apply(Type t) {
141 switch (t.tag) {
142 case UNKNOWN:
143 throw ambiguousNoInstanceException
144 .setMessage("undetermined.type");
145 case UNDETVAR:
146 UndetVar that = (UndetVar) t;
147 if (that.inst == null)
148 throw ambiguousNoInstanceException
149 .setMessage("type.variable.has.undetermined.type",
150 that.qtype);
151 return isConstraintCyclic(that) ?
152 that.qtype :
153 apply(that.inst);
154 default:
155 return t.map(this);
156 }
157 }
158
159 private boolean isConstraintCyclic(UndetVar uv) {
160 Types.UnaryVisitor<Boolean> constraintScanner =
161 new Types.UnaryVisitor<Boolean>() {
162
163 List<Type> seen = List.nil();
164
165 Boolean visit(List<Type> ts) {
166 for (Type t : ts) {
167 if (visit(t)) return true;
168 }
169 return false;
170 }
171
172 public Boolean visitType(Type t, Void ignored) {
173 return false;
174 }
175
176 @Override
177 public Boolean visitClassType(ClassType t, Void ignored) {
178 if (t.isCompound()) {
179 return visit(types.supertype(t)) ||
180 visit(types.interfaces(t));
181 } else {
182 return visit(t.getTypeArguments());
183 }
184 }
185 @Override
186 public Boolean visitWildcardType(WildcardType t, Void ignored) {
187 return visit(t.type);
188 }
189
190 @Override
191 public Boolean visitUndetVar(UndetVar t, Void ignored) {
192 if (seen.contains(t)) {
193 return true;
194 } else {
195 seen = seen.prepend(t);
196 return visit(t.inst);
197 }
198 }
199 };
200 return constraintScanner.visit(uv);
201 }
202 };
203 139
204 /*************************************************************************** 140 /***************************************************************************
205 * Mini/Maximization of UndetVars 141 * Mini/Maximization of UndetVars
206 ***************************************************************************/ 142 ***************************************************************************/
207 143
208 /** Instantiate undetermined type variable to its minimal upper bound. 144 /** Instantiate undetermined type variable to its minimal upper bound.
209 * Throw a NoInstanceException if this not possible. 145 * Throw a NoInstanceException if this not possible.
210 */ 146 */
211 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException { 147 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
212 List<Type> hibounds = Type.filter(that.hibounds, errorFilter); 148 List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
213 if (that.inst == null) { 149 if (that.eq.isEmpty()) {
214 if (hibounds.isEmpty()) 150 if (hibounds.isEmpty())
215 that.inst = syms.objectType; 151 that.inst = syms.objectType;
216 else if (hibounds.tail.isEmpty()) 152 else if (hibounds.tail.isEmpty())
217 that.inst = hibounds.head; 153 that.inst = hibounds.head;
218 else 154 else
219 that.inst = types.glb(hibounds); 155 that.inst = types.glb(hibounds);
156 } else {
157 that.inst = that.eq.head;
220 } 158 }
221 if (that.inst == null || 159 if (that.inst == null ||
222 that.inst.isErroneous()) 160 that.inst.isErroneous())
223 throw ambiguousNoInstanceException 161 throw ambiguousNoInstanceException
224 .setMessage("no.unique.maximal.instance.exists", 162 .setMessage("no.unique.maximal.instance.exists",
225 that.qtype, hibounds); 163 that.qtype, hibounds);
226 } 164 }
227 //where
228 private boolean isSubClass(Type t, final List<Type> ts) {
229 t = t.baseType();
230 if (t.tag == TYPEVAR) {
231 List<Type> bounds = types.getBounds((TypeVar)t);
232 for (Type s : ts) {
233 if (!types.isSameType(t, s.baseType())) {
234 for (Type bound : bounds) {
235 if (!isSubClass(bound, List.of(s.baseType())))
236 return false;
237 }
238 }
239 }
240 } else {
241 for (Type s : ts) {
242 if (!t.tsym.isSubClass(s.baseType().tsym, types))
243 return false;
244 }
245 }
246 return true;
247 }
248 165
249 private Filter<Type> errorFilter = new Filter<Type>() { 166 private Filter<Type> errorFilter = new Filter<Type>() {
250 @Override 167 @Override
251 public boolean accepts(Type t) { 168 public boolean accepts(Type t) {
252 return !t.isErroneous(); 169 return !t.isErroneous();
256 /** Instantiate undetermined type variable to the lub of all its lower bounds. 173 /** Instantiate undetermined type variable to the lub of all its lower bounds.
257 * Throw a NoInstanceException if this not possible. 174 * Throw a NoInstanceException if this not possible.
258 */ 175 */
259 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException { 176 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
260 List<Type> lobounds = Type.filter(that.lobounds, errorFilter); 177 List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
261 if (that.inst == null) { 178 if (that.eq.isEmpty()) {
262 if (lobounds.isEmpty()) 179 if (lobounds.isEmpty())
263 that.inst = syms.botType; 180 that.inst = syms.botType;
264 else if (lobounds.tail.isEmpty()) 181 else if (lobounds.tail.isEmpty())
265 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head; 182 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
266 else { 183 else {
268 } 185 }
269 if (that.inst == null || that.inst.tag == ERROR) 186 if (that.inst == null || that.inst.tag == ERROR)
270 throw ambiguousNoInstanceException 187 throw ambiguousNoInstanceException
271 .setMessage("no.unique.minimal.instance.exists", 188 .setMessage("no.unique.minimal.instance.exists",
272 that.qtype, lobounds); 189 that.qtype, lobounds);
273 // VGJ: sort of inlined maximizeInst() below. Adding 190 } else {
274 // bounds can cause lobounds that are above hibounds. 191 that.inst = that.eq.head;
275 List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
276 Type hb = null;
277 if (hibounds.isEmpty())
278 hb = syms.objectType;
279 else if (hibounds.tail.isEmpty())
280 hb = hibounds.head;
281 else
282 hb = types.glb(hibounds);
283 if (hb == null ||
284 hb.isErroneous())
285 throw ambiguousNoInstanceException
286 .setMessage("incompatible.upper.bounds",
287 that.qtype, hibounds);
288 } 192 }
289 } 193 }
290 194
291 Type asUndetType(Type t, List<Type> undetvars) { 195 Type asUndetType(Type t, List<Type> undetvars) {
292 return types.subst(t, inferenceVars(undetvars), undetvars); 196 return types.subst(t, inferenceVars(undetvars), undetvars);
311 * best instantiations exist throw a NoInstanceException. 215 * best instantiations exist throw a NoInstanceException.
312 */ 216 */
313 public Type instantiateExpr(ForAll that, 217 public Type instantiateExpr(ForAll that,
314 Type to, 218 Type to,
315 Warner warn) throws InferenceException { 219 Warner warn) throws InferenceException {
316 List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun); 220 List<Type> undetvars = that.undetvars();
317 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
318 UndetVar uv = (UndetVar) l.head;
319 TypeVar tv = (TypeVar)uv.qtype;
320 ListBuffer<Type> hibounds = new ListBuffer<Type>();
321 for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS)) {
322 hibounds.append(types.subst(t, that.tvars, undetvars));
323 }
324
325 List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL);
326 if (inst.nonEmpty() && inst.head.tag != BOT) {
327 uv.inst = inst.head;
328 }
329 uv.hibounds = hibounds.toList();
330 }
331 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars); 221 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
332 if (!types.isSubtype(qtype1, 222 if (!types.isSubtype(qtype1,
333 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) { 223 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
334 throw unambiguousNoInstanceException 224 throw unambiguousNoInstanceException
335 .setMessage("infer.no.conforming.instance.exists", 225 .setMessage("infer.no.conforming.instance.exists",
336 that.tvars, that.qtype, to); 226 that.tvars, that.qtype, to);
337 } 227 }
338 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) 228
339 maximizeInst((UndetVar) l.head, warn); 229 List<Type> insttypes;
340 // System.out.println(" = " + qtype1.map(getInstFun));//DEBUG 230 while (true) {
341 231 boolean stuck = true;
342 // check bounds 232 insttypes = List.nil();
343 List<Type> targs = Type.map(undetvars, getInstFun); 233 for (Type t : undetvars) {
344 if (Type.containsAny(targs, that.tvars)) { 234 UndetVar uv = (UndetVar)t;
345 //replace uninferred type-vars 235 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, that.tvars))) {
346 targs = types.subst(targs, 236 maximizeInst((UndetVar)t, warn);
237 stuck = false;
238 }
239 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
240 }
241 if (!Type.containsAny(insttypes, that.tvars)) {
242 //all variables have been instantiated - exit
243 break;
244 } else if (stuck) {
245 //some variables could not be instantiated because of cycles in
246 //upper bounds - provide a (possibly recursive) default instantiation
247 insttypes = types.subst(insttypes,
347 that.tvars, 248 that.tvars,
348 instantiateAsUninferredVars(undetvars, that.tvars)); 249 instantiateAsUninferredVars(undetvars, that.tvars));
349 } 250 break;
350 return that.inst(targs, types); 251 } else {
351 } 252 //some variables have been instantiated - replace newly instantiated
352 //where 253 //variables in remaining upper bounds and continue
254 for (Type t : undetvars) {
255 UndetVar uv = (UndetVar)t;
256 uv.hibounds = types.subst(uv.hibounds, that.tvars, insttypes);
257 }
258 }
259 }
260 return that.inst(insttypes, types);
261 }
262
263 /**
264 * Infer cyclic inference variables as described in 15.12.2.8.
265 */
353 private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) { 266 private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
354 Assert.check(undetvars.length() == tvars.length()); 267 Assert.check(undetvars.length() == tvars.length());
355 ListBuffer<Type> new_targs = ListBuffer.lb(); 268 ListBuffer<Type> insttypes = ListBuffer.lb();
356 //step 1 - create synthetic captured vars 269 ListBuffer<Type> todo = ListBuffer.lb();
270 //step 1 - create fresh tvars
357 for (Type t : undetvars) { 271 for (Type t : undetvars) {
358 UndetVar uv = (UndetVar)t; 272 UndetVar uv = (UndetVar)t;
359 Type newArg = new CapturedType(t.tsym.name, t.tsym, uv.inst, syms.botType, null); 273 if (uv.inst == null) {
360 new_targs = new_targs.append(newArg); 274 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
361 } 275 fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
362 //step 2 - replace synthetic vars in their bounds 276 todo.append(uv);
277 uv.inst = fresh_tvar.type;
278 }
279 insttypes.append(uv.inst);
280 }
281 //step 2 - replace fresh tvars in their bounds
363 List<Type> formals = tvars; 282 List<Type> formals = tvars;
364 for (Type t : new_targs.toList()) { 283 for (Type t : todo) {
365 CapturedType ct = (CapturedType)t; 284 UndetVar uv = (UndetVar)t;
366 ct.bound = types.subst(ct.bound, tvars, new_targs.toList()); 285 TypeVar ct = (TypeVar)uv.inst;
367 WildcardType wt = new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass); 286 ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
368 wt.bound = (TypeVar)formals.head; 287 if (ct.bound.isErroneous()) {
369 ct.wildcard = wt; 288 //report inference error if glb fails
289 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
290 }
370 formals = formals.tail; 291 formals = formals.tail;
371 } 292 }
372 return new_targs.toList(); 293 return insttypes.toList();
373 } 294 }
374 295
375 /** Instantiate method type `mt' by finding instantiations of 296 /** Instantiate method type `mt' by finding instantiations of
376 * `tvars' so that method can be applied to `argtypes'. 297 * `tvars' so that method can be applied to `argtypes'.
377 */ 298 */
382 final List<Type> argtypes, 303 final List<Type> argtypes,
383 final boolean allowBoxing, 304 final boolean allowBoxing,
384 final boolean useVarargs, 305 final boolean useVarargs,
385 final Warner warn) throws InferenceException { 306 final Warner warn) throws InferenceException {
386 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG 307 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
387 List<Type> undetvars = Type.map(tvars, fromTypeVarFun); 308 final List<Type> undetvars = makeUndetvars(tvars);
388 309
389 final List<Type> capturedArgs = 310 final List<Type> capturedArgs =
390 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(), 311 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
391 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars)); 312 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
392 313
417 } else { 338 } else {
418 insttypes.append(uv.inst); 339 insttypes.append(uv.inst);
419 undettypes.append(uv.inst); 340 undettypes.append(uv.inst);
420 } 341 }
421 } 342 }
422 checkWithinBounds(tvars, undettypes.toList(), warn); 343 checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
423 344
424 mt = (MethodType)types.subst(mt, tvars, insttypes.toList()); 345 mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
425 346
426 if (!restvars.isEmpty()) { 347 if (!restvars.isEmpty()) {
427 // if there are uninstantiated variables, 348 // if there are uninstantiated variables,
428 // quantify result type with them 349 // quantify result type with them
429 final List<Type> inferredTypes = insttypes.toList(); 350 final List<Type> inferredTypes = insttypes.toList();
430 final List<Type> all_tvars = tvars; //this is the wrong tvars 351 final List<Type> all_tvars = tvars; //this is the wrong tvars
431 return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) { 352 return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) {
432 @Override 353 @Override
433 List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { 354 List<Type> undetvars() {
434 for (Type t : restundet.toList()) { 355 return restundet.toList();
435 UndetVar uv = (UndetVar)t;
436 if (uv.qtype == tv) {
437 switch (ck) {
438 case EXTENDS: return uv.hibounds.appendList(types.subst(types.getBounds(tv), all_tvars, inferredTypes));
439 case SUPER: return uv.lobounds;
440 case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil();
441 }
442 }
443 }
444 return List.nil();
445 } 356 }
446 @Override 357 @Override
447 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException { 358 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
448 Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred), 359 Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
449 restype, 360 restype,
451 qtype.tsym); 362 qtype.tsym);
452 // check that actuals conform to inferred formals 363 // check that actuals conform to inferred formals
453 warn.clear(); 364 warn.clear();
454 checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn); 365 checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn);
455 // check that inferred bounds conform to their bounds 366 // check that inferred bounds conform to their bounds
456 checkWithinBounds(all_tvars, 367 checkWithinBounds(all_tvars, undetvars,
457 types.subst(inferredTypes, tvars, inferred), warn); 368 types.subst(inferredTypes, tvars, inferred), warn);
458 qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs, warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)); 369 qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs, warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED));
459 } 370 }
460 }; 371 };
461 } 372 }
523 return qtype.map(f); 434 return qtype.map(f);
524 } 435 }
525 436
526 abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types); 437 abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types);
527 438
528 abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck); 439 abstract List<Type> undetvars();
529 440
530 class UninferredReturnType extends ForAll { 441 class UninferredReturnType extends ForAll {
531 public UninferredReturnType(List<Type> tvars, Type restype) { 442 public UninferredReturnType(List<Type> tvars, Type restype) {
532 super(tvars, restype); 443 super(tvars, restype);
533 } 444 }
539 log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype); 450 log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
540 } 451 }
541 return UninferredMethodType.this.qtype.getReturnType(); 452 return UninferredMethodType.this.qtype.getReturnType();
542 } 453 }
543 @Override 454 @Override
544 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { 455 public List<Type> undetvars() {
545 return UninferredMethodType.this.getConstraints(tv, ck); 456 return UninferredMethodType.this.undetvars();
546 } 457 }
547 } 458 }
548 } 459 }
549 460
550 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, 461 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
557 // inferred method is not applicable 468 // inferred method is not applicable
558 throw invalidInstanceException.setMessage(ex.getDiagnostic()); 469 throw invalidInstanceException.setMessage(ex.getDiagnostic());
559 } 470 }
560 } 471 }
561 472
562 /** Try to instantiate argument type `that' to given type `to'.
563 * If this fails, try to insantiate `that' to `to' where
564 * every occurrence of a type variable in `tvars' is replaced
565 * by an unknown type.
566 */
567 private Type instantiateArg(ForAll that,
568 Type to,
569 List<Type> tvars,
570 Warner warn) throws InferenceException {
571 List<Type> targs;
572 try {
573 return instantiateExpr(that, to, warn);
574 } catch (NoInstanceException ex) {
575 Type to1 = to;
576 for (List<Type> l = tvars; l.nonEmpty(); l = l.tail)
577 to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType));
578 return instantiateExpr(that, to1, warn);
579 }
580 }
581
582 /** check that type parameters are within their bounds. 473 /** check that type parameters are within their bounds.
583 */ 474 */
584 void checkWithinBounds(List<Type> tvars, 475 void checkWithinBounds(List<Type> tvars,
585 List<Type> arguments, 476 List<Type> undetvars,
586 Warner warn) 477 List<Type> arguments,
478 Warner warn)
587 throws InvalidInstanceException { 479 throws InvalidInstanceException {
588 for (List<Type> tvs = tvars, args = arguments; 480 List<Type> args = arguments;
589 tvs.nonEmpty(); 481 for (Type t : undetvars) {
590 tvs = tvs.tail, args = args.tail) { 482 UndetVar uv = (UndetVar)t;
591 if (args.head instanceof UndetVar || 483 uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
592 tvars.head.getUpperBound().isErroneous()) continue; 484 uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
593 List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments); 485 uv.eq = types.subst(uv.eq, tvars, arguments);
594 if (!types.isSubtypeUnchecked(args.head, bounds, warn)) 486 checkCompatibleUpperBounds(uv, tvars);
595 throw invalidInstanceException 487 if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
596 .setMessage("inferred.do.not.conform.to.bounds", 488 Type inst = args.head;
597 args.head, bounds); 489 for (Type u : uv.hibounds) {
598 } 490 if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
491 reportBoundError(uv, BoundErrorKind.UPPER);
492 }
493 }
494 for (Type l : uv.lobounds) {
495 if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
496 reportBoundError(uv, BoundErrorKind.LOWER);
497 }
498 }
499 for (Type e : uv.eq) {
500 if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
501 reportBoundError(uv, BoundErrorKind.EQ);
502 }
503 }
504 }
505 args = args.tail;
506 }
507 }
508
509 void checkCompatibleUpperBounds(UndetVar uv, List<Type> tvars) {
510 // VGJ: sort of inlined maximizeInst() below. Adding
511 // bounds can cause lobounds that are above hibounds.
512 ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
513 for (Type t : Type.filter(uv.hibounds, errorFilter)) {
514 if (!t.containsAny(tvars)) {
515 hiboundsNoVars.append(t);
516 }
517 }
518 List<Type> hibounds = hiboundsNoVars.toList();
519 Type hb = null;
520 if (hibounds.isEmpty())
521 hb = syms.objectType;
522 else if (hibounds.tail.isEmpty())
523 hb = hibounds.head;
524 else
525 hb = types.glb(hibounds);
526 if (hb == null || hb.isErroneous())
527 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
528 }
529
530 enum BoundErrorKind {
531 BAD_UPPER() {
532 @Override
533 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
534 return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds);
535 }
536 },
537 UPPER() {
538 @Override
539 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
540 return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds);
541 }
542 },
543 LOWER() {
544 @Override
545 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
546 return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds);
547 }
548 },
549 EQ() {
550 @Override
551 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
552 return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq);
553 }
554 };
555
556 abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv);
557 }
558 //where
559 void reportBoundError(UndetVar uv, BoundErrorKind bk) {
560 throw bk.setMessage(uv.inst == null ? ambiguousNoInstanceException : invalidInstanceException, uv);
599 } 561 }
600 562
601 /** 563 /**
602 * Compute a synthetic method type corresponding to the requested polymorphic 564 * Compute a synthetic method type corresponding to the requested polymorphic
603 * method signature. The target return type is computed from the immediately 565 * method signature. The target return type is computed from the immediately

mercurial