< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java

Print this page
rev 51258 : imported patch switch.diff

@@ -23,11 +23,10 @@
  * questions.
  */
 
 package com.sun.tools.javac.comp;
 
-import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;

@@ -37,23 +36,26 @@
 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredTypeCompleter;
 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner;
+import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner;
 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBreak;
 import com.sun.tools.javac.tree.JCTree.JCConditional;
 import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCLambda;
 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 import com.sun.tools.javac.tree.JCTree.JCNewClass;
 import com.sun.tools.javac.tree.JCTree.JCParens;
 import com.sun.tools.javac.tree.JCTree.JCReturn;
+import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
 import com.sun.tools.javac.tree.TreeCopier;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.DiagnosticSource;

@@ -143,11 +145,11 @@
 
     /**
      * Checks a type in the speculative tree against a given result; the type can be either a plain
      * type or an argument type,in which case a more complex check is required.
      */
-    Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) {
+    Type checkSpeculative(JCTree expr, ResultInfo resultInfo) {
         return checkSpeculative(expr, expr.type, resultInfo);
     }
 
     /**
      * Checks a type in the speculative tree against a given result; the type can be either a plain

@@ -254,10 +256,15 @@
     public void visitConditional(JCConditional that) {
         processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree));
     }
 
     @Override
+    public void visitSwitchExpression(JCSwitchExpression that) {
+        processArg(that, speculativeTree -> new SwitchExpressionType(that, env, speculativeTree));
+    }
+
+    @Override
     public void visitReference(JCMemberReference tree) {
         //perform arity-based check
         Env<AttrContext> localEnv = env.dup(tree);
         JCExpression exprTree;
         exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv,

@@ -454,10 +461,65 @@
             return new ConditionalType(tree, env, speculativeTree, speculativeTypes);
         }
     }
 
     /**
+     * Argument type for switch expressions.
+     */
+    class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
+        /** List of break expressions (lazily populated). */
+        Optional<List<JCBreak>> breakExpressions = Optional.empty();
+
+        SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
+            this(tree, env, speculativeCond, new HashMap<>());
+        }
+
+        SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond, Map<ResultInfo, Type> speculativeTypes) {
+           super(tree, env, speculativeCond, speculativeTypes);
+        }
+
+        @Override
+        Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+            ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
+            if (resultInfo.pt.hasTag(VOID)) {
+                //this means we are returning a poly switch expression from void-compatible lambda expression
+                resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
+                return attr.types.createErrorType(resultInfo.pt);
+            } else {
+                //poly
+                for (JCBreak brk : breakExpressions()) {
+                    checkSpeculative(brk.value, brk.value.type, resultInfo);
+                }
+                return localInfo.pt;
+            }
+        }
+
+        /** Compute return expressions (if needed). */
+        List<JCBreak> breakExpressions() {
+            return breakExpressions.orElseGet(() -> {
+                final List<JCBreak> res;
+                ListBuffer<JCBreak> buf = new ListBuffer<>();
+                new SwitchExpressionScanner() {
+                    @Override
+                    public void visitBreak(JCBreak tree) {
+                        if (tree.target == speculativeTree)
+                            buf.add(tree);
+                    }
+                }.scan(speculativeTree.cases);
+                res = buf.toList();
+                breakExpressions = Optional.of(res);
+                return res;
+            });
+        }
+
+        @Override
+        ArgumentType<JCSwitchExpression> dup(JCSwitchExpression tree, Env<AttrContext> env) {
+            return new SwitchExpressionType(tree, env, speculativeTree, speculativeTypes);
+        }
+    }
+
+    /**
      * Argument type for explicit lambdas.
      */
     class ExplicitLambdaType extends ArgumentType<JCLambda> {
 
         /** List of argument types (lazily populated). */
< prev index next >