2271 target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); |
2271 target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); |
2272 } |
2272 } |
2273 |
2273 |
2274 Type lambdaType; |
2274 Type lambdaType; |
2275 if (pt() != Type.recoveryType) { |
2275 if (pt() != Type.recoveryType) { |
2276 target = checkIntersectionTarget(that, target, resultInfo.checkContext); |
2276 target = targetChecker.visit(target, that); |
2277 lambdaType = types.findDescriptorType(target); |
2277 lambdaType = types.findDescriptorType(target); |
2278 chk.checkFunctionalInterface(that, target); |
2278 chk.checkFunctionalInterface(that, target); |
2279 } else { |
2279 } else { |
2280 target = Type.recoveryType; |
2280 target = Type.recoveryType; |
2281 lambdaType = fallbackDescriptorType(that); |
2281 lambdaType = fallbackDescriptorType(that); |
2282 } |
2282 } |
2283 |
2283 |
2284 setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext()); |
2284 setFunctionalInfo(that, pt(), lambdaType, target, resultInfo.checkContext.inferenceContext()); |
2285 |
2285 |
2286 if (lambdaType.hasTag(FORALL)) { |
2286 if (lambdaType.hasTag(FORALL)) { |
2287 //lambda expression target desc cannot be a generic method |
2287 //lambda expression target desc cannot be a generic method |
2288 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", |
2288 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", |
2289 lambdaType, kindName(target.tsym), target.tsym)); |
2289 lambdaType, kindName(target.tsym), target.tsym)); |
2394 if (needsRecovery) { |
2394 if (needsRecovery) { |
2395 attribTree(that, env, recoveryInfo); |
2395 attribTree(that, env, recoveryInfo); |
2396 } |
2396 } |
2397 } |
2397 } |
2398 } |
2398 } |
2399 |
|
2400 private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) { |
|
2401 if (pt != Type.recoveryType && pt.isCompound()) { |
|
2402 IntersectionClassType ict = (IntersectionClassType)pt; |
|
2403 List<Type> bounds = ict.allInterfaces ? |
|
2404 ict.getComponents().tail : |
|
2405 ict.getComponents(); |
|
2406 types.findDescriptorType(bounds.head); //propagate exception outwards! |
|
2407 for (Type bound : bounds.tail) { |
|
2408 if (!types.isMarkerInterface(bound)) { |
|
2409 checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); |
|
2410 } |
|
2411 } |
|
2412 //for now (translation doesn't support intersection types) |
|
2413 return bounds.head; |
|
2414 } else { |
|
2415 return pt; |
|
2416 } |
|
2417 } |
|
2418 //where |
2399 //where |
|
2400 Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() { |
|
2401 |
|
2402 @Override |
|
2403 public Type visitClassType(ClassType t, DiagnosticPosition pos) { |
|
2404 return t.isCompound() ? |
|
2405 visitIntersectionClassType((IntersectionClassType)t, pos) : t; |
|
2406 } |
|
2407 |
|
2408 public Type visitIntersectionClassType(IntersectionClassType ict, DiagnosticPosition pos) { |
|
2409 Symbol desc = types.findDescriptorSymbol(makeNotionalInterface(ict)); |
|
2410 Type target = null; |
|
2411 for (Type bound : ict.getExplicitComponents()) { |
|
2412 TypeSymbol boundSym = bound.tsym; |
|
2413 if (types.isFunctionalInterface(boundSym) && |
|
2414 types.findDescriptorSymbol(boundSym) == desc) { |
|
2415 target = bound; |
|
2416 } else if (!boundSym.isInterface() || (boundSym.flags() & ANNOTATION) != 0) { |
|
2417 //bound must be an interface |
|
2418 reportIntersectionError(pos, "not.an.intf.component", boundSym); |
|
2419 } |
|
2420 } |
|
2421 return target != null ? |
|
2422 target : |
|
2423 ict.getExplicitComponents().head; //error recovery |
|
2424 } |
|
2425 |
|
2426 private TypeSymbol makeNotionalInterface(IntersectionClassType ict) { |
|
2427 ListBuffer<Type> targs = ListBuffer.lb(); |
|
2428 ListBuffer<Type> supertypes = ListBuffer.lb(); |
|
2429 for (Type i : ict.interfaces_field) { |
|
2430 if (i.isParameterized()) { |
|
2431 targs.appendList(i.tsym.type.allparams()); |
|
2432 } |
|
2433 supertypes.append(i.tsym.type); |
|
2434 } |
|
2435 IntersectionClassType notionalIntf = |
|
2436 (IntersectionClassType)types.makeCompoundType(supertypes.toList()); |
|
2437 notionalIntf.allparams_field = targs.toList(); |
|
2438 notionalIntf.tsym.flags_field |= INTERFACE; |
|
2439 return notionalIntf.tsym; |
|
2440 } |
|
2441 |
|
2442 private void reportIntersectionError(DiagnosticPosition pos, String key, Object... args) { |
|
2443 resultInfo.checkContext.report(pos, diags.fragment("bad.intersection.target.for.functional.expr", |
|
2444 diags.fragment(key, args))); |
|
2445 } |
|
2446 }; |
|
2447 |
2419 private Type fallbackDescriptorType(JCExpression tree) { |
2448 private Type fallbackDescriptorType(JCExpression tree) { |
2420 switch (tree.getTag()) { |
2449 switch (tree.getTag()) { |
2421 case LAMBDA: |
2450 case LAMBDA: |
2422 JCLambda lambda = (JCLambda)tree; |
2451 JCLambda lambda = (JCLambda)tree; |
2423 List<Type> argtypes = List.nil(); |
2452 List<Type> argtypes = List.nil(); |
2584 } |
2613 } |
2585 |
2614 |
2586 Type target; |
2615 Type target; |
2587 Type desc; |
2616 Type desc; |
2588 if (pt() != Type.recoveryType) { |
2617 if (pt() != Type.recoveryType) { |
2589 target = checkIntersectionTarget(that, pt(), resultInfo.checkContext); |
2618 target = targetChecker.visit(pt(), that); |
2590 desc = types.findDescriptorType(target); |
2619 desc = types.findDescriptorType(target); |
2591 chk.checkFunctionalInterface(that, target); |
2620 chk.checkFunctionalInterface(that, target); |
2592 } else { |
2621 } else { |
2593 target = Type.recoveryType; |
2622 target = Type.recoveryType; |
2594 desc = fallbackDescriptorType(that); |
2623 desc = fallbackDescriptorType(that); |
2595 } |
2624 } |
2596 |
2625 |
2597 setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext()); |
2626 setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext()); |
2598 List<Type> argtypes = desc.getParameterTypes(); |
2627 List<Type> argtypes = desc.getParameterTypes(); |
2599 |
2628 |
2600 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = |
2629 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = |
2601 rs.resolveMemberReference(that.pos(), localEnv, that, |
2630 rs.resolveMemberReference(that.pos(), localEnv, that, |
2602 that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck); |
2631 that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck); |
2787 /** |
2816 /** |
2788 * Set functional type info on the underlying AST. Note: as the target descriptor |
2817 * Set functional type info on the underlying AST. Note: as the target descriptor |
2789 * might contain inference variables, we might need to register an hook in the |
2818 * might contain inference variables, we might need to register an hook in the |
2790 * current inference context. |
2819 * current inference context. |
2791 */ |
2820 */ |
2792 private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) { |
2821 private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, |
|
2822 final Type descriptorType, final Type primaryTarget, InferenceContext inferenceContext) { |
2793 if (inferenceContext.free(descriptorType)) { |
2823 if (inferenceContext.free(descriptorType)) { |
2794 inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { |
2824 inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { |
2795 public void typesInferred(InferenceContext inferenceContext) { |
2825 public void typesInferred(InferenceContext inferenceContext) { |
2796 setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType), inferenceContext); |
2826 setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType), |
|
2827 inferenceContext.asInstType(primaryTarget), inferenceContext); |
2797 } |
2828 } |
2798 }); |
2829 }); |
2799 } else { |
2830 } else { |
2800 ListBuffer<TypeSymbol> targets = ListBuffer.lb(); |
2831 ListBuffer<TypeSymbol> targets = ListBuffer.lb(); |
2801 if (pt.hasTag(CLASS)) { |
2832 if (pt.hasTag(CLASS)) { |
2802 if (pt.isCompound()) { |
2833 if (pt.isCompound()) { |
|
2834 targets.append(primaryTarget.tsym); //this goes first |
2803 for (Type t : ((IntersectionClassType)pt()).interfaces_field) { |
2835 for (Type t : ((IntersectionClassType)pt()).interfaces_field) { |
2804 targets.append(t.tsym); |
2836 if (t != primaryTarget) { |
|
2837 targets.append(t.tsym); |
|
2838 } |
2805 } |
2839 } |
2806 } else { |
2840 } else { |
2807 targets.append(pt.tsym); |
2841 targets.append(pt.tsym); |
2808 } |
2842 } |
2809 } |
2843 } |