src/share/classes/com/sun/tools/javac/comp/Attr.java

changeset 1510
7873d37f5b37
parent 1492
df694c775e8a
child 1513
cf84b07a82db
equal deleted inserted replaced
1509:1985e35e97b2 1510:7873d37f5b37
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 }

mercurial