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(); |
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 } |
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 |