< prev index next >

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

Print this page
rev 48744 : 8197439: Crash with -XDfind=lambda for anonymous class in anonymous class.
Summary: Ensuring unresolvable anonymous classes are attributed.
Reviewed-by: TBD


2176             if (!clazztype.isErroneous()) {
2177                 if (cdef != null && clazztype.tsym.isInterface()) {
2178                     log.error(tree.encl.pos(), Errors.AnonClassImplIntfNoQualForNew);
2179                 } else if (clazztype.tsym.isStatic()) {
2180                     log.error(tree.encl.pos(), Errors.QualifiedNewOfStaticClass(clazztype.tsym));
2181                 }
2182             }
2183         } else if (!clazztype.tsym.isInterface() &&
2184                    clazztype.getEnclosingType().hasTag(CLASS)) {
2185             // Check for the existence of an apropos outer instance
2186             rs.resolveImplicitThis(tree.pos(), env, clazztype);
2187         }
2188 
2189         // Attribute constructor arguments.
2190         ListBuffer<Type> argtypesBuf = new ListBuffer<>();
2191         final KindSelector pkind =
2192             attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf);
2193         List<Type> argtypes = argtypesBuf.toList();
2194         List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
2195 
2196         // If we have made no mistakes in the class type...
2197         if (clazztype.hasTag(CLASS)) {
2198             // Enums may not be instantiated except implicitly
2199             if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 &&
2200                 (!env.tree.hasTag(VARDEF) ||
2201                  (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 ||
2202                  ((JCVariableDecl) env.tree).init != tree))
2203                 log.error(tree.pos(), Errors.EnumCantBeInstantiated);
2204 
2205             boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) &&
2206                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
2207             boolean skipNonDiamondPath = false;
2208             // Check that class is not abstract
2209             if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy
2210                 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
2211                 log.error(tree.pos(),
2212                           Errors.AbstractCantBeInstantiated(clazztype.tsym));
2213                 skipNonDiamondPath = true;
2214             } else if (cdef != null && clazztype.tsym.isInterface()) {
2215                 // Check that no constructor arguments are given to
2216                 // anonymous classes implementing an interface
2217                 if (!argtypes.isEmpty())


2364                     List<Type> invalidDiamondArgs = chk.checkDiamondDenotable((ClassType)clazztype);
2365                     if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) {
2366                         // One or more types inferred in the previous steps is non-denotable.
2367                         Fragment fragment = Diamond(clazztype.tsym);
2368                         log.error(tree.clazz.pos(),
2369                                 Errors.CantApplyDiamond1(
2370                                         fragment,
2371                                         invalidDiamondArgs.size() > 1 ?
2372                                                 DiamondInvalidArgs(invalidDiamondArgs, fragment) :
2373                                                 DiamondInvalidArg(invalidDiamondArgs, fragment)));
2374                     }
2375                     // For <>(){}, inferred types must also be accessible.
2376                     for (Type t : clazztype.getTypeArguments()) {
2377                         rs.checkAccessibleType(env, t);
2378                     }
2379                 }
2380 
2381                 // If we already errored, be careful to avoid a further avalanche. ErrorType answers
2382                 // false for isInterface call even when the original type is an interface.
2383                 boolean implementing = clazztype.tsym.isInterface() ||
2384                         clazztype.isErroneous() && clazztype.getOriginalType().tsym.isInterface();

2385 
2386                 if (implementing) {
2387                     cdef.implementing = List.of(clazz);
2388                 } else {
2389                     cdef.extending = clazz;
2390                 }
2391 
2392                 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK &&
2393                     isSerializable(clazztype)) {
2394                     localEnv.info.isSerializable = true;
2395                 }
2396 
2397                 attribStat(cdef, localEnv);
2398 
2399                 List<Type> finalargtypes;
2400                 // If an outer instance is given,
2401                 // prefix it to the constructor arguments
2402                 // and delete it from the new expression
2403                 if (tree.encl != null && !clazztype.tsym.isInterface()) {
2404                     finalargtypes = argtypes.prepend(tree.encl.type);
2405                 } else {
2406                     finalargtypes = argtypes;
2407                 }
2408 
2409                 // Reassign clazztype and recompute constructor. As this necessarily involves
2410                 // another attribution pass for deferred types in the case of <>, replicate
2411                 // them. Original arguments have right decorations already.
2412                 if (isDiamond && pkind.contains(KindSelector.POLY)) {
2413                     finalargtypes = finalargtypes.map(deferredAttr.deferredCopier);
2414                 }
2415 
2416                 clazztype = cdef.sym.type;

