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.resources.CompilerProperties.Fragments;
45 import com.sun.tools.javac.tree.JCTree;
46 import com.sun.tools.javac.tree.JCTree.JCConditional;
47 import com.sun.tools.javac.tree.JCTree.JCExpression;
48 import com.sun.tools.javac.tree.JCTree.JCLambda;
49 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
50 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
51 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
52 import com.sun.tools.javac.tree.JCTree.JCNewClass;
53 import com.sun.tools.javac.tree.JCTree.JCParens;
54 import com.sun.tools.javac.tree.JCTree.JCReturn;
55 import com.sun.tools.javac.tree.TreeCopier;
56 import com.sun.tools.javac.tree.TreeInfo;
57 import com.sun.tools.javac.util.Assert;
58 import com.sun.tools.javac.util.Context;
59 import com.sun.tools.javac.util.DiagnosticSource;
60 import com.sun.tools.javac.util.JCDiagnostic;
61 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
62 import com.sun.tools.javac.util.List;
63 import com.sun.tools.javac.util.ListBuffer;
64 import com.sun.tools.javac.util.Log;
65
66 import java.util.HashMap;
67 import java.util.LinkedHashMap;
68 import java.util.Map;
69 import java.util.Optional;
70 import java.util.function.Function;
71 import java.util.function.Supplier;
72
73 import static com.sun.tools.javac.code.TypeTag.ARRAY;
74 import static com.sun.tools.javac.code.TypeTag.DEFERRED;
128 syms = Symtab.instance(context);
129 log = Log.instance(context);
130 }
131
132 /**
133 * Set the results of method attribution.
134 */
135 void setResult(JCExpression tree, Type type) {
136 result = type;
137 if (env.info.isSpeculative) {
138 //if we are in a speculative branch we can save the type in the tree itself
139 //as there's no risk of polluting the original tree.
140 tree.type = result;
141 }
142 }
143
144 /**
145 * Checks a type in the speculative tree against a given result; the type can be either a plain
146 * type or an argument type,in which case a more complex check is required.
147 */
148 Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) {
149 return checkSpeculative(expr, expr.type, resultInfo);
150 }
151
152 /**
153 * Checks a type in the speculative tree against a given result; the type can be either a plain
154 * type or an argument type,in which case a more complex check is required.
155 */
156 Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) {
157 if (t.hasTag(DEFERRED)) {
158 return ((DeferredType)t).check(resultInfo);
159 } else {
160 return resultInfo.check(pos, t);
161 }
162 }
163
164 /**
165 * Returns a local caching context in which argument types can safely be cached without
166 * the risk of polluting enclosing contexts. This is useful when attempting speculative
167 * attribution of potentially erroneous expressions, which could end up polluting the cache.
168 */
239 //dup existing speculative type
240 setResult(that, cached.dup(that, env));
241 } else {
242 Z res = argumentTypeFactory.get();
243 argumentTypeCache.put(pos, res);
244 setResult(that, res);
245 }
246 }
247
248 @Override
249 public void visitParens(JCParens that) {
250 processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree));
251 }
252
253 @Override
254 public void visitConditional(JCConditional that) {
255 processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree));
256 }
257
258 @Override
259 public void visitReference(JCMemberReference tree) {
260 //perform arity-based check
261 Env<AttrContext> localEnv = env.dup(tree);
262 JCExpression exprTree;
263 exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv,
264 attr.memberReferenceQualifierResult(tree),
265 withLocalCacheContext());
266 JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree);
267 mref2.expr = exprTree;
268 Symbol lhsSym = TreeInfo.symbol(exprTree);
269 localEnv.info.selectSuper = lhsSym != null && lhsSym.name == lhsSym.name.table.names._super;
270 Symbol res =
271 attr.rs.getMemberReference(tree, localEnv, mref2,
272 exprTree.type, tree.name);
273 if (!res.kind.isResolutionError()) {
274 tree.sym = res;
275 }
276 if (res.kind.isResolutionTargetError() ||
277 res.type != null && res.type.hasTag(FORALL) ||
278 (res.flags() & Flags.VARARGS) != 0 ||
435 @Override
436 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
437 ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
438 if (speculativeTree.isStandalone()) {
439 return localInfo.check(speculativeTree, speculativeTree.type);
440 } else if (resultInfo.pt.hasTag(VOID)) {
441 //this means we are returning a poly conditional from void-compatible lambda expression
442 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.ConditionalTargetCantBeVoid));
443 return attr.types.createErrorType(resultInfo.pt);
444 } else {
445 //poly
446 checkSpeculative(speculativeTree.truepart, localInfo);
447 checkSpeculative(speculativeTree.falsepart, localInfo);
448 return localInfo.pt;
449 }
450 }
451
452 @Override
453 ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) {
454 return new ConditionalType(tree, env, speculativeTree, speculativeTypes);
455 }
456 }
457
458 /**
459 * Argument type for explicit lambdas.
460 */
461 class ExplicitLambdaType extends ArgumentType<JCLambda> {
462
463 /** List of argument types (lazily populated). */
464 Optional<List<Type>> argtypes = Optional.empty();
465
466 /** List of return expressions (lazily populated). */
467 Optional<List<JCReturn>> returnExpressions = Optional.empty();
468
469 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) {
470 this(originalLambda, env, speculativeLambda, new HashMap<>());
471 }
472
473 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) {
474 super(originalLambda, env, speculativeLambda, speculativeTypes);
|
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.tools.javac.code.Flags;
29 import com.sun.tools.javac.code.Symbol;
30 import com.sun.tools.javac.code.Symtab;
31 import com.sun.tools.javac.code.Type;
32 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
33 import com.sun.tools.javac.comp.Attr.ResultInfo;
34 import com.sun.tools.javac.comp.Attr.TargetInfo;
35 import com.sun.tools.javac.comp.Check.CheckContext;
36 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
37 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
38 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
39 import com.sun.tools.javac.comp.DeferredAttr.DeferredTypeCompleter;
40 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner;
41 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner;
42 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
43 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
45 import com.sun.tools.javac.tree.JCTree;
46 import com.sun.tools.javac.tree.JCTree.JCBreak;
47 import com.sun.tools.javac.tree.JCTree.JCConditional;
48 import com.sun.tools.javac.tree.JCTree.JCExpression;
49 import com.sun.tools.javac.tree.JCTree.JCLambda;
50 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
51 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
52 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
53 import com.sun.tools.javac.tree.JCTree.JCNewClass;
54 import com.sun.tools.javac.tree.JCTree.JCParens;
55 import com.sun.tools.javac.tree.JCTree.JCReturn;
56 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
57 import com.sun.tools.javac.tree.TreeCopier;
58 import com.sun.tools.javac.tree.TreeInfo;
59 import com.sun.tools.javac.util.Assert;
60 import com.sun.tools.javac.util.Context;
61 import com.sun.tools.javac.util.DiagnosticSource;
62 import com.sun.tools.javac.util.JCDiagnostic;
63 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
64 import com.sun.tools.javac.util.List;
65 import com.sun.tools.javac.util.ListBuffer;
66 import com.sun.tools.javac.util.Log;
67
68 import java.util.HashMap;
69 import java.util.LinkedHashMap;
70 import java.util.Map;
71 import java.util.Optional;
72 import java.util.function.Function;
73 import java.util.function.Supplier;
74
75 import static com.sun.tools.javac.code.TypeTag.ARRAY;
76 import static com.sun.tools.javac.code.TypeTag.DEFERRED;
130 syms = Symtab.instance(context);
131 log = Log.instance(context);
132 }
133
134 /**
135 * Set the results of method attribution.
136 */
137 void setResult(JCExpression tree, Type type) {
138 result = type;
139 if (env.info.isSpeculative) {
140 //if we are in a speculative branch we can save the type in the tree itself
141 //as there's no risk of polluting the original tree.
142 tree.type = result;
143 }
144 }
145
146 /**
147 * Checks a type in the speculative tree against a given result; the type can be either a plain
148 * type or an argument type,in which case a more complex check is required.
149 */
150 Type checkSpeculative(JCTree expr, ResultInfo resultInfo) {
151 return checkSpeculative(expr, expr.type, resultInfo);
152 }
153
154 /**
155 * Checks a type in the speculative tree against a given result; the type can be either a plain
156 * type or an argument type,in which case a more complex check is required.
157 */
158 Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) {
159 if (t.hasTag(DEFERRED)) {
160 return ((DeferredType)t).check(resultInfo);
161 } else {
162 return resultInfo.check(pos, t);
163 }
164 }
165
166 /**
167 * Returns a local caching context in which argument types can safely be cached without
168 * the risk of polluting enclosing contexts. This is useful when attempting speculative
169 * attribution of potentially erroneous expressions, which could end up polluting the cache.
170 */
241 //dup existing speculative type
242 setResult(that, cached.dup(that, env));
243 } else {
244 Z res = argumentTypeFactory.get();
245 argumentTypeCache.put(pos, res);
246 setResult(that, res);
247 }
248 }
249
250 @Override
251 public void visitParens(JCParens that) {
252 processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree));
253 }
254
255 @Override
256 public void visitConditional(JCConditional that) {
257 processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree));
258 }
259
260 @Override
261 public void visitSwitchExpression(JCSwitchExpression that) {
262 processArg(that, speculativeTree -> new SwitchExpressionType(that, env, speculativeTree));
263 }
264
265 @Override
266 public void visitReference(JCMemberReference tree) {
267 //perform arity-based check
268 Env<AttrContext> localEnv = env.dup(tree);
269 JCExpression exprTree;
270 exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv,
271 attr.memberReferenceQualifierResult(tree),
272 withLocalCacheContext());
273 JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree);
274 mref2.expr = exprTree;
275 Symbol lhsSym = TreeInfo.symbol(exprTree);
276 localEnv.info.selectSuper = lhsSym != null && lhsSym.name == lhsSym.name.table.names._super;
277 Symbol res =
278 attr.rs.getMemberReference(tree, localEnv, mref2,
279 exprTree.type, tree.name);
280 if (!res.kind.isResolutionError()) {
281 tree.sym = res;
282 }
283 if (res.kind.isResolutionTargetError() ||
284 res.type != null && res.type.hasTag(FORALL) ||
285 (res.flags() & Flags.VARARGS) != 0 ||
442 @Override
443 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
444 ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
445 if (speculativeTree.isStandalone()) {
446 return localInfo.check(speculativeTree, speculativeTree.type);
447 } else if (resultInfo.pt.hasTag(VOID)) {
448 //this means we are returning a poly conditional from void-compatible lambda expression
449 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.ConditionalTargetCantBeVoid));
450 return attr.types.createErrorType(resultInfo.pt);
451 } else {
452 //poly
453 checkSpeculative(speculativeTree.truepart, localInfo);
454 checkSpeculative(speculativeTree.falsepart, localInfo);
455 return localInfo.pt;
456 }
457 }
458
459 @Override
460 ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) {
461 return new ConditionalType(tree, env, speculativeTree, speculativeTypes);
462 }
463 }
464
465 /**
466 * Argument type for switch expressions.
467 */
468 class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
469 /** List of break expressions (lazily populated). */
470 Optional<List<JCBreak>> breakExpressions = Optional.empty();
471
472 SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
473 this(tree, env, speculativeCond, new HashMap<>());
474 }
475
476 SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond, Map<ResultInfo, Type> speculativeTypes) {
477 super(tree, env, speculativeCond, speculativeTypes);
478 }
479
480 @Override
481 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
482 ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
483 if (speculativeTree.isStandalone()) {
484 return localInfo.check(speculativeTree, speculativeTree.type);
485 } else if (resultInfo.pt.hasTag(VOID)) {
486 //this means we are returning a poly switch expression from void-compatible lambda expression
487 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
488 return attr.types.createErrorType(resultInfo.pt);
489 } else {
490 //poly
491 for (JCBreak brk : breakExpressions()) {
492 checkSpeculative(brk.value, brk.value.type, resultInfo);
493 }
494 return localInfo.pt;
495 }
496 }
497
498 /** Compute return expressions (if needed). */
499 List<JCBreak> breakExpressions() {
500 return breakExpressions.orElseGet(() -> {
501 final List<JCBreak> res;
502 ListBuffer<JCBreak> buf = new ListBuffer<>();
503 new SwitchExpressionScanner() {
504 @Override
505 public void visitBreak(JCBreak tree) {
506 if (tree.target == speculativeTree)
507 buf.add(tree);
508 }
509 }.scan(speculativeTree.cases);
510 res = buf.toList();
511 breakExpressions = Optional.of(res);
512 return res;
513 });
514 }
515
516 @Override
517 ArgumentType<JCSwitchExpression> dup(JCSwitchExpression tree, Env<AttrContext> env) {
518 return new SwitchExpressionType(tree, env, speculativeTree, speculativeTypes);
519 }
520 }
521
522 /**
523 * Argument type for explicit lambdas.
524 */
525 class ExplicitLambdaType extends ArgumentType<JCLambda> {
526
527 /** List of argument types (lazily populated). */
528 Optional<List<Type>> argtypes = Optional.empty();
529
530 /** List of return expressions (lazily populated). */
531 Optional<List<JCReturn>> returnExpressions = Optional.empty();
532
533 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) {
534 this(originalLambda, env, speculativeLambda, new HashMap<>());
535 }
536
537 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) {
538 super(originalLambda, env, speculativeLambda, speculativeTypes);
|