1 /* |
1 /* |
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
41 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner; |
41 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner; |
42 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType; |
42 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType; |
43 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; |
43 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; |
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments; |
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments; |
45 import com.sun.tools.javac.tree.JCTree; |
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; |
46 import com.sun.tools.javac.tree.JCTree.JCConditional; |
48 import com.sun.tools.javac.tree.JCTree.JCExpression; |
47 import com.sun.tools.javac.tree.JCTree.JCExpression; |
49 import com.sun.tools.javac.tree.JCTree.JCLambda; |
48 import com.sun.tools.javac.tree.JCTree.JCLambda; |
50 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; |
49 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; |
51 import com.sun.tools.javac.tree.JCTree.JCMemberReference; |
50 import com.sun.tools.javac.tree.JCTree.JCMemberReference; |
75 import static com.sun.tools.javac.code.TypeTag.ARRAY; |
74 import static com.sun.tools.javac.code.TypeTag.ARRAY; |
76 import static com.sun.tools.javac.code.TypeTag.DEFERRED; |
75 import static com.sun.tools.javac.code.TypeTag.DEFERRED; |
77 import static com.sun.tools.javac.code.TypeTag.FORALL; |
76 import static com.sun.tools.javac.code.TypeTag.FORALL; |
78 import static com.sun.tools.javac.code.TypeTag.METHOD; |
77 import static com.sun.tools.javac.code.TypeTag.METHOD; |
79 import static com.sun.tools.javac.code.TypeTag.VOID; |
78 import static com.sun.tools.javac.code.TypeTag.VOID; |
|
79 import com.sun.tools.javac.tree.JCTree.JCYield; |
80 |
80 |
81 /** |
81 /** |
82 * This class performs attribution of method/constructor arguments when target-typing is enabled |
82 * This class performs attribution of method/constructor arguments when target-typing is enabled |
83 * (source >= 8); for each argument that is potentially a poly expression, this class builds |
83 * (source >= 8); for each argument that is potentially a poly expression, this class builds |
84 * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload |
84 * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload |
134 /** |
134 /** |
135 * Set the results of method attribution. |
135 * Set the results of method attribution. |
136 */ |
136 */ |
137 void setResult(JCExpression tree, Type type) { |
137 void setResult(JCExpression tree, Type type) { |
138 result = type; |
138 result = type; |
139 if (env.info.isSpeculative) { |
139 if (env.info.attributionMode == DeferredAttr.AttributionMode.SPECULATIVE) { |
140 //if we are in a speculative branch we can save the type in the tree itself |
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. |
141 //as there's no risk of polluting the original tree. |
142 tree.type = result; |
142 tree.type = result; |
143 } |
143 } |
144 } |
144 } |
363 deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) : |
363 deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) : |
364 overloadCheck(resultInfo, deferredAttrContext); |
364 overloadCheck(resultInfo, deferredAttrContext); |
365 speculativeTypes.put(resultInfo, t); |
365 speculativeTypes.put(resultInfo, t); |
366 return t; |
366 return t; |
367 } else { |
367 } else { |
368 if (!env.info.isSpeculative) { |
368 if (!env.info.attributionMode.isSpeculative) { |
369 argumentTypeCache.remove(new UniquePos(dt.tree)); |
369 argumentTypeCache.remove(new UniquePos(dt.tree)); |
370 } |
370 } |
371 return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext); |
371 return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext); |
372 } |
372 } |
373 } |
373 } |
466 /** |
466 /** |
467 * Argument type for switch expressions. |
467 * Argument type for switch expressions. |
468 */ |
468 */ |
469 class SwitchExpressionType extends ArgumentType<JCSwitchExpression> { |
469 class SwitchExpressionType extends ArgumentType<JCSwitchExpression> { |
470 /** List of break expressions (lazily populated). */ |
470 /** List of break expressions (lazily populated). */ |
471 Optional<List<JCBreak>> breakExpressions = Optional.empty(); |
471 Optional<List<JCYield>> yieldExpressions = Optional.empty(); |
472 |
472 |
473 SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) { |
473 SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) { |
474 this(tree, env, speculativeCond, new HashMap<>()); |
474 this(tree, env, speculativeCond, new HashMap<>()); |
475 } |
475 } |
476 |
476 |
485 //this means we are returning a poly switch expression from void-compatible lambda expression |
485 //this means we are returning a poly switch expression from void-compatible lambda expression |
486 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid)); |
486 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid)); |
487 return attr.types.createErrorType(resultInfo.pt); |
487 return attr.types.createErrorType(resultInfo.pt); |
488 } else { |
488 } else { |
489 //poly |
489 //poly |
490 for (JCBreak brk : breakExpressions()) { |
490 for (JCYield brk : yieldExpressions()) { |
491 checkSpeculative(brk.value, brk.value.type, resultInfo); |
491 checkSpeculative(brk.value, brk.value.type, resultInfo); |
492 } |
492 } |
493 return localInfo.pt; |
493 return localInfo.pt; |
494 } |
494 } |
495 } |
495 } |
496 |
496 |
497 /** Compute return expressions (if needed). */ |
497 /** Compute return expressions (if needed). */ |
498 List<JCBreak> breakExpressions() { |
498 List<JCYield> yieldExpressions() { |
499 return breakExpressions.orElseGet(() -> { |
499 return yieldExpressions.orElseGet(() -> { |
500 final List<JCBreak> res; |
500 final List<JCYield> res; |
501 ListBuffer<JCBreak> buf = new ListBuffer<>(); |
501 ListBuffer<JCYield> buf = new ListBuffer<>(); |
502 new SwitchExpressionScanner() { |
502 new SwitchExpressionScanner() { |
503 @Override |
503 @Override |
504 public void visitBreak(JCBreak tree) { |
504 public void visitYield(JCYield tree) { |
505 if (tree.target == speculativeTree) |
505 if (tree.target == speculativeTree) |
506 buf.add(tree); |
506 buf.add(tree); |
|
507 super.visitYield(tree); |
507 } |
508 } |
508 }.scan(speculativeTree.cases); |
509 }.scan(speculativeTree.cases); |
509 res = buf.toList(); |
510 res = buf.toList(); |
510 breakExpressions = Optional.of(res); |
511 yieldExpressions = Optional.of(res); |
511 return res; |
512 return res; |
512 }); |
513 }); |
513 } |
514 } |
514 |
515 |
515 @Override |
516 @Override |