203 |
203 |
204 /** Instantiate undetermined type variable to its minimal upper bound. |
204 /** Instantiate undetermined type variable to its minimal upper bound. |
205 * Throw a NoInstanceException if this not possible. |
205 * Throw a NoInstanceException if this not possible. |
206 */ |
206 */ |
207 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException { |
207 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException { |
|
208 List<Type> hibounds = Type.filter(that.hibounds, errorFilter); |
208 if (that.inst == null) { |
209 if (that.inst == null) { |
209 if (that.hibounds.isEmpty()) |
210 if (hibounds.isEmpty()) |
210 that.inst = syms.objectType; |
211 that.inst = syms.objectType; |
211 else if (that.hibounds.tail.isEmpty()) |
212 else if (hibounds.tail.isEmpty()) |
212 that.inst = that.hibounds.head; |
213 that.inst = hibounds.head; |
213 else |
214 else |
214 that.inst = types.glb(that.hibounds); |
215 that.inst = types.glb(hibounds); |
215 } |
216 } |
216 if (that.inst == null || |
217 if (that.inst == null || |
217 that.inst.isErroneous()) |
218 that.inst.isErroneous()) |
218 throw ambiguousNoInstanceException |
219 throw ambiguousNoInstanceException |
219 .setMessage("no.unique.maximal.instance.exists", |
220 .setMessage("no.unique.maximal.instance.exists", |
220 that.qtype, that.hibounds); |
221 that.qtype, hibounds); |
221 } |
222 } |
222 //where |
223 //where |
223 private boolean isSubClass(Type t, final List<Type> ts) { |
224 private boolean isSubClass(Type t, final List<Type> ts) { |
224 t = t.baseType(); |
225 t = t.baseType(); |
225 if (t.tag == TYPEVAR) { |
226 if (t.tag == TYPEVAR) { |
239 } |
240 } |
240 } |
241 } |
241 return true; |
242 return true; |
242 } |
243 } |
243 |
244 |
|
245 private Filter<Type> errorFilter = new Filter<Type>() { |
|
246 @Override |
|
247 public boolean accepts(Type t) { |
|
248 return !t.isErroneous(); |
|
249 } |
|
250 }; |
|
251 |
244 /** Instantiate undetermined type variable to the lub of all its lower bounds. |
252 /** Instantiate undetermined type variable to the lub of all its lower bounds. |
245 * Throw a NoInstanceException if this not possible. |
253 * Throw a NoInstanceException if this not possible. |
246 */ |
254 */ |
247 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException { |
255 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException { |
|
256 List<Type> lobounds = Type.filter(that.lobounds, errorFilter); |
248 if (that.inst == null) { |
257 if (that.inst == null) { |
249 if (that.lobounds.isEmpty()) |
258 if (lobounds.isEmpty()) |
250 that.inst = syms.botType; |
259 that.inst = syms.botType; |
251 else if (that.lobounds.tail.isEmpty()) |
260 else if (lobounds.tail.isEmpty()) |
252 that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head; |
261 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head; |
253 else { |
262 else { |
254 that.inst = types.lub(that.lobounds); |
263 that.inst = types.lub(lobounds); |
255 } |
264 } |
256 if (that.inst == null || that.inst.tag == ERROR) |
265 if (that.inst == null || that.inst.tag == ERROR) |
257 throw ambiguousNoInstanceException |
266 throw ambiguousNoInstanceException |
258 .setMessage("no.unique.minimal.instance.exists", |
267 .setMessage("no.unique.minimal.instance.exists", |
259 that.qtype, that.lobounds); |
268 that.qtype, lobounds); |
260 // VGJ: sort of inlined maximizeInst() below. Adding |
269 // VGJ: sort of inlined maximizeInst() below. Adding |
261 // bounds can cause lobounds that are above hibounds. |
270 // bounds can cause lobounds that are above hibounds. |
262 if (that.hibounds.isEmpty()) |
271 List<Type> hibounds = Type.filter(that.hibounds, errorFilter); |
|
272 if (hibounds.isEmpty()) |
263 return; |
273 return; |
264 Type hb = null; |
274 Type hb = null; |
265 if (that.hibounds.tail.isEmpty()) |
275 if (hibounds.tail.isEmpty()) |
266 hb = that.hibounds.head; |
276 hb = hibounds.head; |
267 else for (List<Type> bs = that.hibounds; |
277 else for (List<Type> bs = hibounds; |
268 bs.nonEmpty() && hb == null; |
278 bs.nonEmpty() && hb == null; |
269 bs = bs.tail) { |
279 bs = bs.tail) { |
270 if (isSubClass(bs.head, that.hibounds)) |
280 if (isSubClass(bs.head, hibounds)) |
271 hb = types.fromUnknownFun.apply(bs.head); |
281 hb = types.fromUnknownFun.apply(bs.head); |
272 } |
282 } |
273 if (hb == null || |
283 if (hb == null || |
274 !types.isSubtypeUnchecked(hb, that.hibounds, warn) || |
284 !types.isSubtypeUnchecked(hb, hibounds, warn) || |
275 !types.isSubtypeUnchecked(that.inst, hb, warn)) |
285 !types.isSubtypeUnchecked(that.inst, hb, warn)) |
276 throw ambiguousNoInstanceException; |
286 throw ambiguousNoInstanceException; |
277 } |
287 } |
278 } |
288 } |
279 |
289 |
526 Warner warn) |
536 Warner warn) |
527 throws InvalidInstanceException { |
537 throws InvalidInstanceException { |
528 for (List<Type> tvs = tvars, args = arguments; |
538 for (List<Type> tvs = tvars, args = arguments; |
529 tvs.nonEmpty(); |
539 tvs.nonEmpty(); |
530 tvs = tvs.tail, args = args.tail) { |
540 tvs = tvs.tail, args = args.tail) { |
531 if (args.head instanceof UndetVar) continue; |
541 if (args.head instanceof UndetVar || |
|
542 tvars.head.getUpperBound().isErroneous()) continue; |
532 List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments); |
543 List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments); |
533 if (!types.isSubtypeUnchecked(args.head, bounds, warn)) |
544 if (!types.isSubtypeUnchecked(args.head, bounds, warn)) |
534 throw invalidInstanceException |
545 throw invalidInstanceException |
535 .setMessage("inferred.do.not.conform.to.bounds", |
546 .setMessage("inferred.do.not.conform.to.bounds", |
536 args.head, bounds); |
547 args.head, bounds); |