langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
changeset 28142 32a6b1af81b1
parent 27857 7e913a535736
child 28148 6415a95b07fd
equal deleted inserted replaced
28141:a9bd48f9cf07 28142:32a6b1af81b1
    81     final Names names;
    81     final Names names;
    82     final Log log;
    82     final Log log;
    83     final Symtab syms;
    83     final Symtab syms;
    84     final Resolve rs;
    84     final Resolve rs;
    85     final Infer infer;
    85     final Infer infer;
       
    86     final Analyzer analyzer;
    86     final DeferredAttr deferredAttr;
    87     final DeferredAttr deferredAttr;
    87     final Check chk;
    88     final Check chk;
    88     final Flow flow;
    89     final Flow flow;
    89     final MemberEnter memberEnter;
    90     final MemberEnter memberEnter;
    90     final TypeEnter typeEnter;
    91     final TypeEnter typeEnter;
   119         memberEnter = MemberEnter.instance(context);
   120         memberEnter = MemberEnter.instance(context);
   120         typeEnter = TypeEnter.instance(context);
   121         typeEnter = TypeEnter.instance(context);
   121         make = TreeMaker.instance(context);
   122         make = TreeMaker.instance(context);
   122         enter = Enter.instance(context);
   123         enter = Enter.instance(context);
   123         infer = Infer.instance(context);
   124         infer = Infer.instance(context);
       
   125         analyzer = Analyzer.instance(context);
   124         deferredAttr = DeferredAttr.instance(context);
   126         deferredAttr = DeferredAttr.instance(context);
   125         cfolder = ConstFold.instance(context);
   127         cfolder = ConstFold.instance(context);
   126         target = Target.instance(context);
   128         target = Target.instance(context);
   127         types = Types.instance(context);
   129         types = Types.instance(context);
   128         diags = JCDiagnostic.Factory.instance(context);
   130         diags = JCDiagnostic.Factory.instance(context);
   141         allowLambda = source.allowLambda();
   143         allowLambda = source.allowLambda();
   142         allowDefaultMethods = source.allowDefaultMethods();
   144         allowDefaultMethods = source.allowDefaultMethods();
   143         allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
   145         allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
   144         sourceName = source.name;
   146         sourceName = source.name;
   145         relax = (options.isSet("-retrofit") ||
   147         relax = (options.isSet("-retrofit") ||
   146                  options.isSet("-relax"));
   148                 options.isSet("-relax"));
   147         findDiamonds = options.get("findDiamond") != null &&
       
   148                  source.allowDiamond();
       
   149         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
   149         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
   150         identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false);
       
   151 
   150 
   152         statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
   151         statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
   153         varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
   152         varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
   154         unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
   153         unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
   155         unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
   154         unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
   180 
   179 
   181     /** Switch: static interface methods enabled?
   180     /** Switch: static interface methods enabled?
   182      */
   181      */
   183     boolean allowStaticInterfaceMethods;
   182     boolean allowStaticInterfaceMethods;
   184 
   183 
   185     /** Switch: generates a warning if diamond can be safely applied
       
   186      *  to a given new expression
       
   187      */
       
   188     boolean findDiamonds;
       
   189 
       
   190     /**
       
   191      * Internally enables/disables diamond finder feature
       
   192      */
       
   193     static final boolean allowDiamondFinder = true;
       
   194 
       
   195     /**
   184     /**
   196      * Switch: warn about use of variable before declaration?
   185      * Switch: warn about use of variable before declaration?
   197      * RFE: 6425594
   186      * RFE: 6425594
   198      */
   187      */
   199     boolean useBeforeDeclarationWarning;
   188     boolean useBeforeDeclarationWarning;
   200 
       
   201     /**
       
   202      * Switch: generate warnings whenever an anonymous inner class that is convertible
       
   203      * to a lambda expression is found
       
   204      */
       
   205     boolean identifyLambdaCandidate;
       
   206 
   189 
   207     /**
   190     /**
   208      * Switch: allow strings in switch?
   191      * Switch: allow strings in switch?
   209      */
   192      */
   210     boolean allowStringsInSwitch;
   193     boolean allowStringsInSwitch;
   608     }
   591     }
   609 
   592 
   610     /** Derived visitor method: attribute a statement or definition tree.
   593     /** Derived visitor method: attribute a statement or definition tree.
   611      */
   594      */
   612     public Type attribStat(JCTree tree, Env<AttrContext> env) {
   595     public Type attribStat(JCTree tree, Env<AttrContext> env) {
   613         return attribTree(tree, env, statInfo);
   596         Env<AttrContext> analyzeEnv =
       
   597                 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
       
   598         try {
       
   599             return attribTree(tree, env, statInfo);
       
   600         } finally {
       
   601             analyzer.analyzeIfNeeded(tree, analyzeEnv);
       
   602         }
   614     }
   603     }
   615 
   604 
   616     /** Attribute a list of expressions, returning a list of types.
   605     /** Attribute a list of expressions, returning a list of types.
   617      */
   606      */
   618     List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) {
   607     List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) {
   790         return t;
   779         return t;
   791     }
   780     }
   792 
   781 
   793     Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
   782     Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
   794         Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
   783         Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
   795         id.type = env.info.scope.owner.type;
   784         id.type = env.info.scope.owner.enclClass().type;
   796         id.sym = env.info.scope.owner;
   785         id.sym = env.info.scope.owner.enclClass();
   797         return id.type;
   786         return id.type;
   798     }
   787     }
   799 
   788 
   800     public void visitClassDef(JCClassDecl tree) {
   789     public void visitClassDef(JCClassDecl tree) {
   801         // Local and anonymous classes have not been entered yet, so we need to
   790         // Local and anonymous classes have not been entered yet, so we need to
  2050                             rsEnv,
  2039                             rsEnv,
  2051                             new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes)));
  2040                             new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes)));
  2052                     if (rsEnv.info.lastResolveVarargs())
  2041                     if (rsEnv.info.lastResolveVarargs())
  2053                         Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
  2042                         Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
  2054                 }
  2043                 }
  2055                 if (cdef == null &&
       
  2056                         !clazztype.isErroneous() &&
       
  2057                         clazztype.getTypeArguments().nonEmpty() &&
       
  2058                         findDiamonds) {
       
  2059                     findDiamond(localEnv, tree, clazztype);
       
  2060                 }
       
  2061             }
  2044             }
  2062 
  2045 
  2063             if (cdef != null) {
  2046             if (cdef != null) {
  2064                 // We are seeing an anonymous class instance creation.
  2047                 // We are seeing an anonymous class instance creation.
  2065                 // In this case, the class instance creation
  2048                 // In this case, the class instance creation
  2103                     localEnv.info.isSerializable = true;
  2086                     localEnv.info.isSerializable = true;
  2104                 }
  2087                 }
  2105 
  2088 
  2106                 attribStat(cdef, localEnv);
  2089                 attribStat(cdef, localEnv);
  2107 
  2090 
  2108                 checkLambdaCandidate(tree, cdef.sym, clazztype);
       
  2109 
       
  2110                 // If an outer instance is given,
  2091                 // If an outer instance is given,
  2111                 // prefix it to the constructor arguments
  2092                 // prefix it to the constructor arguments
  2112                 // and delete it from the new expression
  2093                 // and delete it from the new expression
  2113                 if (tree.encl != null && !clazztype.tsym.isInterface()) {
  2094                 if (tree.encl != null && !clazztype.tsym.isInterface()) {
  2114                     tree.args = tree.args.prepend(makeNullCheck(tree.encl));
  2095                     tree.args = tree.args.prepend(makeNullCheck(tree.encl));
  2133                 owntype = clazztype;
  2114                 owntype = clazztype;
  2134         }
  2115         }
  2135         result = check(tree, owntype, KindSelector.VAL, resultInfo);
  2116         result = check(tree, owntype, KindSelector.VAL, resultInfo);
  2136         chk.validate(tree.typeargs, localEnv);
  2117         chk.validate(tree.typeargs, localEnv);
  2137     }
  2118     }
  2138     //where
       
  2139         void findDiamond(Env<AttrContext> env, JCNewClass tree, Type clazztype) {
       
  2140             JCTypeApply ta = (JCTypeApply)tree.clazz;
       
  2141             List<JCExpression> prevTypeargs = ta.arguments;
       
  2142             try {
       
  2143                 //create a 'fake' diamond AST node by removing type-argument trees
       
  2144                 ta.arguments = List.nil();
       
  2145                 ResultInfo findDiamondResult = new ResultInfo(KindSelector.VAL,
       
  2146                         resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt());
       
  2147                 Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type;
       
  2148                 Type polyPt = allowPoly ?
       
  2149                         syms.objectType :
       
  2150                         clazztype;
       
  2151                 if (!inferred.isErroneous() &&
       
  2152                     (allowPoly && pt() == Infer.anyPoly ?
       
  2153                         types.isSameType(inferred, clazztype) :
       
  2154                         types.isAssignable(inferred, pt().hasTag(NONE) ? polyPt : pt(), types.noWarnings))) {
       
  2155                     String key = types.isSameType(clazztype, inferred) ?
       
  2156                         "diamond.redundant.args" :
       
  2157                         "diamond.redundant.args.1";
       
  2158                     log.warning(tree.clazz.pos(), key, clazztype, inferred);
       
  2159                 }
       
  2160             } finally {
       
  2161                 ta.arguments = prevTypeargs;
       
  2162             }
       
  2163         }
       
  2164 
       
  2165             private void checkLambdaCandidate(JCNewClass tree, ClassSymbol csym, Type clazztype) {
       
  2166                 if (allowLambda &&
       
  2167                         identifyLambdaCandidate &&
       
  2168                         clazztype.hasTag(CLASS) &&
       
  2169                         !pt().hasTag(NONE) &&
       
  2170                         types.isFunctionalInterface(clazztype.tsym)) {
       
  2171                     Symbol descriptor = types.findDescriptorSymbol(clazztype.tsym);
       
  2172                     int count = 0;
       
  2173                     boolean found = false;
       
  2174                     for (Symbol sym : csym.members().getSymbols()) {
       
  2175                         if ((sym.flags() & SYNTHETIC) != 0 ||
       
  2176                                 sym.isConstructor()) continue;
       
  2177                         count++;
       
  2178                         if (sym.kind != MTH ||
       
  2179                                 !sym.name.equals(descriptor.name)) continue;
       
  2180                         Type mtype = types.memberType(clazztype, sym);
       
  2181                         if (types.overrideEquivalent(mtype, types.memberType(clazztype, descriptor))) {
       
  2182                             found = true;
       
  2183                         }
       
  2184                     }
       
  2185                     if (found && count == 1) {
       
  2186                         log.note(tree.def, "potential.lambda.found");
       
  2187                     }
       
  2188                 }
       
  2189             }
       
  2190 
  2119 
  2191     /** Make an attributed null check tree.
  2120     /** Make an attributed null check tree.
  2192      */
  2121      */
  2193     public JCExpression makeNullCheck(JCExpression arg) {
  2122     public JCExpression makeNullCheck(JCExpression arg) {
  2194         // optimization: X.this is never null; skip null check
  2123         // optimization: X.this is never null; skip null check