1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Thu Oct 04 13:04:53 2012 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Oct 05 14:35:24 2012 +0100 1.3 @@ -274,7 +274,7 @@ 1.4 Resolve.MethodResolutionContext resolveContext, 1.5 Warner warn) throws InferenceException { 1.6 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG 1.7 - final InferenceContext inferenceContext = new InferenceContext(tvars, this); 1.8 + final InferenceContext inferenceContext = new InferenceContext(tvars, this, true); 1.9 inferenceException.clear(); 1.10 1.11 try { 1.12 @@ -467,6 +467,75 @@ 1.13 throw bk.setMessage(inferenceException, uv); 1.14 } 1.15 1.16 + // <editor-fold desc="functional interface instantiation"> 1.17 + /** 1.18 + * This method is used to infer a suitable target functional interface in case 1.19 + * the original parameterized interface contains wildcards. An inference process 1.20 + * is applied so that wildcard bounds, as well as explicit lambda/method ref parameters 1.21 + * (where applicable) are used to constraint the solution. 1.22 + */ 1.23 + public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface, 1.24 + List<Type> paramTypes, Check.CheckContext checkContext) { 1.25 + if (types.capture(funcInterface) == funcInterface) { 1.26 + //if capture doesn't change the type then return the target unchanged 1.27 + //(this means the target contains no wildcards!) 1.28 + return funcInterface; 1.29 + } else { 1.30 + Type formalInterface = funcInterface.tsym.type; 1.31 + InferenceContext funcInterfaceContext = 1.32 + new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false); 1.33 + if (paramTypes != null) { 1.34 + //get constraints from explicit params (this is done by 1.35 + //checking that explicit param types are equal to the ones 1.36 + //in the functional interface descriptors) 1.37 + List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); 1.38 + if (descParameterTypes.size() != paramTypes.size()) { 1.39 + checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); 1.40 + return types.createErrorType(funcInterface); 1.41 + } 1.42 + for (Type p : descParameterTypes) { 1.43 + if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { 1.44 + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 1.45 + return types.createErrorType(funcInterface); 1.46 + } 1.47 + paramTypes = paramTypes.tail; 1.48 + } 1.49 + for (Type t : funcInterfaceContext.undetvars) { 1.50 + UndetVar uv = (UndetVar)t; 1.51 + minimizeInst(uv, Warner.noWarnings); 1.52 + if (uv.inst == null && 1.53 + Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { 1.54 + maximizeInst(uv, Warner.noWarnings); 1.55 + } 1.56 + } 1.57 + 1.58 + formalInterface = funcInterfaceContext.asInstType(formalInterface, types); 1.59 + } 1.60 + ListBuffer<Type> typeargs = ListBuffer.lb(); 1.61 + List<Type> actualTypeargs = funcInterface.getTypeArguments(); 1.62 + //for remaining uninferred type-vars in the functional interface type, 1.63 + //simply replace the wildcards with its bound 1.64 + for (Type t : formalInterface.getTypeArguments()) { 1.65 + if (actualTypeargs.head.tag == WILDCARD) { 1.66 + WildcardType wt = (WildcardType)actualTypeargs.head; 1.67 + typeargs.append(wt.type); 1.68 + } else { 1.69 + typeargs.append(actualTypeargs.head); 1.70 + } 1.71 + actualTypeargs = actualTypeargs.tail; 1.72 + } 1.73 + Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList()); 1.74 + if (!chk.checkValidGenericType(owntype)) { 1.75 + //if the inferred functional interface type is not well-formed, 1.76 + //or if it's not a subtype of the original target, issue an error 1.77 + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 1.78 + return types.createErrorType(funcInterface); 1.79 + } 1.80 + return owntype; 1.81 + } 1.82 + } 1.83 + // </editor-fold> 1.84 + 1.85 /** 1.86 * Compute a synthetic method type corresponding to the requested polymorphic 1.87 * method signature. The target return type is computed from the immediately 1.88 @@ -536,9 +605,17 @@ 1.89 * Mapping that turns inference variables into undet vars 1.90 * (used by inference context) 1.91 */ 1.92 - Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") { 1.93 + class FromTypeVarFun extends Mapping { 1.94 + 1.95 + boolean includeBounds; 1.96 + 1.97 + FromTypeVarFun(boolean includeBounds) { 1.98 + super("fromTypeVarFunWithBounds"); 1.99 + this.includeBounds = includeBounds; 1.100 + } 1.101 + 1.102 public Type apply(Type t) { 1.103 - if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types); 1.104 + if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types, includeBounds); 1.105 else return t.map(this); 1.106 } 1.107 }; 1.108 @@ -573,8 +650,8 @@ 1.109 1.110 List<FreeTypeListener> freetypeListeners = List.nil(); 1.111 1.112 - public InferenceContext(List<Type> inferencevars, Infer infer) { 1.113 - this.undetvars = Type.map(inferencevars, infer.fromTypeVarFun); 1.114 + public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) { 1.115 + this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds)); 1.116 this.inferencevars = inferencevars; 1.117 } 1.118 1.119 @@ -737,5 +814,5 @@ 1.120 } 1.121 } 1.122 1.123 - final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this); 1.124 + final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false); 1.125 }