1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Mon Jan 21 11:16:28 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Mon Jan 21 20:13:56 2013 +0000 1.3 @@ -66,6 +66,9 @@ 1.4 Log log; 1.5 JCDiagnostic.Factory diags; 1.6 1.7 + /** Should we inject return-type constraints earlier? */ 1.8 + boolean allowEarlyReturnConstraints; 1.9 + 1.10 public static Infer instance(Context context) { 1.11 Infer instance = context.get(inferKey); 1.12 if (instance == null) 1.13 @@ -83,6 +86,7 @@ 1.14 chk = Check.instance(context); 1.15 diags = JCDiagnostic.Factory.instance(context); 1.16 inferenceException = new InferenceException(diags); 1.17 + allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints(); 1.18 } 1.19 1.20 /** 1.21 @@ -188,19 +192,6 @@ 1.22 MethodType mtype, 1.23 Attr.ResultInfo resultInfo, 1.24 Warner warn) throws InferenceException { 1.25 - Type to = resultInfo.pt; 1.26 - if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { 1.27 - to = mtype.getReturnType().isPrimitiveOrVoid() ? 1.28 - mtype.getReturnType() : syms.objectType; 1.29 - } 1.30 - Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types); 1.31 - if (!types.isSubtype(qtype1, 1.32 - qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) { 1.33 - throw inferenceException 1.34 - .setMessage("infer.no.conforming.instance.exists", 1.35 - inferenceContext.restvars(), mtype.getReturnType(), to); 1.36 - } 1.37 - 1.38 while (true) { 1.39 boolean stuck = true; 1.40 for (Type t : inferenceContext.undetvars) { 1.41 @@ -283,6 +274,11 @@ 1.42 try { 1.43 methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn); 1.44 1.45 + if (resultInfo != null && allowEarlyReturnConstraints && 1.46 + !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { 1.47 + generateReturnConstraints(mt, inferenceContext, resultInfo); 1.48 + } 1.49 + 1.50 deferredAttrContext.complete(); 1.51 1.52 // minimize as yet undetermined type variables 1.53 @@ -298,6 +294,9 @@ 1.54 1.55 if (!restvars.isEmpty()) { 1.56 if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { 1.57 + if (!allowEarlyReturnConstraints) { 1.58 + generateReturnConstraints(mt, inferenceContext, resultInfo); 1.59 + } 1.60 instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn); 1.61 checkWithinBounds(inferenceContext, warn); 1.62 mt = (MethodType)inferenceContext.asInstType(mt, types); 1.63 @@ -313,6 +312,23 @@ 1.64 inferenceContext.notifyChange(types); 1.65 } 1.66 } 1.67 + //where 1.68 + void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) { 1.69 + if (resultInfo != null) { 1.70 + Type to = resultInfo.pt; 1.71 + if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { 1.72 + to = mt.getReturnType().isPrimitiveOrVoid() ? 1.73 + mt.getReturnType() : syms.objectType; 1.74 + } 1.75 + Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types); 1.76 + if (!types.isSubtype(qtype1, 1.77 + qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) { 1.78 + throw inferenceException 1.79 + .setMessage("infer.no.conforming.instance.exists", 1.80 + inferenceContext.restvars(), mt.getReturnType(), to); 1.81 + } 1.82 + } 1.83 + } 1.84 1.85 /** check that type parameters are within their bounds. 1.86 */ 1.87 @@ -461,52 +477,40 @@ 1.88 Type formalInterface = funcInterface.tsym.type; 1.89 InferenceContext funcInterfaceContext = 1.90 new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false); 1.91 - if (paramTypes != null) { 1.92 - //get constraints from explicit params (this is done by 1.93 - //checking that explicit param types are equal to the ones 1.94 - //in the functional interface descriptors) 1.95 - List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); 1.96 - if (descParameterTypes.size() != paramTypes.size()) { 1.97 - checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); 1.98 + Assert.check(paramTypes != null); 1.99 + //get constraints from explicit params (this is done by 1.100 + //checking that explicit param types are equal to the ones 1.101 + //in the functional interface descriptors) 1.102 + List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); 1.103 + if (descParameterTypes.size() != paramTypes.size()) { 1.104 + checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); 1.105 + return types.createErrorType(funcInterface); 1.106 + } 1.107 + for (Type p : descParameterTypes) { 1.108 + if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { 1.109 + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 1.110 return types.createErrorType(funcInterface); 1.111 } 1.112 - for (Type p : descParameterTypes) { 1.113 - if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { 1.114 - checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 1.115 - return types.createErrorType(funcInterface); 1.116 - } 1.117 - paramTypes = paramTypes.tail; 1.118 + paramTypes = paramTypes.tail; 1.119 + } 1.120 + List<Type> actualTypeargs = funcInterface.getTypeArguments(); 1.121 + for (Type t : funcInterfaceContext.undetvars) { 1.122 + UndetVar uv = (UndetVar)t; 1.123 + minimizeInst(uv, types.noWarnings); 1.124 + if (uv.inst == null && 1.125 + Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { 1.126 + maximizeInst(uv, types.noWarnings); 1.127 } 1.128 - for (Type t : funcInterfaceContext.undetvars) { 1.129 - UndetVar uv = (UndetVar)t; 1.130 - minimizeInst(uv, types.noWarnings); 1.131 - if (uv.inst == null && 1.132 - Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { 1.133 - maximizeInst(uv, types.noWarnings); 1.134 - } 1.135 - } 1.136 - 1.137 - formalInterface = funcInterfaceContext.asInstType(formalInterface, types); 1.138 - } 1.139 - ListBuffer<Type> typeargs = ListBuffer.lb(); 1.140 - List<Type> actualTypeargs = funcInterface.getTypeArguments(); 1.141 - //for remaining uninferred type-vars in the functional interface type, 1.142 - //simply replace the wildcards with its bound 1.143 - for (Type t : formalInterface.getTypeArguments()) { 1.144 - if (actualTypeargs.head.hasTag(WILDCARD)) { 1.145 - WildcardType wt = (WildcardType)actualTypeargs.head; 1.146 - typeargs.append(wt.type); 1.147 - } else { 1.148 - typeargs.append(actualTypeargs.head); 1.149 + if (uv.inst == null) { 1.150 + uv.inst = actualTypeargs.head; 1.151 } 1.152 actualTypeargs = actualTypeargs.tail; 1.153 } 1.154 - Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList()); 1.155 + Type owntype = funcInterfaceContext.asInstType(formalInterface, types); 1.156 if (!chk.checkValidGenericType(owntype)) { 1.157 //if the inferred functional interface type is not well-formed, 1.158 //or if it's not a subtype of the original target, issue an error 1.159 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 1.160 - return types.createErrorType(funcInterface); 1.161 } 1.162 return owntype; 1.163 }