langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
changeset 45756 67f4f8f4d34a
parent 45750 15404afd36ab
equal deleted inserted replaced
45755:48b1fb3acdab 45756:67f4f8f4d34a
  2513 
  2513 
  2514             if (!isSpeculativeRound) {
  2514             if (!isSpeculativeRound) {
  2515                 //add thrown types as bounds to the thrown types free variables if needed:
  2515                 //add thrown types as bounds to the thrown types free variables if needed:
  2516                 if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) {
  2516                 if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) {
  2517                     List<Type> inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make);
  2517                     List<Type> inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make);
  2518                     List<Type> thrownTypes = resultInfo.checkContext.inferenceContext().asUndetVars(lambdaType.getThrownTypes());
  2518                     if(!checkExConstraints(inferredThrownTypes, lambdaType.getThrownTypes(), resultInfo.checkContext.inferenceContext())) {
  2519 
  2519                         log.error(that, Errors.IncompatibleThrownTypesInMref(lambdaType.getThrownTypes()));
  2520                     chk.unhandled(inferredThrownTypes, thrownTypes);
  2520                     }
  2521 
       
  2522                     //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
       
  2523                     thrownTypes.stream()
       
  2524                             .filter(t -> t.hasTag(UNDETVAR))
       
  2525                             .forEach(t -> ((UndetVar)t).setThrow());
       
  2526                 }
  2521                 }
  2527 
  2522 
  2528                 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget);
  2523                 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget);
  2529             }
  2524             }
  2530             result = check(that, currentTarget, KindSelector.VAL, resultInfo);
  2525             result = check(that, currentTarget, KindSelector.VAL, resultInfo);
  3109                 tree.referentType = refType;
  3104                 tree.referentType = refType;
  3110             }
  3105             }
  3111         }
  3106         }
  3112 
  3107 
  3113         if (!speculativeAttr) {
  3108         if (!speculativeAttr) {
  3114             List<Type> thrownTypes = inferenceContext.asUndetVars(descriptor.getThrownTypes());
  3109             if (!checkExConstraints(refType.getThrownTypes(), descriptor.getThrownTypes(), inferenceContext)) {
  3115             if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
       
  3116                 log.error(tree, Errors.IncompatibleThrownTypesInMref(refType.getThrownTypes()));
  3110                 log.error(tree, Errors.IncompatibleThrownTypesInMref(refType.getThrownTypes()));
  3117             }
  3111             }
  3118             //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
  3112         }
  3119             thrownTypes.stream()
  3113     }
  3120                     .filter(t -> t.hasTag(UNDETVAR))
  3114 
  3121                     .forEach(t -> ((UndetVar)t).setThrow());
  3115     boolean checkExConstraints(
  3122         }
  3116             List<Type> thrownByFuncExpr,
       
  3117             List<Type> thrownAtFuncType,
       
  3118             InferenceContext inferenceContext) {
       
  3119         /** 18.2.5: Otherwise, let E1, ..., En be the types in the function type's throws clause that
       
  3120          *  are not proper types
       
  3121          */
       
  3122         List<Type> nonProperList = thrownAtFuncType.stream()
       
  3123                 .filter(e -> inferenceContext.free(e)).collect(List.collector());
       
  3124         List<Type> properList = thrownAtFuncType.diff(nonProperList);
       
  3125 
       
  3126         /** Let X1,...,Xm be the checked exception types that the lambda body can throw or
       
  3127          *  in the throws clause of the invocation type of the method reference's compile-time
       
  3128          *  declaration
       
  3129          */
       
  3130         List<Type> checkedList = thrownByFuncExpr.stream()
       
  3131                 .filter(e -> chk.isChecked(e)).collect(List.collector());
       
  3132 
       
  3133         /** If n = 0 (the function type's throws clause consists only of proper types), then
       
  3134          *  if there exists some i (1 <= i <= m) such that Xi is not a subtype of any proper type
       
  3135          *  in the throws clause, the constraint reduces to false; otherwise, the constraint
       
  3136          *  reduces to true
       
  3137          */
       
  3138         ListBuffer<Type> uncaughtByProperTypes = new ListBuffer<>();
       
  3139         for (Type checked : checkedList) {
       
  3140             boolean isSubtype = false;
       
  3141             for (Type proper : properList) {
       
  3142                 if (types.isSubtype(checked, proper)) {
       
  3143                     isSubtype = true;
       
  3144                     break;
       
  3145                 }
       
  3146             }
       
  3147             if (!isSubtype) {
       
  3148                 uncaughtByProperTypes.add(checked);
       
  3149             }
       
  3150         }
       
  3151 
       
  3152         if (nonProperList.isEmpty() && !uncaughtByProperTypes.isEmpty()) {
       
  3153             return false;
       
  3154         }
       
  3155 
       
  3156         /** If n > 0, the constraint reduces to a set of subtyping constraints:
       
  3157          *  for all i (1 <= i <= m), if Xi is not a subtype of any proper type in the
       
  3158          *  throws clause, then the constraints include, for all j (1 <= j <= n), <Xi <: Ej>
       
  3159          */
       
  3160         List<Type> nonProperAsUndet = inferenceContext.asUndetVars(nonProperList);
       
  3161         uncaughtByProperTypes.forEach(checkedEx -> {
       
  3162             nonProperAsUndet.forEach(nonProper -> {
       
  3163                 types.isSubtype(checkedEx, nonProper);
       
  3164             });
       
  3165         });
       
  3166 
       
  3167         /** In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej
       
  3168          */
       
  3169         nonProperAsUndet.stream()
       
  3170                 .filter(t -> t.hasTag(UNDETVAR))
       
  3171                 .forEach(t -> ((UndetVar)t).setThrow());
       
  3172         return true;
  3123     }
  3173     }
  3124 
  3174 
  3125     /**
  3175     /**
  3126      * Set functional type info on the underlying AST. Note: as the target descriptor
  3176      * Set functional type info on the underlying AST. Note: as the target descriptor
  3127      * might contain inference variables, we might need to register an hook in the
  3177      * might contain inference variables, we might need to register an hook in the