46 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; |
46 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; |
47 import com.sun.tools.javac.jvm.*; |
47 import com.sun.tools.javac.jvm.*; |
48 import com.sun.tools.javac.jvm.Target; |
48 import com.sun.tools.javac.jvm.Target; |
49 import com.sun.tools.javac.tree.*; |
49 import com.sun.tools.javac.tree.*; |
50 import com.sun.tools.javac.tree.JCTree.*; |
50 import com.sun.tools.javac.tree.JCTree.*; |
|
51 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; |
51 import com.sun.tools.javac.util.*; |
52 import com.sun.tools.javac.util.*; |
52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
53 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
53 import com.sun.tools.javac.util.List; |
54 import com.sun.tools.javac.util.List; |
54 import static com.sun.tools.javac.code.Flags.*; |
55 import static com.sun.tools.javac.code.Flags.*; |
55 import static com.sun.tools.javac.code.Flags.ANNOTATION; |
56 import static com.sun.tools.javac.code.Flags.ANNOTATION; |
1374 } |
1375 } |
1375 |
1376 |
1376 public void visitConditional(JCConditional tree) { |
1377 public void visitConditional(JCConditional tree) { |
1377 Type condtype = attribExpr(tree.cond, env, syms.booleanType); |
1378 Type condtype = attribExpr(tree.cond, env, syms.booleanType); |
1378 |
1379 |
1379 boolean standaloneConditional = !allowPoly || |
1380 tree.polyKind = (!allowPoly || |
1380 pt().hasTag(NONE) && pt() != Type.recoveryType || |
1381 pt().hasTag(NONE) && pt() != Type.recoveryType || |
1381 isBooleanOrNumeric(env, tree); |
1382 isBooleanOrNumeric(env, tree)) ? |
1382 |
1383 PolyKind.STANDALONE : PolyKind.POLY; |
1383 if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) { |
1384 |
|
1385 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { |
1384 //cannot get here (i.e. it means we are returning from void method - which is already an error) |
1386 //cannot get here (i.e. it means we are returning from void method - which is already an error) |
1385 resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void")); |
1387 resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void")); |
1386 result = tree.type = types.createErrorType(resultInfo.pt); |
1388 result = tree.type = types.createErrorType(resultInfo.pt); |
1387 return; |
1389 return; |
1388 } |
1390 } |
1389 |
1391 |
1390 ResultInfo condInfo = standaloneConditional ? |
1392 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? |
1391 unknownExprInfo : |
1393 unknownExprInfo : |
1392 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { |
1394 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { |
1393 //this will use enclosing check context to check compatibility of |
1395 //this will use enclosing check context to check compatibility of |
1394 //subexpression against target type; if we are in a method check context, |
1396 //subexpression against target type; if we are in a method check context, |
1395 //depending on whether boxing is allowed, we could have incompatibilities |
1397 //depending on whether boxing is allowed, we could have incompatibilities |
1400 }); |
1402 }); |
1401 |
1403 |
1402 Type truetype = attribTree(tree.truepart, env, condInfo); |
1404 Type truetype = attribTree(tree.truepart, env, condInfo); |
1403 Type falsetype = attribTree(tree.falsepart, env, condInfo); |
1405 Type falsetype = attribTree(tree.falsepart, env, condInfo); |
1404 |
1406 |
1405 Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt(); |
1407 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt(); |
1406 if (condtype.constValue() != null && |
1408 if (condtype.constValue() != null && |
1407 truetype.constValue() != null && |
1409 truetype.constValue() != null && |
1408 falsetype.constValue() != null && |
1410 falsetype.constValue() != null && |
1409 !owntype.hasTag(NONE)) { |
1411 !owntype.hasTag(NONE)) { |
1410 //constant folding |
1412 //constant folding |
1422 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); |
1424 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); |
1423 case CONDEXPR: |
1425 case CONDEXPR: |
1424 JCConditional condTree = (JCConditional)tree; |
1426 JCConditional condTree = (JCConditional)tree; |
1425 return isBooleanOrNumeric(env, condTree.truepart) && |
1427 return isBooleanOrNumeric(env, condTree.truepart) && |
1426 isBooleanOrNumeric(env, condTree.falsepart); |
1428 isBooleanOrNumeric(env, condTree.falsepart); |
|
1429 case APPLY: |
|
1430 JCMethodInvocation speculativeMethodTree = |
|
1431 (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo); |
|
1432 Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType(); |
|
1433 return types.unboxedTypeOrType(owntype).isPrimitive(); |
|
1434 case NEWCLASS: |
|
1435 JCExpression className = |
|
1436 removeClassParams.translate(((JCNewClass)tree).clazz); |
|
1437 JCExpression speculativeNewClassTree = |
|
1438 (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo); |
|
1439 return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive(); |
1427 default: |
1440 default: |
1428 Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; |
1441 Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; |
1429 speculativeType = types.unboxedTypeOrType(speculativeType); |
1442 speculativeType = types.unboxedTypeOrType(speculativeType); |
1430 return speculativeType.isPrimitive(); |
1443 return speculativeType.isPrimitive(); |
1431 } |
1444 } |
1432 } |
1445 } |
|
1446 //where |
|
1447 TreeTranslator removeClassParams = new TreeTranslator() { |
|
1448 @Override |
|
1449 public void visitTypeApply(JCTypeApply tree) { |
|
1450 result = translate(tree.clazz); |
|
1451 } |
|
1452 }; |
1433 |
1453 |
1434 /** Compute the type of a conditional expression, after |
1454 /** Compute the type of a conditional expression, after |
1435 * checking that it exists. See JLS 15.25. Does not take into |
1455 * checking that it exists. See JLS 15.25. Does not take into |
1436 * account the special case where condition and both arms |
1456 * account the special case where condition and both arms |
1437 * are constants. |
1457 * are constants. |
2171 //create an environment for attribution of the lambda expression |
2191 //create an environment for attribution of the lambda expression |
2172 final Env<AttrContext> localEnv = lambdaEnv(that, env); |
2192 final Env<AttrContext> localEnv = lambdaEnv(that, env); |
2173 boolean needsRecovery = |
2193 boolean needsRecovery = |
2174 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; |
2194 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; |
2175 try { |
2195 try { |
|
2196 Type target = pt(); |
2176 List<Type> explicitParamTypes = null; |
2197 List<Type> explicitParamTypes = null; |
2177 if (TreeInfo.isExplicitLambda(that)) { |
2198 if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { |
2178 //attribute lambda parameters |
2199 //attribute lambda parameters |
2179 attribStats(that.params, localEnv); |
2200 attribStats(that.params, localEnv); |
2180 explicitParamTypes = TreeInfo.types(that.params); |
2201 explicitParamTypes = TreeInfo.types(that.params); |
2181 } |
2202 target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); |
2182 |
2203 } |
2183 Type target; |
2204 |
2184 Type lambdaType; |
2205 Type lambdaType; |
2185 if (pt() != Type.recoveryType) { |
2206 if (pt() != Type.recoveryType) { |
2186 target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext); |
2207 target = checkIntersectionTarget(that, target, resultInfo.checkContext); |
2187 lambdaType = types.findDescriptorType(target); |
2208 lambdaType = types.findDescriptorType(target); |
2188 chk.checkFunctionalInterface(that, target); |
2209 chk.checkFunctionalInterface(that, target); |
2189 } else { |
2210 } else { |
2190 target = Type.recoveryType; |
2211 target = Type.recoveryType; |
2191 lambdaType = fallbackDescriptorType(that); |
2212 lambdaType = fallbackDescriptorType(that); |
2192 } |
2213 } |
|
2214 |
|
2215 setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext()); |
2193 |
2216 |
2194 if (lambdaType.hasTag(FORALL)) { |
2217 if (lambdaType.hasTag(FORALL)) { |
2195 //lambda expression target desc cannot be a generic method |
2218 //lambda expression target desc cannot be a generic method |
2196 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", |
2219 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", |
2197 lambdaType, kindName(target.tsym), target.tsym)); |
2220 lambdaType, kindName(target.tsym), target.tsym)); |
2198 result = that.type = types.createErrorType(pt()); |
2221 result = that.type = types.createErrorType(pt()); |
2199 return; |
2222 return; |
2200 } |
2223 } |
2201 |
2224 |
2202 if (!TreeInfo.isExplicitLambda(that)) { |
2225 if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) { |
2203 //add param type info in the AST |
2226 //add param type info in the AST |
2204 List<Type> actuals = lambdaType.getParameterTypes(); |
2227 List<Type> actuals = lambdaType.getParameterTypes(); |
2205 List<JCVariableDecl> params = that.params; |
2228 List<JCVariableDecl> params = that.params; |
2206 |
2229 |
2207 boolean arityMismatch = false; |
2230 boolean arityMismatch = false; |
2280 attribTree(that, env, recoveryInfo); |
2303 attribTree(that, env, recoveryInfo); |
2281 } |
2304 } |
2282 } |
2305 } |
2283 } |
2306 } |
2284 |
2307 |
2285 private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) { |
2308 private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) { |
2286 Type pt = resultInfo.pt; |
|
2287 if (pt != Type.recoveryType && pt.isCompound()) { |
2309 if (pt != Type.recoveryType && pt.isCompound()) { |
2288 IntersectionClassType ict = (IntersectionClassType)pt; |
2310 IntersectionClassType ict = (IntersectionClassType)pt; |
2289 List<Type> bounds = ict.allInterfaces ? |
2311 List<Type> bounds = ict.allInterfaces ? |
2290 ict.getComponents().tail : |
2312 ict.getComponents().tail : |
2291 ict.getComponents(); |
2313 ict.getComponents(); |
2292 types.findDescriptorType(bounds.head); //propagate exception outwards! |
2314 types.findDescriptorType(bounds.head); //propagate exception outwards! |
2293 for (Type bound : bounds.tail) { |
2315 for (Type bound : bounds.tail) { |
2294 if (!types.isMarkerInterface(bound)) { |
2316 if (!types.isMarkerInterface(bound)) { |
2295 resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); |
2317 checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); |
2296 } |
2318 } |
2297 } |
2319 } |
2298 //for now (translation doesn't support intersection types) |
2320 //for now (translation doesn't support intersection types) |
2299 return bounds.head; |
2321 return bounds.head; |
2300 } else { |
2322 } else { |
2353 } |
2375 } |
2354 |
2376 |
2355 @Override |
2377 @Override |
2356 public boolean compatible(Type found, Type req, Warner warn) { |
2378 public boolean compatible(Type found, Type req, Warner warn) { |
2357 //return type must be compatible in both current context and assignment context |
2379 //return type must be compatible in both current context and assignment context |
2358 return types.isAssignable(found, inferenceContext().asFree(req, types), warn) && |
2380 return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn); |
2359 super.compatible(found, req, warn); |
2381 } |
2360 } |
2382 |
2361 @Override |
2383 @Override |
2362 public void report(DiagnosticPosition pos, JCDiagnostic details) { |
2384 public void report(DiagnosticPosition pos, JCDiagnostic details) { |
2363 enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details)); |
2385 enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details)); |
2364 } |
2386 } |
2365 } |
2387 } |
2471 } |
2493 } |
2472 |
2494 |
2473 Type target; |
2495 Type target; |
2474 Type desc; |
2496 Type desc; |
2475 if (pt() != Type.recoveryType) { |
2497 if (pt() != Type.recoveryType) { |
2476 target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext); |
2498 target = checkIntersectionTarget(that, pt(), resultInfo.checkContext); |
2477 desc = types.findDescriptorType(target); |
2499 desc = types.findDescriptorType(target); |
2478 chk.checkFunctionalInterface(that, target); |
2500 chk.checkFunctionalInterface(that, target); |
2479 } else { |
2501 } else { |
2480 target = Type.recoveryType; |
2502 target = Type.recoveryType; |
2481 desc = fallbackDescriptorType(that); |
2503 desc = fallbackDescriptorType(that); |
2482 } |
2504 } |
2483 |
2505 |
|
2506 setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext()); |
2484 List<Type> argtypes = desc.getParameterTypes(); |
2507 List<Type> argtypes = desc.getParameterTypes(); |
2485 |
2508 |
2486 boolean allowBoxing = |
|
2487 resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired(); |
|
2488 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that, |
2509 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that, |
2489 that.expr.type, that.name, argtypes, typeargtypes, allowBoxing); |
2510 that.expr.type, that.name, argtypes, typeargtypes, true); |
2490 |
2511 |
2491 Symbol refSym = refResult.fst; |
2512 Symbol refSym = refResult.fst; |
2492 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; |
2513 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; |
2493 |
2514 |
2494 if (refSym.kind != MTH) { |
2515 if (refSym.kind != MTH) { |
2630 if (!speculativeAttr) { |
2651 if (!speculativeAttr) { |
2631 List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types); |
2652 List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types); |
2632 if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) { |
2653 if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) { |
2633 log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes()); |
2654 log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes()); |
2634 } |
2655 } |
|
2656 } |
|
2657 } |
|
2658 |
|
2659 /** |
|
2660 * Set functional type info on the underlying AST. Note: as the target descriptor |
|
2661 * might contain inference variables, we might need to register an hook in the |
|
2662 * current inference context. |
|
2663 */ |
|
2664 private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) { |
|
2665 if (inferenceContext.free(descriptorType)) { |
|
2666 inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { |
|
2667 public void typesInferred(InferenceContext inferenceContext) { |
|
2668 setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext); |
|
2669 } |
|
2670 }); |
|
2671 } else { |
|
2672 ListBuffer<TypeSymbol> targets = ListBuffer.lb(); |
|
2673 if (pt.hasTag(CLASS)) { |
|
2674 if (pt.isCompound()) { |
|
2675 for (Type t : ((IntersectionClassType)pt()).interfaces_field) { |
|
2676 targets.append(t.tsym); |
|
2677 } |
|
2678 } else { |
|
2679 targets.append(pt.tsym); |
|
2680 } |
|
2681 } |
|
2682 fExpr.targets = targets.toList(); |
|
2683 fExpr.descriptorType = descriptorType; |
2635 } |
2684 } |
2636 } |
2685 } |
2637 |
2686 |
2638 public void visitParens(JCParens tree) { |
2687 public void visitParens(JCParens tree) { |
2639 Type owntype = attribTree(tree.expr, env, resultInfo); |
2688 Type owntype = attribTree(tree.expr, env, resultInfo); |
4076 that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol); |
4125 that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol); |
4077 super.visitUnary(that); |
4126 super.visitUnary(that); |
4078 } |
4127 } |
4079 |
4128 |
4080 @Override |
4129 @Override |
|
4130 public void visitLambda(JCLambda that) { |
|
4131 super.visitLambda(that); |
|
4132 if (that.descriptorType == null) { |
|
4133 that.descriptorType = syms.unknownType; |
|
4134 } |
|
4135 if (that.targets == null) { |
|
4136 that.targets = List.nil(); |
|
4137 } |
|
4138 } |
|
4139 |
|
4140 @Override |
4081 public void visitReference(JCMemberReference that) { |
4141 public void visitReference(JCMemberReference that) { |
4082 super.visitReference(that); |
4142 super.visitReference(that); |
4083 if (that.sym == null) { |
4143 if (that.sym == null) { |
4084 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); |
4144 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); |
4085 } |
4145 } |
|
4146 if (that.descriptorType == null) { |
|
4147 that.descriptorType = syms.unknownType; |
|
4148 } |
|
4149 if (that.targets == null) { |
|
4150 that.targets = List.nil(); |
|
4151 } |
4086 } |
4152 } |
4087 } |
4153 } |
4088 // </editor-fold> |
4154 // </editor-fold> |
4089 } |
4155 } |