44 import com.sun.tools.javac.comp.Check.CheckContext; |
44 import com.sun.tools.javac.comp.Check.CheckContext; |
45 import com.sun.tools.javac.comp.DeferredAttr.AttrMode; |
45 import com.sun.tools.javac.comp.DeferredAttr.AttrMode; |
46 import com.sun.tools.javac.comp.Infer.InferenceContext; |
46 import com.sun.tools.javac.comp.Infer.InferenceContext; |
47 import com.sun.tools.javac.comp.Infer.FreeTypeListener; |
47 import com.sun.tools.javac.comp.Infer.FreeTypeListener; |
48 import com.sun.tools.javac.jvm.*; |
48 import com.sun.tools.javac.jvm.*; |
|
49 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond; |
|
50 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg; |
|
51 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs; |
|
52 import com.sun.tools.javac.resources.CompilerProperties.Errors; |
49 import com.sun.tools.javac.resources.CompilerProperties.Fragments; |
53 import com.sun.tools.javac.resources.CompilerProperties.Fragments; |
50 import com.sun.tools.javac.tree.*; |
54 import com.sun.tools.javac.tree.*; |
51 import com.sun.tools.javac.tree.JCTree.*; |
55 import com.sun.tools.javac.tree.JCTree.*; |
52 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; |
56 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; |
53 import com.sun.tools.javac.util.*; |
57 import com.sun.tools.javac.util.*; |
54 import com.sun.tools.javac.util.DefinedBy.Api; |
58 import com.sun.tools.javac.util.DefinedBy.Api; |
55 import com.sun.tools.javac.util.Dependencies.AttributionKind; |
59 import com.sun.tools.javac.util.Dependencies.AttributionKind; |
56 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
60 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
|
61 import com.sun.tools.javac.util.JCDiagnostic.Fragment; |
57 import com.sun.tools.javac.util.List; |
62 import com.sun.tools.javac.util.List; |
58 import static com.sun.tools.javac.code.Flags.*; |
63 import static com.sun.tools.javac.code.Flags.*; |
59 import static com.sun.tools.javac.code.Flags.ANNOTATION; |
64 import static com.sun.tools.javac.code.Flags.ANNOTATION; |
60 import static com.sun.tools.javac.code.Flags.BLOCK; |
65 import static com.sun.tools.javac.code.Flags.BLOCK; |
61 import static com.sun.tools.javac.code.Kinds.*; |
66 import static com.sun.tools.javac.code.Kinds.*; |
217 */ |
222 */ |
218 Type check(final JCTree tree, |
223 Type check(final JCTree tree, |
219 final Type found, |
224 final Type found, |
220 final KindSelector ownkind, |
225 final KindSelector ownkind, |
221 final ResultInfo resultInfo) { |
226 final ResultInfo resultInfo) { |
|
227 return check(tree, found, ownkind, resultInfo, true); |
|
228 } |
|
229 /** Check kind and type of given tree against protokind and prototype. |
|
230 * If check succeeds, store type in tree and return it. |
|
231 * If check fails, store errType in tree and return it. |
|
232 * No checks are performed if the prototype is a method type. |
|
233 * It is not necessary in this case since we know that kind and type |
|
234 * are correct. |
|
235 * |
|
236 * @param tree The tree whose kind and type is checked |
|
237 * @param found The computed type of the tree |
|
238 * @param ownkind The computed kind of the tree |
|
239 * @param resultInfo The expected result of the tree |
|
240 * @param recheckPostInference If true and inference is underway, arrange to recheck the tree after inference finishes. |
|
241 */ |
|
242 Type check(final JCTree tree, |
|
243 final Type found, |
|
244 final KindSelector ownkind, |
|
245 final ResultInfo resultInfo, |
|
246 boolean recheckPostInference) { |
222 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); |
247 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); |
223 Type owntype; |
248 Type owntype; |
224 boolean shouldCheck = !found.hasTag(ERROR) && |
249 boolean shouldCheck = !found.hasTag(ERROR) && |
225 !resultInfo.pt.hasTag(METHOD) && |
250 !resultInfo.pt.hasTag(METHOD) && |
226 !resultInfo.pt.hasTag(FORALL); |
251 !resultInfo.pt.hasTag(FORALL); |
231 owntype = types.createErrorType(found); |
256 owntype = types.createErrorType(found); |
232 } else if (allowPoly && inferenceContext.free(found)) { |
257 } else if (allowPoly && inferenceContext.free(found)) { |
233 //delay the check if there are inference variables in the found type |
258 //delay the check if there are inference variables in the found type |
234 //this means we are dealing with a partially inferred poly expression |
259 //this means we are dealing with a partially inferred poly expression |
235 owntype = shouldCheck ? resultInfo.pt : found; |
260 owntype = shouldCheck ? resultInfo.pt : found; |
236 inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), |
261 if (recheckPostInference) { |
237 instantiatedContext -> { |
262 inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), |
238 ResultInfo pendingResult = |
263 instantiatedContext -> { |
239 resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); |
264 ResultInfo pendingResult = |
240 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); |
265 resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); |
241 }); |
266 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult, false); |
|
267 }); |
|
268 } |
242 } else { |
269 } else { |
243 owntype = shouldCheck ? |
270 owntype = shouldCheck ? |
244 resultInfo.check(tree, found) : |
271 resultInfo.check(tree, found) : |
245 found; |
272 found; |
246 } |
273 } |
1967 if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 && |
1994 if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 && |
1968 (!env.tree.hasTag(VARDEF) || |
1995 (!env.tree.hasTag(VARDEF) || |
1969 (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 || |
1996 (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 || |
1970 ((JCVariableDecl) env.tree).init != tree)) |
1997 ((JCVariableDecl) env.tree).init != tree)) |
1971 log.error(tree.pos(), "enum.cant.be.instantiated"); |
1998 log.error(tree.pos(), "enum.cant.be.instantiated"); |
|
1999 |
|
2000 boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) && |
|
2001 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; |
|
2002 boolean skipNonDiamondPath = false; |
1972 // Check that class is not abstract |
2003 // Check that class is not abstract |
1973 if (cdef == null && |
2004 if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy |
1974 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { |
2005 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { |
1975 log.error(tree.pos(), "abstract.cant.be.instantiated", |
2006 log.error(tree.pos(), "abstract.cant.be.instantiated", |
1976 clazztype.tsym); |
2007 clazztype.tsym); |
|
2008 skipNonDiamondPath = true; |
1977 } else if (cdef != null && clazztype.tsym.isInterface()) { |
2009 } else if (cdef != null && clazztype.tsym.isInterface()) { |
1978 // Check that no constructor arguments are given to |
2010 // Check that no constructor arguments are given to |
1979 // anonymous classes implementing an interface |
2011 // anonymous classes implementing an interface |
1980 if (!argtypes.isEmpty()) |
2012 if (!argtypes.isEmpty()) |
1981 log.error(tree.args.head.pos(), "anon.class.impl.intf.no.args"); |
2013 log.error(tree.args.head.pos(), "anon.class.impl.intf.no.args"); |
2020 diamondEnv, |
2054 diamondEnv, |
2021 diamondResult); |
2055 diamondResult); |
2022 |
2056 |
2023 tree.clazz.type = types.createErrorType(clazztype); |
2057 tree.clazz.type = types.createErrorType(clazztype); |
2024 if (!constructorType.isErroneous()) { |
2058 if (!constructorType.isErroneous()) { |
2025 tree.clazz.type = clazztype = constructorType.getReturnType(); |
2059 tree.clazz.type = clazz.type = constructorType.getReturnType(); |
2026 tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); |
2060 tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); |
2027 } |
2061 } |
2028 clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); |
2062 clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); |
2029 } |
2063 } |
2030 |
2064 |
2031 // Resolve the called constructor under the assumption |
2065 // Resolve the called constructor under the assumption |
2032 // that we are referring to a superclass instance of the |
2066 // that we are referring to a superclass instance of the |
2033 // current instance (JLS ???). |
2067 // current instance (JLS ???). |
2034 else { |
2068 else if (!skipNonDiamondPath) { |
2035 //the following code alters some of the fields in the current |
2069 //the following code alters some of the fields in the current |
2036 //AttrContext - hence, the current context must be dup'ed in |
2070 //AttrContext - hence, the current context must be dup'ed in |
2037 //order to avoid downstream failures |
2071 //order to avoid downstream failures |
2038 Env<AttrContext> rsEnv = localEnv.dup(tree); |
2072 Env<AttrContext> rsEnv = localEnv.dup(tree); |
2039 rsEnv.info.selectSuper = cdef != null; |
2073 rsEnv.info.selectSuper = cdef != null; |
2050 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); |
2084 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); |
2051 } |
2085 } |
2052 } |
2086 } |
2053 |
2087 |
2054 if (cdef != null) { |
2088 if (cdef != null) { |
2055 // We are seeing an anonymous class instance creation. |
2089 visitAnonymousClassDefinition(tree, clazz, clazztype, cdef, localEnv, argtypes, typeargtypes, pkind); |
2056 // In this case, the class instance creation |
2090 return; |
2057 // expression |
|
2058 // |
|
2059 // E.new <typeargs1>C<typargs2>(args) { ... } |
|
2060 // |
|
2061 // is represented internally as |
|
2062 // |
|
2063 // E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) . |
|
2064 // |
|
2065 // This expression is then *transformed* as follows: |
|
2066 // |
|
2067 // (1) add an extends or implements clause |
|
2068 // (2) add a constructor. |
|
2069 // |
|
2070 // For instance, if C is a class, and ET is the type of E, |
|
2071 // the expression |
|
2072 // |
|
2073 // E.new <typeargs1>C<typargs2>(args) { ... } |
|
2074 // |
|
2075 // is translated to (where X is a fresh name and typarams is the |
|
2076 // parameter list of the super constructor): |
|
2077 // |
|
2078 // new <typeargs1>X(<*nullchk*>E, args) where |
|
2079 // X extends C<typargs2> { |
|
2080 // <typarams> X(ET e, args) { |
|
2081 // e.<typeargs1>super(args) |
|
2082 // } |
|
2083 // ... |
|
2084 // } |
|
2085 |
|
2086 if (clazztype.tsym.isInterface()) { |
|
2087 cdef.implementing = List.of(clazz); |
|
2088 } else { |
|
2089 cdef.extending = clazz; |
|
2090 } |
|
2091 |
|
2092 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && |
|
2093 isSerializable(clazztype)) { |
|
2094 localEnv.info.isSerializable = true; |
|
2095 } |
|
2096 |
|
2097 attribStat(cdef, localEnv); |
|
2098 |
|
2099 // If an outer instance is given, |
|
2100 // prefix it to the constructor arguments |
|
2101 // and delete it from the new expression |
|
2102 if (tree.encl != null && !clazztype.tsym.isInterface()) { |
|
2103 tree.args = tree.args.prepend(makeNullCheck(tree.encl)); |
|
2104 argtypes = argtypes.prepend(tree.encl.type); |
|
2105 tree.encl = null; |
|
2106 } |
|
2107 |
|
2108 // Reassign clazztype and recompute constructor. |
|
2109 clazztype = cdef.sym.type; |
|
2110 Symbol sym = tree.constructor = rs.resolveConstructor( |
|
2111 tree.pos(), localEnv, clazztype, argtypes, typeargtypes); |
|
2112 Assert.check(!sym.kind.isResolutionError()); |
|
2113 tree.constructor = sym; |
|
2114 tree.constructorType = checkId(noCheckTree, |
|
2115 clazztype, |
|
2116 tree.constructor, |
|
2117 localEnv, |
|
2118 new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); |
|
2119 } |
2091 } |
2120 |
2092 |
2121 if (tree.constructor != null && tree.constructor.kind == MTH) |
2093 if (tree.constructor != null && tree.constructor.kind == MTH) |
2122 owntype = clazztype; |
2094 owntype = clazztype; |
2123 } |
2095 } |
2130 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); |
2102 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); |
2131 }); |
2103 }); |
2132 } |
2104 } |
2133 chk.validate(tree.typeargs, localEnv); |
2105 chk.validate(tree.typeargs, localEnv); |
2134 } |
2106 } |
|
2107 |
|
2108 // where |
|
2109 private void visitAnonymousClassDefinition(JCNewClass tree, JCExpression clazz, Type clazztype, |
|
2110 JCClassDecl cdef, Env<AttrContext> localEnv, |
|
2111 List<Type> argtypes, List<Type> typeargtypes, |
|
2112 KindSelector pkind) { |
|
2113 // We are seeing an anonymous class instance creation. |
|
2114 // In this case, the class instance creation |
|
2115 // expression |
|
2116 // |
|
2117 // E.new <typeargs1>C<typargs2>(args) { ... } |
|
2118 // |
|
2119 // is represented internally as |
|
2120 // |
|
2121 // E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) . |
|
2122 // |
|
2123 // This expression is then *transformed* as follows: |
|
2124 // |
|
2125 // (1) add an extends or implements clause |
|
2126 // (2) add a constructor. |
|
2127 // |
|
2128 // For instance, if C is a class, and ET is the type of E, |
|
2129 // the expression |
|
2130 // |
|
2131 // E.new <typeargs1>C<typargs2>(args) { ... } |
|
2132 // |
|
2133 // is translated to (where X is a fresh name and typarams is the |
|
2134 // parameter list of the super constructor): |
|
2135 // |
|
2136 // new <typeargs1>X(<*nullchk*>E, args) where |
|
2137 // X extends C<typargs2> { |
|
2138 // <typarams> X(ET e, args) { |
|
2139 // e.<typeargs1>super(args) |
|
2140 // } |
|
2141 // ... |
|
2142 // } |
|
2143 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); |
|
2144 final boolean isDiamond = TreeInfo.isDiamond(tree); |
|
2145 if (isDiamond |
|
2146 && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) |
|
2147 || (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) { |
|
2148 inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type), |
|
2149 instantiatedContext -> { |
|
2150 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); |
|
2151 clazz.type = instantiatedContext.asInstType(clazz.type); |
|
2152 visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef, localEnv, argtypes, typeargtypes, pkind); |
|
2153 }); |
|
2154 } else { |
|
2155 if (isDiamond && clazztype.hasTag(CLASS)) { |
|
2156 List<Type> invalidDiamondArgs = chk.checkDiamondDenotable((ClassType)clazztype); |
|
2157 if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) { |
|
2158 // One or more types inferred in the previous steps is non-denotable. |
|
2159 Fragment fragment = Diamond(clazztype.tsym); |
|
2160 log.error(tree.clazz.pos(), |
|
2161 Errors.CantApplyDiamond1( |
|
2162 fragment, |
|
2163 invalidDiamondArgs.size() > 1 ? |
|
2164 DiamondInvalidArgs(invalidDiamondArgs, fragment) : |
|
2165 DiamondInvalidArg(invalidDiamondArgs, fragment))); |
|
2166 } |
|
2167 // For <>(){}, inferred types must also be accessible. |
|
2168 for (Type t : clazztype.getTypeArguments()) { |
|
2169 rs.checkAccessibleType(env, t); |
|
2170 } |
|
2171 } |
|
2172 |
|
2173 // If we already errored, be careful to avoid a further avalanche. ErrorType answers |
|
2174 // false for isInterface call even when the original type is an interface. |
|
2175 boolean implementing = clazztype.tsym.isInterface() || |
|
2176 clazztype.isErroneous() && clazztype.getOriginalType().tsym.isInterface(); |
|
2177 |
|
2178 if (implementing) { |
|
2179 cdef.implementing = List.of(clazz); |
|
2180 } else { |
|
2181 cdef.extending = clazz; |
|
2182 } |
|
2183 |
|
2184 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && |
|
2185 isSerializable(clazztype)) { |
|
2186 localEnv.info.isSerializable = true; |
|
2187 } |
|
2188 |
|
2189 attribStat(cdef, localEnv); |
|
2190 |
|
2191 List<Type> finalargtypes; |
|
2192 // If an outer instance is given, |
|
2193 // prefix it to the constructor arguments |
|
2194 // and delete it from the new expression |
|
2195 if (tree.encl != null && !clazztype.tsym.isInterface()) { |
|
2196 tree.args = tree.args.prepend(makeNullCheck(tree.encl)); |
|
2197 finalargtypes = argtypes.prepend(tree.encl.type); |
|
2198 tree.encl = null; |
|
2199 } else { |
|
2200 finalargtypes = argtypes; |
|
2201 } |
|
2202 |
|
2203 // Reassign clazztype and recompute constructor. As this necessarily involves |
|
2204 // another attribution pass for deferred types in the case of <>, replicate |
|
2205 // them. Original arguments have right decorations already. |
|
2206 if (isDiamond && pkind.contains(KindSelector.POLY)) { |
|
2207 finalargtypes = finalargtypes.map(deferredAttr.deferredCopier); |
|
2208 } |
|
2209 |
|
2210 clazztype = cdef.sym.type; |
|
2211 Symbol sym = tree.constructor = rs.resolveConstructor( |
|
2212 tree.pos(), localEnv, clazztype, finalargtypes, typeargtypes); |
|
2213 Assert.check(!sym.kind.isResolutionError()); |
|
2214 tree.constructor = sym; |
|
2215 tree.constructorType = checkId(noCheckTree, |
|
2216 clazztype, |
|
2217 tree.constructor, |
|
2218 localEnv, |
|
2219 new ResultInfo(pkind, newMethodTemplate(syms.voidType, finalargtypes, typeargtypes))); |
|
2220 } |
|
2221 Type owntype = (tree.constructor != null && tree.constructor.kind == MTH) ? |
|
2222 clazztype : types.createErrorType(tree.type); |
|
2223 result = check(tree, owntype, KindSelector.VAL, resultInfo, false); |
|
2224 chk.validate(tree.typeargs, localEnv); |
|
2225 } |
2135 |
2226 |
2136 /** Make an attributed null check tree. |
2227 /** Make an attributed null check tree. |
2137 */ |
2228 */ |
2138 public JCExpression makeNullCheck(JCExpression arg) { |
2229 public JCExpression makeNullCheck(JCExpression arg) { |
2139 // optimization: X.this is never null; skip null check |
2230 // optimization: X.this is never null; skip null check |