|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package com.sun.tools.javac.comp; |
|
27 |
|
28 import com.sun.source.tree.LambdaExpressionTree.BodyKind; |
|
29 import com.sun.tools.javac.code.Flags; |
|
30 import com.sun.tools.javac.code.Symbol; |
|
31 import com.sun.tools.javac.code.Symtab; |
|
32 import com.sun.tools.javac.code.Type; |
|
33 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; |
|
34 import com.sun.tools.javac.comp.Attr.ResultInfo; |
|
35 import com.sun.tools.javac.comp.Attr.TargetInfo; |
|
36 import com.sun.tools.javac.comp.Check.CheckContext; |
|
37 import com.sun.tools.javac.comp.DeferredAttr.AttrMode; |
|
38 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; |
|
39 import com.sun.tools.javac.comp.DeferredAttr.DeferredType; |
|
40 import com.sun.tools.javac.comp.DeferredAttr.DeferredTypeCompleter; |
|
41 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner; |
|
42 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType; |
|
43 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; |
|
44 import com.sun.tools.javac.tree.JCTree; |
|
45 import com.sun.tools.javac.tree.JCTree.JCConditional; |
|
46 import com.sun.tools.javac.tree.JCTree.JCExpression; |
|
47 import com.sun.tools.javac.tree.JCTree.JCLambda; |
|
48 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; |
|
49 import com.sun.tools.javac.tree.JCTree.JCMemberReference; |
|
50 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; |
|
51 import com.sun.tools.javac.tree.JCTree.JCNewClass; |
|
52 import com.sun.tools.javac.tree.JCTree.JCParens; |
|
53 import com.sun.tools.javac.tree.JCTree.JCReturn; |
|
54 import com.sun.tools.javac.tree.TreeCopier; |
|
55 import com.sun.tools.javac.tree.TreeInfo; |
|
56 import com.sun.tools.javac.util.Assert; |
|
57 import com.sun.tools.javac.util.Context; |
|
58 import com.sun.tools.javac.util.DiagnosticSource; |
|
59 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
|
60 import com.sun.tools.javac.util.List; |
|
61 import com.sun.tools.javac.util.ListBuffer; |
|
62 import com.sun.tools.javac.util.Log; |
|
63 |
|
64 import java.util.HashMap; |
|
65 import java.util.LinkedHashMap; |
|
66 import java.util.Map; |
|
67 import java.util.Optional; |
|
68 import java.util.function.Function; |
|
69 import java.util.function.Supplier; |
|
70 |
|
71 import static com.sun.tools.javac.code.TypeTag.DEFERRED; |
|
72 import static com.sun.tools.javac.code.TypeTag.FORALL; |
|
73 import static com.sun.tools.javac.code.TypeTag.METHOD; |
|
74 import static com.sun.tools.javac.code.TypeTag.VOID; |
|
75 |
|
76 /** |
|
77 * This class performs attribution of method/constructor arguments when target-typing is enabled |
|
78 * (source >= 8); for each argument that is potentially a poly expression, this class builds |
|
79 * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload |
|
80 * checks without requiring multiple attribution passes over the same code. |
|
81 * |
|
82 * The attribution strategy for a given method/constructor argument A is as follows: |
|
83 * |
|
84 * - if A is potentially a poly expression (i.e. diamond instance creation expression), a speculative |
|
85 * pass over A is performed; the results of such speculative attribution are then saved in a special |
|
86 * type, so that enclosing overload resolution can be carried by simply checking compatibility against the |
|
87 * type determined during this speculative pass. |
|
88 * |
|
89 * - if A is a standalone expression, regular atributtion takes place. |
|
90 * |
|
91 * To minimize the speculative work, a cache is used, so that already computed argument types |
|
92 * associated with a given unique source location are never recomputed multiple times. |
|
93 */ |
|
94 public class ArgumentAttr extends JCTree.Visitor { |
|
95 |
|
96 protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>(); |
|
97 |
|
98 private final DeferredAttr deferredAttr; |
|
99 private final Attr attr; |
|
100 private final Symtab syms; |
|
101 private final Log log; |
|
102 |
|
103 /** Attribution environment to be used. */ |
|
104 private Env<AttrContext> env; |
|
105 |
|
106 /** Result of method attribution. */ |
|
107 private Type result; |
|
108 |
|
109 /** Cache for argument types; behavior is influences by the currrently selected cache policy. */ |
|
110 Map<UniquePos, ArgumentType<?>> argumentTypeCache = new LinkedHashMap<>(); |
|
111 |
|
112 /** Cache policy: should argument types be cached? */ |
|
113 private CachePolicy cachePolicy = CachePolicy.CACHE; |
|
114 |
|
115 public static ArgumentAttr instance(Context context) { |
|
116 ArgumentAttr instance = context.get(methodAttrKey); |
|
117 if (instance == null) |
|
118 instance = new ArgumentAttr(context); |
|
119 return instance; |
|
120 } |
|
121 |
|
122 protected ArgumentAttr(Context context) { |
|
123 context.put(methodAttrKey, this); |
|
124 deferredAttr = DeferredAttr.instance(context); |
|
125 attr = Attr.instance(context); |
|
126 syms = Symtab.instance(context); |
|
127 log = Log.instance(context); |
|
128 } |
|
129 |
|
130 /** |
|
131 * Set the results of method attribution. |
|
132 */ |
|
133 void setResult(JCExpression tree, Type type) { |
|
134 result = type; |
|
135 if (env.info.isSpeculative) { |
|
136 //if we are in a speculative branch we can save the type in the tree itself |
|
137 //as there's no risk of polluting the original tree. |
|
138 tree.type = result; |
|
139 } |
|
140 } |
|
141 |
|
142 /** |
|
143 * Checks a type in the speculative tree against a given result; the type can be either a plain |
|
144 * type or an argument type,in which case a more complex check is required. |
|
145 */ |
|
146 Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) { |
|
147 return checkSpeculative(expr, expr.type, resultInfo); |
|
148 } |
|
149 |
|
150 /** |
|
151 * Checks a type in the speculative tree against a given result; the type can be either a plain |
|
152 * type or an argument type,in which case a more complex check is required. |
|
153 */ |
|
154 Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) { |
|
155 if (t.hasTag(DEFERRED)) { |
|
156 return ((DeferredType)t).check(resultInfo); |
|
157 } else { |
|
158 return resultInfo.check(pos, t); |
|
159 } |
|
160 } |
|
161 |
|
162 /** |
|
163 * Sets given ache policy and returns current policy. |
|
164 */ |
|
165 CachePolicy withCachePolicy(CachePolicy newPolicy) { |
|
166 CachePolicy oldPolicy = this.cachePolicy; |
|
167 this.cachePolicy = newPolicy; |
|
168 return oldPolicy; |
|
169 } |
|
170 |
|
171 /** |
|
172 * Main entry point for attributing an argument with given tree and attribution environment. |
|
173 */ |
|
174 Type attribArg(JCTree tree, Env<AttrContext> env) { |
|
175 Env<AttrContext> prevEnv = this.env; |
|
176 try { |
|
177 this.env = env; |
|
178 tree.accept(this); |
|
179 return result; |
|
180 } finally { |
|
181 this.env = prevEnv; |
|
182 } |
|
183 } |
|
184 |
|
185 @Override |
|
186 public void visitTree(JCTree that) { |
|
187 //delegates to Attr |
|
188 that.accept(attr); |
|
189 result = attr.result; |
|
190 } |
|
191 |
|
192 /** |
|
193 * Process a method argument; this method takes care of performing a speculative pass over the |
|
194 * argument tree and calling a well-defined entry point to build the argument type associated |
|
195 * with such tree. |
|
196 */ |
|
197 @SuppressWarnings("unchecked") |
|
198 <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Function<T, Z> argumentTypeFactory) { |
|
199 UniquePos pos = new UniquePos(that); |
|
200 processArg(that, () -> { |
|
201 T speculativeTree = (T)deferredAttr.attribSpeculative(that, env, attr.new MethodAttrInfo() { |
|
202 @Override |
|
203 protected void attr(JCTree tree, Env<AttrContext> env) { |
|
204 //avoid speculative attribution loops |
|
205 if (!new UniquePos(tree).equals(pos)) { |
|
206 super.attr(tree, env); |
|
207 } else { |
|
208 visitTree(tree); |
|
209 } |
|
210 } |
|
211 }); |
|
212 return argumentTypeFactory.apply(speculativeTree); |
|
213 }); |
|
214 } |
|
215 |
|
216 /** |
|
217 * Process a method argument; this method allows the caller to specify a custom speculative attribution |
|
218 * logic (this is used e.g. for lambdas). |
|
219 */ |
|
220 @SuppressWarnings("unchecked") |
|
221 <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Supplier<Z> argumentTypeFactory) { |
|
222 UniquePos pos = new UniquePos(that); |
|
223 Z cached = (Z)argumentTypeCache.get(pos); |
|
224 if (cached != null) { |
|
225 //dup existing speculative type |
|
226 setResult(that, cached.dup(that, env)); |
|
227 } else { |
|
228 Z res = argumentTypeFactory.get(); |
|
229 if (cachePolicy == CachePolicy.CACHE) { |
|
230 argumentTypeCache.put(pos, res); |
|
231 } |
|
232 setResult(that, res); |
|
233 } |
|
234 } |
|
235 |
|
236 @Override |
|
237 public void visitParens(JCParens that) { |
|
238 processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree)); |
|
239 } |
|
240 |
|
241 @Override |
|
242 public void visitConditional(JCConditional that) { |
|
243 processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree)); |
|
244 } |
|
245 |
|
246 @Override |
|
247 public void visitReference(JCMemberReference tree) { |
|
248 //perform arity-based check |
|
249 Env<AttrContext> localEnv = env.dup(tree); |
|
250 JCExpression exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv, |
|
251 attr.memberReferenceQualifierResult(tree)); |
|
252 JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree); |
|
253 mref2.expr = exprTree; |
|
254 Symbol res = |
|
255 attr.rs.getMemberReference(tree, localEnv, mref2, |
|
256 exprTree.type, tree.name); |
|
257 if (!res.kind.isResolutionError()) { |
|
258 tree.sym = res; |
|
259 } |
|
260 if (res.kind.isResolutionTargetError() || |
|
261 res.type != null && res.type.hasTag(FORALL) || |
|
262 (res.flags() & Flags.VARARGS) != 0 || |
|
263 (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && |
|
264 exprTree.type.isRaw())) { |
|
265 tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; |
|
266 } else { |
|
267 tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; |
|
268 } |
|
269 //return a plain old deferred type for this |
|
270 setResult(tree, deferredAttr.new DeferredType(tree, env)); |
|
271 } |
|
272 |
|
273 @Override |
|
274 public void visitLambda(JCLambda that) { |
|
275 if (that.paramKind == ParameterKind.EXPLICIT) { |
|
276 //if lambda is explicit, we can save info in the corresponding argument type |
|
277 processArg(that, () -> { |
|
278 JCLambda speculativeLambda = |
|
279 deferredAttr.attribSpeculativeLambda(that, env, attr.methodAttrInfo); |
|
280 return new ExplicitLambdaType(that, env, speculativeLambda); |
|
281 }); |
|
282 } else { |
|
283 //otherwise just use a deferred type |
|
284 setResult(that, deferredAttr.new DeferredType(that, env)); |
|
285 } |
|
286 } |
|
287 |
|
288 @Override |
|
289 public void visitApply(JCMethodInvocation that) { |
|
290 if (that.getTypeArguments().isEmpty()) { |
|
291 processArg(that, speculativeTree -> new ResolvedMethodType(that, env, speculativeTree)); |
|
292 } else { |
|
293 //not a poly expression, just call Attr |
|
294 setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); |
|
295 } |
|
296 } |
|
297 |
|
298 @Override |
|
299 public void visitNewClass(JCNewClass that) { |
|
300 if (TreeInfo.isDiamond(that)) { |
|
301 processArg(that, speculativeTree -> new ResolvedConstructorType(that, env, speculativeTree)); |
|
302 } else { |
|
303 //not a poly expression, just call Attr |
|
304 setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); |
|
305 } |
|
306 } |
|
307 |
|
308 /** |
|
309 * An argument type is similar to a plain deferred type; the most important difference is that |
|
310 * the completion logic associated with argument types allows speculative attribution to be skipped |
|
311 * during overload resolution - that is, an argument type always has enough information to |
|
312 * perform an overload check without the need of calling back to Attr. This extra information |
|
313 * is typically stored in the form of a speculative tree. |
|
314 */ |
|
315 abstract class ArgumentType<T extends JCExpression> extends DeferredType implements DeferredTypeCompleter { |
|
316 |
|
317 /** The speculative tree carrying type information. */ |
|
318 T speculativeTree; |
|
319 |
|
320 /** Types associated with this argument (one type per possible target result). */ |
|
321 Map<ResultInfo, Type> speculativeTypes; |
|
322 |
|
323 public ArgumentType(JCExpression tree, Env<AttrContext> env, T speculativeTree, Map<ResultInfo, Type> speculativeTypes) { |
|
324 deferredAttr.super(tree, env); |
|
325 this.speculativeTree = speculativeTree; |
|
326 this.speculativeTypes = speculativeTypes; |
|
327 } |
|
328 |
|
329 @Override |
|
330 final DeferredTypeCompleter completer() { |
|
331 return this; |
|
332 } |
|
333 |
|
334 @Override |
|
335 final public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { |
|
336 Assert.check(dt == this); |
|
337 if (deferredAttrContext.mode == AttrMode.SPECULATIVE) { |
|
338 Type t = (resultInfo.pt == Type.recoveryType) ? |
|
339 deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) : |
|
340 overloadCheck(resultInfo, deferredAttrContext); |
|
341 speculativeTypes.put(resultInfo, t); |
|
342 return t; |
|
343 } else { |
|
344 if (!env.info.isSpeculative && cachePolicy == CachePolicy.CACHE) { |
|
345 argumentTypeCache.remove(new UniquePos(dt.tree)); |
|
346 } |
|
347 return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext); |
|
348 } |
|
349 } |
|
350 |
|
351 @Override |
|
352 Type speculativeType(Symbol msym, MethodResolutionPhase phase) { |
|
353 for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) { |
|
354 DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext(); |
|
355 if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) { |
|
356 return _entry.getValue(); |
|
357 } |
|
358 } |
|
359 return Type.noType; |
|
360 } |
|
361 |
|
362 @Override |
|
363 JCTree speculativeTree(DeferredAttrContext deferredAttrContext) { |
|
364 return speculativeTree; |
|
365 } |
|
366 |
|
367 /** |
|
368 * Performs an overload check against a given target result. |
|
369 */ |
|
370 abstract Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext); |
|
371 |
|
372 /** |
|
373 * Creates a copy of this argument type with given tree and environment. |
|
374 */ |
|
375 abstract ArgumentType<T> dup(T tree, Env<AttrContext> env); |
|
376 } |
|
377 |
|
378 /** |
|
379 * Argument type for parenthesized expression. |
|
380 */ |
|
381 class ParensType extends ArgumentType<JCParens> { |
|
382 ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens) { |
|
383 this(tree, env, speculativeParens, new HashMap<>()); |
|
384 } |
|
385 |
|
386 ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens, Map<ResultInfo, Type> speculativeTypes) { |
|
387 super(tree, env, speculativeParens, speculativeTypes); |
|
388 } |
|
389 |
|
390 @Override |
|
391 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { |
|
392 return checkSpeculative(speculativeTree.expr, resultInfo); |
|
393 } |
|
394 |
|
395 @Override |
|
396 ArgumentType<JCParens> dup(JCParens tree, Env<AttrContext> env) { |
|
397 return new ParensType(tree, env, speculativeTree, speculativeTypes); |
|
398 } |
|
399 } |
|
400 |
|
401 /** |
|
402 * Argument type for conditionals. |
|
403 */ |
|
404 class ConditionalType extends ArgumentType<JCConditional> { |
|
405 ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond) { |
|
406 this(tree, env, speculativeCond, new HashMap<>()); |
|
407 } |
|
408 |
|
409 ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond, Map<ResultInfo, Type> speculativeTypes) { |
|
410 super(tree, env, speculativeCond, speculativeTypes); |
|
411 } |
|
412 |
|
413 @Override |
|
414 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { |
|
415 ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext)); |
|
416 if (speculativeTree.isStandalone()) { |
|
417 return localInfo.check(speculativeTree, speculativeTree.type); |
|
418 } else if (resultInfo.pt.hasTag(VOID)) { |
|
419 //this means we are returning a poly conditional from void-compatible lambda expression |
|
420 resultInfo.checkContext.report(tree, attr.diags.fragment("conditional.target.cant.be.void")); |
|
421 return attr.types.createErrorType(resultInfo.pt); |
|
422 } else { |
|
423 //poly |
|
424 checkSpeculative(speculativeTree.truepart, localInfo); |
|
425 checkSpeculative(speculativeTree.falsepart, localInfo); |
|
426 return localInfo.pt; |
|
427 } |
|
428 } |
|
429 |
|
430 @Override |
|
431 ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) { |
|
432 return new ConditionalType(tree, env, speculativeTree, speculativeTypes); |
|
433 } |
|
434 } |
|
435 |
|
436 /** |
|
437 * Argument type for explicit lambdas. |
|
438 */ |
|
439 class ExplicitLambdaType extends ArgumentType<JCLambda> { |
|
440 |
|
441 /** List of argument types (lazily populated). */ |
|
442 Optional<List<Type>> argtypes = Optional.empty(); |
|
443 |
|
444 /** List of return expressions (lazily populated). */ |
|
445 Optional<List<JCReturn>> returnExpressions = Optional.empty(); |
|
446 |
|
447 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) { |
|
448 this(originalLambda, env, speculativeLambda, new HashMap<>()); |
|
449 } |
|
450 |
|
451 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) { |
|
452 super(originalLambda, env, speculativeLambda, speculativeTypes); |
|
453 } |
|
454 |
|
455 /** Compute argument types (if needed). */ |
|
456 List<Type> argtypes() { |
|
457 return argtypes.orElseGet(() -> { |
|
458 List<Type> res = TreeInfo.types(speculativeTree.params); |
|
459 argtypes = Optional.of(res); |
|
460 return res; |
|
461 }); |
|
462 } |
|
463 |
|
464 /** Compute return expressions (if needed). */ |
|
465 List<JCReturn> returnExpressions() { |
|
466 return returnExpressions.orElseGet(() -> { |
|
467 final List<JCReturn> res; |
|
468 if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) { |
|
469 res = List.of(attr.make.Return((JCExpression)speculativeTree.body)); |
|
470 } else { |
|
471 ListBuffer<JCReturn> returnExpressions = new ListBuffer<>(); |
|
472 new LambdaReturnScanner() { |
|
473 @Override |
|
474 public void visitReturn(JCReturn tree) { |
|
475 returnExpressions.add(tree); |
|
476 } |
|
477 }.scan(speculativeTree.body); |
|
478 res = returnExpressions.toList(); |
|
479 } |
|
480 returnExpressions = Optional.of(res); |
|
481 return res; |
|
482 }); |
|
483 } |
|
484 |
|
485 @Override |
|
486 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { |
|
487 try { |
|
488 //compute target-type; this logic could be shared with Attr |
|
489 TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes()); |
|
490 Type lambdaType = targetInfo.descriptor; |
|
491 Type currentTarget = targetInfo.target; |
|
492 //check compatibility |
|
493 checkLambdaCompatible(lambdaType, resultInfo); |
|
494 return currentTarget; |
|
495 } catch (FunctionDescriptorLookupError ex) { |
|
496 resultInfo.checkContext.report(null, ex.getDiagnostic()); |
|
497 return null; //cannot get here |
|
498 } |
|
499 } |
|
500 |
|
501 /** Check lambda against given target result */ |
|
502 private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) { |
|
503 CheckContext checkContext = resultInfo.checkContext; |
|
504 ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo); |
|
505 for (JCReturn ret : returnExpressions()) { |
|
506 Type t = getReturnType(ret); |
|
507 if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) { |
|
508 checkSpeculative(ret.expr, t, bodyResultInfo); |
|
509 } |
|
510 } |
|
511 |
|
512 attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext); |
|
513 } |
|
514 |
|
515 /** Get the type associated with given return expression. */ |
|
516 Type getReturnType(JCReturn ret) { |
|
517 if (ret.expr == null) { |
|
518 return syms.voidType; |
|
519 } else { |
|
520 return ret.expr.type; |
|
521 } |
|
522 } |
|
523 |
|
524 @Override |
|
525 ArgumentType<JCLambda> dup(JCLambda tree, Env<AttrContext> env) { |
|
526 return new ExplicitLambdaType(tree, env, speculativeTree, speculativeTypes); |
|
527 } |
|
528 } |
|
529 |
|
530 /** |
|
531 * Argument type for methods/constructors. |
|
532 */ |
|
533 abstract class ResolvedMemberType<E extends JCExpression> extends ArgumentType<E> { |
|
534 |
|
535 public ResolvedMemberType(JCExpression tree, Env<AttrContext> env, E speculativeMethod, Map<ResultInfo, Type> speculativeTypes) { |
|
536 super(tree, env, speculativeMethod, speculativeTypes); |
|
537 } |
|
538 |
|
539 @Override |
|
540 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { |
|
541 Type mtype = methodType(); |
|
542 ResultInfo localInfo = resultInfo(resultInfo); |
|
543 if (mtype != null && mtype.hasTag(METHOD) && mtype.isPartial()) { |
|
544 Type t = ((PartiallyInferredMethodType)mtype).check(localInfo); |
|
545 if (!deferredAttrContext.inferenceContext.free(localInfo.pt)) { |
|
546 speculativeTypes.put(localInfo, t); |
|
547 return localInfo.check(tree.pos(), t); |
|
548 } else { |
|
549 return t; |
|
550 } |
|
551 } else { |
|
552 Type t = localInfo.check(tree.pos(), speculativeTree.type); |
|
553 speculativeTypes.put(localInfo, t); |
|
554 return t; |
|
555 } |
|
556 } |
|
557 |
|
558 /** |
|
559 * Get the result info to be used for performing an overload check. |
|
560 */ |
|
561 abstract ResultInfo resultInfo(ResultInfo resultInfo); |
|
562 |
|
563 /** |
|
564 * Get the method type to be used for performing an overload check. |
|
565 */ |
|
566 abstract Type methodType(); |
|
567 } |
|
568 |
|
569 /** |
|
570 * Argument type for methods. |
|
571 */ |
|
572 class ResolvedMethodType extends ResolvedMemberType<JCMethodInvocation> { |
|
573 |
|
574 public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree) { |
|
575 this(tree, env, speculativeTree, new HashMap<>()); |
|
576 } |
|
577 |
|
578 public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree, Map<ResultInfo, Type> speculativeTypes) { |
|
579 super(tree, env, speculativeTree, speculativeTypes); |
|
580 } |
|
581 |
|
582 @Override |
|
583 ResultInfo resultInfo(ResultInfo resultInfo) { |
|
584 return resultInfo; |
|
585 } |
|
586 |
|
587 @Override |
|
588 Type methodType() { |
|
589 return speculativeTree.meth.type; |
|
590 } |
|
591 |
|
592 @Override |
|
593 ArgumentType<JCMethodInvocation> dup(JCMethodInvocation tree, Env<AttrContext> env) { |
|
594 return new ResolvedMethodType(tree, env, speculativeTree, speculativeTypes); |
|
595 } |
|
596 } |
|
597 |
|
598 /** |
|
599 * Argument type for constructors. |
|
600 */ |
|
601 class ResolvedConstructorType extends ResolvedMemberType<JCNewClass> { |
|
602 |
|
603 public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree) { |
|
604 this(tree, env, speculativeTree, new HashMap<>()); |
|
605 } |
|
606 |
|
607 public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree, Map<ResultInfo, Type> speculativeTypes) { |
|
608 super(tree, env, speculativeTree, speculativeTypes); |
|
609 } |
|
610 |
|
611 @Override |
|
612 ResultInfo resultInfo(ResultInfo resultInfo) { |
|
613 return resultInfo.dup(attr.diamondContext(speculativeTree, speculativeTree.clazz.type.tsym, resultInfo.checkContext)); |
|
614 } |
|
615 |
|
616 @Override |
|
617 Type methodType() { |
|
618 return (speculativeTree.constructorType != null) ? |
|
619 speculativeTree.constructorType.baseType() : syms.errType; |
|
620 } |
|
621 |
|
622 @Override |
|
623 ArgumentType<JCNewClass> dup(JCNewClass tree, Env<AttrContext> env) { |
|
624 return new ResolvedConstructorType(tree, env, speculativeTree, speculativeTypes); |
|
625 } |
|
626 } |
|
627 |
|
628 /** |
|
629 * An instance of this class represents a unique position in a compilation unit. A unique |
|
630 * position is made up of (i) a unique position in a source file (char offset) and (ii) |
|
631 * a source file info. |
|
632 */ |
|
633 class UniquePos { |
|
634 |
|
635 /** Char offset. */ |
|
636 int pos; |
|
637 |
|
638 /** Source info. */ |
|
639 DiagnosticSource source; |
|
640 |
|
641 UniquePos(JCTree tree) { |
|
642 this.pos = tree.pos; |
|
643 this.source = log.currentSource(); |
|
644 } |
|
645 |
|
646 @Override |
|
647 public int hashCode() { |
|
648 return pos << 16 + source.hashCode(); |
|
649 } |
|
650 |
|
651 @Override |
|
652 public boolean equals(Object obj) { |
|
653 if (obj instanceof UniquePos) { |
|
654 UniquePos that = (UniquePos)obj; |
|
655 return pos == that.pos && source == that.source; |
|
656 } else { |
|
657 return false; |
|
658 } |
|
659 } |
|
660 |
|
661 @Override |
|
662 public String toString() { |
|
663 return source.getFile().getName() + " @ " + source.getLineNumber(pos); |
|
664 } |
|
665 } |
|
666 |
|
667 /** |
|
668 * Argument type caching policy. |
|
669 */ |
|
670 enum CachePolicy { |
|
671 /** Cache argument types. */ |
|
672 CACHE, |
|
673 /** |
|
674 * Don't cache argument types. This is useful when performing speculative attribution on |
|
675 * a tree that is known to contain erroneous info. |
|
676 */ |
|
677 NO_CACHE; |
|
678 } |
|
679 } |