192 resultInfo != null && |
192 resultInfo != null && |
193 !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { |
193 !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { |
194 //inject return constraints earlier |
194 //inject return constraints earlier |
195 doIncorporation(inferenceContext, warn); //propagation |
195 doIncorporation(inferenceContext, warn); //propagation |
196 |
196 |
197 boolean shouldPropagate = resultInfo.checkContext.inferenceContext().free(resultInfo.pt); |
197 boolean shouldPropagate = shouldPropagate(mt.getReturnType(), resultInfo, inferenceContext); |
198 |
198 |
199 InferenceContext minContext = shouldPropagate ? |
199 InferenceContext minContext = shouldPropagate ? |
200 inferenceContext.min(roots(mt, deferredAttrContext), true, warn) : |
200 inferenceContext.min(roots(mt, deferredAttrContext), true, warn) : |
201 inferenceContext; |
201 inferenceContext; |
202 |
202 |
253 } |
253 } |
254 dumpGraphsIfNeeded(env.tree, msym, resolveContext); |
254 dumpGraphsIfNeeded(env.tree, msym, resolveContext); |
255 } |
255 } |
256 } |
256 } |
257 //where |
257 //where |
|
258 private boolean shouldPropagate(Type restype, Attr.ResultInfo target, InferenceContext inferenceContext) { |
|
259 return target.checkContext.inferenceContext() != emptyContext && //enclosing context is a generic method |
|
260 inferenceContext.free(restype) && //return type contains inference vars |
|
261 (!inferenceContext.inferencevars.contains(restype) || //no eager instantiation is required (as per 18.5.2) |
|
262 !needsEagerInstantiation((UndetVar)inferenceContext.asUndetVar(restype), target.pt, inferenceContext)); |
|
263 } |
|
264 |
258 private List<Type> roots(MethodType mt, DeferredAttrContext deferredAttrContext) { |
265 private List<Type> roots(MethodType mt, DeferredAttrContext deferredAttrContext) { |
259 ListBuffer<Type> roots = new ListBuffer<>(); |
266 ListBuffer<Type> roots = new ListBuffer<>(); |
260 roots.add(mt.getReturnType()); |
267 roots.add(mt.getReturnType()); |
261 if (deferredAttrContext != null && deferredAttrContext.mode == AttrMode.CHECK) { |
268 if (deferredAttrContext != null && deferredAttrContext.mode == AttrMode.CHECK) { |
262 roots.addAll(mt.getThrownTypes()); |
269 roots.addAll(mt.getThrownTypes()); |
307 * This constraints may pollute the inference context and make it useless in case we |
314 * This constraints may pollute the inference context and make it useless in case we |
308 * need to use it several times: with several targets. |
315 * need to use it several times: with several targets. |
309 */ |
316 */ |
310 saved_undet = inferenceContext.save(); |
317 saved_undet = inferenceContext.save(); |
311 if (allowGraphInference && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { |
318 if (allowGraphInference && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { |
312 boolean shouldPropagate = resultInfo.checkContext.inferenceContext().free(resultInfo.pt); |
319 boolean shouldPropagate = shouldPropagate(getReturnType(), resultInfo, inferenceContext); |
313 |
320 |
314 InferenceContext minContext = shouldPropagate ? |
321 InferenceContext minContext = shouldPropagate ? |
315 inferenceContext.min(roots(asMethodType(), null), false, warn) : |
322 inferenceContext.min(roots(asMethodType(), null), false, warn) : |
316 inferenceContext; |
323 inferenceContext; |
317 |
324 |
392 to = syms.voidType; |
399 to = syms.voidType; |
393 } else if (to.hasTag(NONE)) { |
400 } else if (to.hasTag(NONE)) { |
394 to = from.isPrimitive() ? from : syms.objectType; |
401 to = from.isPrimitive() ? from : syms.objectType; |
395 } else if (qtype.hasTag(UNDETVAR)) { |
402 } else if (qtype.hasTag(UNDETVAR)) { |
396 if (resultInfo.pt.isReference()) { |
403 if (resultInfo.pt.isReference()) { |
397 to = generateReturnConstraintsUndetVarToReference( |
404 if (needsEagerInstantiation((UndetVar)qtype, to, inferenceContext)) { |
398 tree, (UndetVar)qtype, to, resultInfo, inferenceContext); |
405 to = generateReferenceToTargetConstraint(tree, (UndetVar)qtype, to, resultInfo, inferenceContext); |
|
406 } |
399 } else { |
407 } else { |
400 if (to.isPrimitive()) { |
408 if (to.isPrimitive()) { |
401 to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to, |
409 to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to, |
402 resultInfo, inferenceContext); |
410 resultInfo, inferenceContext); |
403 } |
411 } |
437 resultInfo, inferenceContext); |
445 resultInfo, inferenceContext); |
438 } |
446 } |
439 return types.boxedClass(to).type; |
447 return types.boxedClass(to).type; |
440 } |
448 } |
441 |
449 |
442 private Type generateReturnConstraintsUndetVarToReference(JCTree tree, |
450 private boolean needsEagerInstantiation(UndetVar from, Type to, InferenceContext inferenceContext) { |
443 UndetVar from, Type to, Attr.ResultInfo resultInfo, |
|
444 InferenceContext inferenceContext) { |
|
445 Type captureOfTo = types.capture(to); |
451 Type captureOfTo = types.capture(to); |
446 /* T is a reference type, but is not a wildcard-parameterized type, and either |
452 /* T is a reference type, but is not a wildcard-parameterized type, and either |
447 */ |
453 */ |
448 if (captureOfTo == to) { //not a wildcard parameterized type |
454 if (captureOfTo == to) { //not a wildcard parameterized type |
449 /* i) B2 contains a bound of one of the forms alpha = S or S <: alpha, |
455 /* i) B2 contains a bound of one of the forms alpha = S or S <: alpha, |
450 * where S is a wildcard-parameterized type, or |
456 * where S is a wildcard-parameterized type, or |
451 */ |
457 */ |
452 for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { |
458 for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { |
453 Type captureOfBound = types.capture(t); |
459 Type captureOfBound = types.capture(t); |
454 if (captureOfBound != t) { |
460 if (captureOfBound != t) { |
455 return generateReferenceToTargetConstraint(tree, from, to, |
461 return true; |
456 resultInfo, inferenceContext); |
|
457 } |
462 } |
458 } |
463 } |
459 |
464 |
460 /* ii) B2 contains two bounds of the forms S1 <: alpha and S2 <: alpha, |
465 /* ii) B2 contains two bounds of the forms S1 <: alpha and S2 <: alpha, |
461 * where S1 and S2 have supertypes that are two different |
466 * where S1 and S2 have supertypes that are two different |
465 for (Type anotherLowerBound : from.getBounds(InferenceBound.LOWER)) { |
470 for (Type anotherLowerBound : from.getBounds(InferenceBound.LOWER)) { |
466 if (aLowerBound != anotherLowerBound && |
471 if (aLowerBound != anotherLowerBound && |
467 !inferenceContext.free(aLowerBound) && |
472 !inferenceContext.free(aLowerBound) && |
468 !inferenceContext.free(anotherLowerBound) && |
473 !inferenceContext.free(anotherLowerBound) && |
469 commonSuperWithDiffParameterization(aLowerBound, anotherLowerBound)) { |
474 commonSuperWithDiffParameterization(aLowerBound, anotherLowerBound)) { |
470 return generateReferenceToTargetConstraint(tree, from, to, |
475 return true; |
471 resultInfo, inferenceContext); |
|
472 } |
476 } |
473 } |
477 } |
474 } |
478 } |
475 } |
479 } |
476 |
480 |
481 */ |
485 */ |
482 if (to.isParameterized()) { |
486 if (to.isParameterized()) { |
483 for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { |
487 for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { |
484 Type sup = types.asSuper(t, to.tsym); |
488 Type sup = types.asSuper(t, to.tsym); |
485 if (sup != null && sup.isRaw()) { |
489 if (sup != null && sup.isRaw()) { |
486 return generateReferenceToTargetConstraint(tree, from, to, |
490 return true; |
487 resultInfo, inferenceContext); |
491 } |
488 } |
492 } |
489 } |
493 } |
490 } |
494 return false; |
491 return to; |
|
492 } |
495 } |
493 |
496 |
494 private boolean commonSuperWithDiffParameterization(Type t, Type s) { |
497 private boolean commonSuperWithDiffParameterization(Type t, Type s) { |
495 for (Pair<Type, Type> supers : getParameterizedSupers(t, s)) { |
498 for (Pair<Type, Type> supers : getParameterizedSupers(t, s)) { |
496 if (!types.isSameType(supers.fst, supers.snd)) return true; |
499 if (!types.isSameType(supers.fst, supers.snd)) return true; |
1473 public boolean accepts(UndetVar t, InferenceContext inferenceContext) { |
1476 public boolean accepts(UndetVar t, InferenceContext inferenceContext) { |
1474 if ((t.qtype.tsym.flags() & Flags.THROWS) == 0) { |
1477 if ((t.qtype.tsym.flags() & Flags.THROWS) == 0) { |
1475 //not a throws undet var |
1478 //not a throws undet var |
1476 return false; |
1479 return false; |
1477 } |
1480 } |
1478 if (t.getBounds(InferenceBound.EQ, InferenceBound.LOWER, InferenceBound.UPPER) |
|
1479 .diff(t.getDeclaredBounds()).nonEmpty()) { |
|
1480 //not an unbounded undet var |
|
1481 return false; |
|
1482 } |
|
1483 Infer infer = inferenceContext.infer; |
1481 Infer infer = inferenceContext.infer; |
1484 for (Type db : t.getDeclaredBounds()) { |
1482 for (Type db : t.getBounds(InferenceBound.UPPER)) { |
1485 if (t.isInterface()) continue; |
1483 if (t.isInterface()) continue; |
1486 if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) { |
1484 if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) == null) { |
1487 //declared bound is a supertype of RuntimeException |
1485 //upper bound is not a supertype of RuntimeException - give up |
1488 return true; |
1486 return false; |
1489 } |
1487 } |
1490 } |
1488 } |
1491 //declared bound is more specific then RuntimeException - give up |
1489 |
1492 return false; |
1490 return true; |
1493 } |
1491 } |
1494 |
1492 |
1495 @Override |
1493 @Override |
1496 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1494 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1497 return inferenceContext.infer.syms.runtimeExceptionType; |
1495 return inferenceContext.infer.syms.runtimeExceptionType; |