< 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 >