--- old/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java 2018-08-01 08:09:03.455826066 +0200 +++ new/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java 2018-08-01 08:09:03.163826080 +0200 @@ -27,6 +27,7 @@ import java.util.*; import java.util.function.BiConsumer; +import java.util.stream.Collectors; import javax.lang.model.element.ElementKind; import javax.tools.JavaFileObject; @@ -707,12 +708,6 @@ 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 env, ResultInfo resultInfo) { - return attribTree(tree, env, resultInfo); - } - /** Derived visitor method: attribute an expression tree with * no constraints on the computed type. */ @@ -1424,6 +1419,7 @@ unknownExprInfo : resultInfo.dup(switchExpressionContext(resultInfo.checkContext)); + ListBuffer caseTypePositions = new ListBuffer<>(); ListBuffer caseTypes = new ListBuffer<>(); handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> { @@ -1432,18 +1428,24 @@ 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); } @@ -1689,7 +1691,9 @@ 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 && @@ -1770,8 +1774,7 @@ * @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 condTypes) { + Type condType(List positions, List condTypes) { if (condTypes.isEmpty()) { return syms.objectType; //TODO: how to handle? } @@ -1821,13 +1824,11 @@ 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 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