1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Jan 21 11:16:28 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Jan 21 20:13:56 2013 +0000 1.3 @@ -48,6 +48,7 @@ 1.4 import com.sun.tools.javac.jvm.Target; 1.5 import com.sun.tools.javac.tree.*; 1.6 import com.sun.tools.javac.tree.JCTree.*; 1.7 +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 1.8 import com.sun.tools.javac.util.*; 1.9 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.10 import com.sun.tools.javac.util.List; 1.11 @@ -1376,18 +1377,19 @@ 1.12 public void visitConditional(JCConditional tree) { 1.13 Type condtype = attribExpr(tree.cond, env, syms.booleanType); 1.14 1.15 - boolean standaloneConditional = !allowPoly || 1.16 + tree.polyKind = (!allowPoly || 1.17 pt().hasTag(NONE) && pt() != Type.recoveryType || 1.18 - isBooleanOrNumeric(env, tree); 1.19 - 1.20 - if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) { 1.21 + isBooleanOrNumeric(env, tree)) ? 1.22 + PolyKind.STANDALONE : PolyKind.POLY; 1.23 + 1.24 + if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { 1.25 //cannot get here (i.e. it means we are returning from void method - which is already an error) 1.26 resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void")); 1.27 result = tree.type = types.createErrorType(resultInfo.pt); 1.28 return; 1.29 } 1.30 1.31 - ResultInfo condInfo = standaloneConditional ? 1.32 + ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? 1.33 unknownExprInfo : 1.34 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { 1.35 //this will use enclosing check context to check compatibility of 1.36 @@ -1402,7 +1404,7 @@ 1.37 Type truetype = attribTree(tree.truepart, env, condInfo); 1.38 Type falsetype = attribTree(tree.falsepart, env, condInfo); 1.39 1.40 - Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt(); 1.41 + Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt(); 1.42 if (condtype.constValue() != null && 1.43 truetype.constValue() != null && 1.44 falsetype.constValue() != null && 1.45 @@ -1424,12 +1426,30 @@ 1.46 JCConditional condTree = (JCConditional)tree; 1.47 return isBooleanOrNumeric(env, condTree.truepart) && 1.48 isBooleanOrNumeric(env, condTree.falsepart); 1.49 + case APPLY: 1.50 + JCMethodInvocation speculativeMethodTree = 1.51 + (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo); 1.52 + Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType(); 1.53 + return types.unboxedTypeOrType(owntype).isPrimitive(); 1.54 + case NEWCLASS: 1.55 + JCExpression className = 1.56 + removeClassParams.translate(((JCNewClass)tree).clazz); 1.57 + JCExpression speculativeNewClassTree = 1.58 + (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo); 1.59 + return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive(); 1.60 default: 1.61 Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; 1.62 speculativeType = types.unboxedTypeOrType(speculativeType); 1.63 return speculativeType.isPrimitive(); 1.64 } 1.65 } 1.66 + //where 1.67 + TreeTranslator removeClassParams = new TreeTranslator() { 1.68 + @Override 1.69 + public void visitTypeApply(JCTypeApply tree) { 1.70 + result = translate(tree.clazz); 1.71 + } 1.72 + }; 1.73 1.74 /** Compute the type of a conditional expression, after 1.75 * checking that it exists. See JLS 15.25. Does not take into 1.76 @@ -2173,17 +2193,18 @@ 1.77 boolean needsRecovery = 1.78 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; 1.79 try { 1.80 + Type target = pt(); 1.81 List<Type> explicitParamTypes = null; 1.82 - if (TreeInfo.isExplicitLambda(that)) { 1.83 + if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { 1.84 //attribute lambda parameters 1.85 attribStats(that.params, localEnv); 1.86 explicitParamTypes = TreeInfo.types(that.params); 1.87 + target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); 1.88 } 1.89 1.90 - Type target; 1.91 Type lambdaType; 1.92 if (pt() != Type.recoveryType) { 1.93 - target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext); 1.94 + target = checkIntersectionTarget(that, target, resultInfo.checkContext); 1.95 lambdaType = types.findDescriptorType(target); 1.96 chk.checkFunctionalInterface(that, target); 1.97 } else { 1.98 @@ -2191,6 +2212,8 @@ 1.99 lambdaType = fallbackDescriptorType(that); 1.100 } 1.101 1.102 + setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext()); 1.103 + 1.104 if (lambdaType.hasTag(FORALL)) { 1.105 //lambda expression target desc cannot be a generic method 1.106 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", 1.107 @@ -2199,7 +2222,7 @@ 1.108 return; 1.109 } 1.110 1.111 - if (!TreeInfo.isExplicitLambda(that)) { 1.112 + if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) { 1.113 //add param type info in the AST 1.114 List<Type> actuals = lambdaType.getParameterTypes(); 1.115 List<JCVariableDecl> params = that.params; 1.116 @@ -2282,8 +2305,7 @@ 1.117 } 1.118 } 1.119 1.120 - private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) { 1.121 - Type pt = resultInfo.pt; 1.122 + private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) { 1.123 if (pt != Type.recoveryType && pt.isCompound()) { 1.124 IntersectionClassType ict = (IntersectionClassType)pt; 1.125 List<Type> bounds = ict.allInterfaces ? 1.126 @@ -2292,7 +2314,7 @@ 1.127 types.findDescriptorType(bounds.head); //propagate exception outwards! 1.128 for (Type bound : bounds.tail) { 1.129 if (!types.isMarkerInterface(bound)) { 1.130 - resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); 1.131 + checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); 1.132 } 1.133 } 1.134 //for now (translation doesn't support intersection types) 1.135 @@ -2355,9 +2377,9 @@ 1.136 @Override 1.137 public boolean compatible(Type found, Type req, Warner warn) { 1.138 //return type must be compatible in both current context and assignment context 1.139 - return types.isAssignable(found, inferenceContext().asFree(req, types), warn) && 1.140 - super.compatible(found, req, warn); 1.141 + return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn); 1.142 } 1.143 + 1.144 @Override 1.145 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.146 enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details)); 1.147 @@ -2473,7 +2495,7 @@ 1.148 Type target; 1.149 Type desc; 1.150 if (pt() != Type.recoveryType) { 1.151 - target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext); 1.152 + target = checkIntersectionTarget(that, pt(), resultInfo.checkContext); 1.153 desc = types.findDescriptorType(target); 1.154 chk.checkFunctionalInterface(that, target); 1.155 } else { 1.156 @@ -2481,12 +2503,11 @@ 1.157 desc = fallbackDescriptorType(that); 1.158 } 1.159 1.160 + setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext()); 1.161 List<Type> argtypes = desc.getParameterTypes(); 1.162 1.163 - boolean allowBoxing = 1.164 - resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired(); 1.165 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that, 1.166 - that.expr.type, that.name, argtypes, typeargtypes, allowBoxing); 1.167 + that.expr.type, that.name, argtypes, typeargtypes, true); 1.168 1.169 Symbol refSym = refResult.fst; 1.170 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; 1.171 @@ -2635,6 +2656,34 @@ 1.172 } 1.173 } 1.174 1.175 + /** 1.176 + * Set functional type info on the underlying AST. Note: as the target descriptor 1.177 + * might contain inference variables, we might need to register an hook in the 1.178 + * current inference context. 1.179 + */ 1.180 + private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) { 1.181 + if (inferenceContext.free(descriptorType)) { 1.182 + inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { 1.183 + public void typesInferred(InferenceContext inferenceContext) { 1.184 + setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext); 1.185 + } 1.186 + }); 1.187 + } else { 1.188 + ListBuffer<TypeSymbol> targets = ListBuffer.lb(); 1.189 + if (pt.hasTag(CLASS)) { 1.190 + if (pt.isCompound()) { 1.191 + for (Type t : ((IntersectionClassType)pt()).interfaces_field) { 1.192 + targets.append(t.tsym); 1.193 + } 1.194 + } else { 1.195 + targets.append(pt.tsym); 1.196 + } 1.197 + } 1.198 + fExpr.targets = targets.toList(); 1.199 + fExpr.descriptorType = descriptorType; 1.200 + } 1.201 + } 1.202 + 1.203 public void visitParens(JCParens tree) { 1.204 Type owntype = attribTree(tree.expr, env, resultInfo); 1.205 result = check(tree, owntype, pkind(), resultInfo); 1.206 @@ -4078,11 +4127,28 @@ 1.207 } 1.208 1.209 @Override 1.210 + public void visitLambda(JCLambda that) { 1.211 + super.visitLambda(that); 1.212 + if (that.descriptorType == null) { 1.213 + that.descriptorType = syms.unknownType; 1.214 + } 1.215 + if (that.targets == null) { 1.216 + that.targets = List.nil(); 1.217 + } 1.218 + } 1.219 + 1.220 + @Override 1.221 public void visitReference(JCMemberReference that) { 1.222 super.visitReference(that); 1.223 if (that.sym == null) { 1.224 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); 1.225 } 1.226 + if (that.descriptorType == null) { 1.227 + that.descriptorType = syms.unknownType; 1.228 + } 1.229 + if (that.targets == null) { 1.230 + that.targets = List.nil(); 1.231 + } 1.232 } 1.233 } 1.234 // </editor-fold>