langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
changeset 16809 5acfcb821d65
parent 16808 90b98d194b75
child 16972 b5e557f4d536
equal deleted inserted replaced
16808:90b98d194b75 16809:5acfcb821d65
  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             }