langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 38538 8bdc63ff6961
parent 38516 b643c42e9d25
child 38832 759100b68651
equal deleted inserted replaced
38537:ba5503adca64 38538:8bdc63ff6961
   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;