< prev index next >
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
Print this page
rev 51258 : imported patch switch
rev 51259 : imported patch switch.01
@@ -25,10 +25,11 @@
package com.sun.tools.javac.comp;
import java.util.*;
import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
import javax.lang.model.element.ElementKind;
import javax.tools.JavaFileObject;
import com.sun.source.tree.CaseTree.CaseKind;
@@ -705,16 +706,10 @@
*/
public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType));
}
- /** Derived visitor method: attribute an expression tree.
- */
- public Type attribExpr(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
- return attribTree(tree, env, resultInfo);
- }
-
/** Derived visitor method: attribute an expression tree with
* no constraints on the computed type.
*/
public Type attribExpr(JCTree tree, Env<AttrContext> env) {
return attribTree(tree, env, unknownExprInfo);
@@ -1422,30 +1417,37 @@
ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
unknownExprInfo :
resultInfo.dup(switchExpressionContext(resultInfo.checkContext));
+ ListBuffer<DiagnosticPosition> caseTypePositions = new ListBuffer<>();
ListBuffer<Type> caseTypes = new ListBuffer<>();
handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
caseEnv.info.breakResult = condInfo;
attribStats(c.stats, caseEnv);
new TreeScanner() {
@Override
public void visitBreak(JCBreak brk) {
- if (brk.target == tree)
+ if (brk.target == tree) {
+ caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos());
caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
+ }
super.visitBreak(brk);
}
@Override public void visitClassDef(JCClassDecl tree) {}
@Override public void visitLambda(JCLambda tree) {}
- @Override public void visitMethodDef(JCMethodDecl tree) {}
}.scan(c.stats);
});
- Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, caseTypes.toList()) : pt();
+ if (tree.cases.isEmpty()) {
+ log.error(tree.pos(),
+ Errors.SwitchExpressionEmpty);
+ }
+
+ Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(caseTypePositions.toList(), caseTypes.toList()) : pt();
result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
}
//where:
CheckContext switchExpressionContext(CheckContext checkContext) {
@@ -1687,11 +1689,13 @@
resultInfo.dup(conditionalContext(resultInfo.checkContext));
Type truetype = attribTree(tree.truepart, env, condInfo);
Type falsetype = attribTree(tree.falsepart, env, condInfo);
- Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, List.of(truetype, falsetype)) : pt();
+ Type owntype = (tree.polyKind == PolyKind.STANDALONE) ?
+ condType(List.of(tree.truepart.pos(), tree.falsepart.pos()),
+ List.of(truetype, falsetype)) : pt();
if (condtype.constValue() != null &&
truetype.constValue() != null &&
falsetype.constValue() != null &&
!owntype.hasTag(NONE)) {
//constant folding
@@ -1768,12 +1772,11 @@
* @param pos The source position to be used for error
* diagnostics.
* @param thentype The type of the expression's then-part.
* @param elsetype The type of the expression's else-part.
*/
- Type condType(DiagnosticPosition pos,
- List<Type> condTypes) {
+ Type condType(List<DiagnosticPosition> positions, List<Type> condTypes) {
if (condTypes.isEmpty()) {
return syms.objectType; //TODO: how to handle?
}
if (condTypes.size() == 1) {
return condTypes.head;
@@ -1819,17 +1822,15 @@
for (Type type : condTypes) {
if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type)))
return type.baseType();
}
- if (condTypes.stream().anyMatch(t -> t.hasTag(VOID))) {
- //XXX:
- log.error(pos,
- Errors.NeitherConditionalSubtype(condTypes.head,
- condTypes.tail.head));
- return condTypes.head.baseType();
- }
+ Iterator<DiagnosticPosition> posIt = positions.iterator();
+
+ condTypes = condTypes.stream()
+ .map(t -> chk.checkNonVoid(posIt.next(), t))
+ .collect(List.collector());
// both are known to be reference types. The result is
// lub(thentype,elsetype). This cannot fail, as it will
// always be possible to infer "Object" if nothing better.
return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector()));
< prev index next >