2417                 Symbol sym = tree.constructor = rs.resolveConstructor(
2418                         tree.pos(), localEnv, clazztype, finalargtypes, typeargtypes);
2419                 Assert.check(!sym.kind.isResolutionError());
2420                 tree.constructor = sym;
2421                 tree.constructorType = checkId(tree,
2422                         clazztype,
2423                         tree.constructor,
2424                         localEnv,
2425                         new ResultInfo(pkind, newMethodTemplate(syms.voidType, finalargtypes, typeargtypes), CheckMode.NO_TREE_UPDATE));
2426             }
2427             Type owntype = (tree.constructor != null && tree.constructor.kind == MTH) ?
2428                                 clazztype : types.createErrorType(tree.type);
2429             result = check(tree, owntype, KindSelector.VAL, resultInfo.dup(CheckMode.NO_INFERENCE_HOOK));
2430             chk.validate(tree.typeargs, localEnv);
2431         }
2432 
2433         CheckContext diamondContext(JCNewClass clazz, TypeSymbol tsym, CheckContext checkContext) {
2434             return new Check.NestedCheckContext(checkContext) {
2435                 @Override
2436                 public void report(DiagnosticPosition _unused, JCDiagnostic details) {


5063 
5064     class PostAttrAnalyzer extends TreeScanner {
5065 
5066         private void initTypeIfNeeded(JCTree that) {
5067             if (that.type == null) {
5068                 if (that.hasTag(METHODDEF)) {
5069                     that.type = dummyMethodType((JCMethodDecl)that);
5070                 } else {
5071                     that.type = syms.unknownType;
5072                 }
5073             }
5074         }
5075 
5076         /* Construct a dummy method type. If we have a method declaration,
5077          * and the declared return type is void, then use that return type
5078          * instead of UNKNOWN to avoid spurious error messages in lambda
5079          * bodies (see:JDK-8041704).
5080          */
5081         private Type dummyMethodType(JCMethodDecl md) {
5082             Type restype = syms.unknownType;
5083             if (md != null && md.restype.hasTag(TYPEIDENT)) {
5084                 JCPrimitiveTypeTree prim = (JCPrimitiveTypeTree)md.restype;
5085                 if (prim.typetag == VOID)
5086                     restype = syms.voidType;
5087             }
5088             return new MethodType(List.nil(), restype,
5089                                   List.nil(), syms.methodClass);
5090         }
5091         private Type dummyMethodType() {
5092             return dummyMethodType(null);
5093         }
5094 
5095         @Override
5096         public void scan(JCTree tree) {
5097             if (tree == null) return;
5098             if (tree instanceof JCExpression) {
5099                 initTypeIfNeeded(tree);
5100             }
5101             super.scan(tree);
5102         }
5103 




2176             if (!clazztype.isErroneous()) {
2177                 if (cdef != null && clazztype.tsym.isInterface()) {
2178                     log.error(tree.encl.pos(), Errors.AnonClassImplIntfNoQualForNew);
2179                 } else if (clazztype.tsym.isStatic()) {
2180                     log.error(tree.encl.pos(), Errors.QualifiedNewOfStaticClass(clazztype.tsym));
2181                 }
2182             }
2183         } else if (!clazztype.tsym.isInterface() &&
2184                    clazztype.getEnclosingType().hasTag(CLASS)) {
2185             // Check for the existence of an apropos outer instance
2186             rs.resolveImplicitThis(tree.pos(), env, clazztype);
2187         }
2188 
2189         // Attribute constructor arguments.
2190         ListBuffer<Type> argtypesBuf = new ListBuffer<>();
2191         final KindSelector pkind =
2192             attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf);
2193         List<Type> argtypes = argtypesBuf.toList();
2194         List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
2195 
2196         if (clazztype.hasTag(CLASS) || clazztype.hasTag(ERROR)) {

2197             // Enums may not be instantiated except implicitly
2198             if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 &&
2199                 (!env.tree.hasTag(VARDEF) ||
2200                  (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 ||
2201                  ((JCVariableDecl) env.tree).init != tree))
2202                 log.error(tree.pos(), Errors.EnumCantBeInstantiated);
2203 
2204             boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) &&
2205                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
2206             boolean skipNonDiamondPath = false;
2207             // Check that class is not abstract
2208             if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy
2209                 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
2210                 log.error(tree.pos(),
2211                           Errors.AbstractCantBeInstantiated(clazztype.tsym));
2212                 skipNonDiamondPath = true;
2213             } else if (cdef != null && clazztype.tsym.isInterface()) {
2214                 // Check that no constructor arguments are given to
2215                 // anonymous classes implementing an interface
2216                 if (!argtypes.isEmpty())


2363                     List<Type> invalidDiamondArgs = chk.checkDiamondDenotable((ClassType)clazztype);
2364                     if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) {
2365                         // One or more types inferred in the previous steps is non-denotable.
2366                         Fragment fragment = Diamond(clazztype.tsym);
2367                         log.error(tree.clazz.pos(),
2368                                 Errors.CantApplyDiamond1(
2369                                         fragment,
2370                                         invalidDiamondArgs.size() > 1 ?
2371                                                 DiamondInvalidArgs(invalidDiamondArgs, fragment) :
2372                                                 DiamondInvalidArg(invalidDiamondArgs, fragment)));
2373                     }
2374                     // For <>(){}, inferred types must also be accessible.
2375                     for (Type t : clazztype.getTypeArguments()) {
2376                         rs.checkAccessibleType(env, t);
2377                     }
2378                 }
2379 
2380                 // If we already errored, be careful to avoid a further avalanche. ErrorType answers
2381                 // false for isInterface call even when the original type is an interface.
2382                 boolean implementing = clazztype.tsym.isInterface() ||
2383                         clazztype.isErroneous() && !clazztype.getOriginalType().hasTag(NONE) &&
2384                         clazztype.getOriginalType().tsym.isInterface();
2385 
2386                 if (implementing) {
2387                     cdef.implementing = List.of(clazz);
2388                 } else {
2389                     cdef.extending = clazz;
2390                 }
2391 
2392                 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK &&
2393                     isSerializable(clazztype)) {
2394                     localEnv.info.isSerializable = true;
2395                 }
2396 
2397                 attribStat(cdef, localEnv);
2398 
2399                 List<Type> finalargtypes;
2400                 // If an outer instance is given,
2401                 // prefix it to the constructor arguments
2402                 // and delete it from the new expression
2403                 if (tree.encl != null && !clazztype.tsym.isInterface()) {
2404                     finalargtypes = argtypes.prepend(tree.encl.type);
2405                 } else {
2406                     finalargtypes = argtypes;
2407                 }
2408 
2409                 // Reassign clazztype and recompute constructor. As this necessarily involves
2410                 // another attribution pass for deferred types in the case of <>, replicate
2411                 // them. Original arguments have right decorations already.
2412                 if (isDiamond && pkind.contains(KindSelector.POLY)) {
2413                     finalargtypes = finalargtypes.map(deferredAttr.deferredCopier);
2414                 }
2415 
2416                 clazztype = clazztype.hasTag(ERROR) ? types.createErrorType(cdef.sym.type)
2417                                                     : cdef.sym.type;
2418                 Symbol sym = tree.constructor = rs.resolveConstructor(
2419                         tree.pos(), localEnv, clazztype, finalargtypes, typeargtypes);
2420                 Assert.check(!sym.kind.isResolutionError());
2421                 tree.constructor = sym;
2422                 tree.constructorType = checkId(tree,
2423                         clazztype,
2424                         tree.constructor,
2425                         localEnv,
2426                         new ResultInfo(pkind, newMethodTemplate(syms.voidType, finalargtypes, typeargtypes), CheckMode.NO_TREE_UPDATE));
2427             }
2428             Type owntype = (tree.constructor != null && tree.constructor.kind == MTH) ?
2429                                 clazztype : types.createErrorType(tree.type);
2430             result = check(tree, owntype, KindSelector.VAL, resultInfo.dup(CheckMode.NO_INFERENCE_HOOK));
2431             chk.validate(tree.typeargs, localEnv);
2432         }
2433 
2434         CheckContext diamondContext(JCNewClass clazz, TypeSymbol tsym, CheckContext checkContext) {
2435             return new Check.NestedCheckContext(checkContext) {
2436                 @Override
2437                 public void report(DiagnosticPosition _unused, JCDiagnostic details) {


5064 
5065     class PostAttrAnalyzer extends TreeScanner {
5066 
5067         private void initTypeIfNeeded(JCTree that) {
5068             if (that.type == null) {
5069                 if (that.hasTag(METHODDEF)) {
5070                     that.type = dummyMethodType((JCMethodDecl)that);
5071                 } else {
5072                     that.type = syms.unknownType;
5073                 }
5074             }
5075         }
5076 
5077         /* Construct a dummy method type. If we have a method declaration,
5078          * and the declared return type is void, then use that return type
5079          * instead of UNKNOWN to avoid spurious error messages in lambda
5080          * bodies (see:JDK-8041704).
5081          */
5082         private Type dummyMethodType(JCMethodDecl md) {
5083             Type restype = syms.unknownType;
5084             if (md != null && md.restype != null && md.restype.hasTag(TYPEIDENT)) {
5085                 JCPrimitiveTypeTree prim = (JCPrimitiveTypeTree)md.restype;
5086                 if (prim.typetag == VOID)
5087                     restype = syms.voidType;
5088             }
5089             return new MethodType(List.nil(), restype,
5090                                   List.nil(), syms.methodClass);
5091         }
5092         private Type dummyMethodType() {
5093             return dummyMethodType(null);
5094         }
5095 
5096         @Override
5097         public void scan(JCTree tree) {
5098             if (tree == null) return;
5099             if (tree instanceof JCExpression) {
5100                 initTypeIfNeeded(tree);
5101             }
5102             super.scan(tree);
5103         }
5104 


< prev index next >