8223305: Compiler support for Switch Expressions

Reviewed-by: mcimadamore, vromero
This commit is contained in:
Jan Lahoda 2019-06-10 05:09:52 +02:00
parent c569ad302a
commit b34b2d993c
88 changed files with 2033 additions and 829 deletions
src
test/langtools/tools/javac
diags/examples
expswitch
lambda/deduplication
lib
lvti
parser
switchexpr
switchextra
var_implicit_lambda

@ -257,8 +257,8 @@ public enum SourceVersion {
* followed only by characters for which {@link
* Character#isJavaIdentifierPart(int)} returns {@code true}.
* This pattern matches regular identifiers, keywords, restricted
* keywords, and the literals {@code "true"}, {@code "false"},
* {@code "null"}, and {@code "var"}.
* keywords, restricted identifiers and the literals {@code "true"},
* {@code "false"}, {@code "null"}.
*
* The method returns {@code false} for all other strings.
*
@ -295,7 +295,7 @@ public enum SourceVersion {
* for keywords, boolean literals, and the null literal.
*
* This method returns {@code true} for <i>restricted
* keywords</i> and {@code "var"}.
* keywords</i> and <i>restricted identifiers</i>
*
* @param name the string to check
* @return {@code true} if this string is a
@ -314,7 +314,7 @@ public enum SourceVersion {
* for keywords, boolean literals, and the null literal.
*
* This method returns {@code true} for <i>restricted
* keywords</i> and {@code "var"}.
* keywords</i> and <i>restricted identifiers</i>
*
* @param name the string to check
* @param version the version to use
@ -338,7 +338,7 @@ public enum SourceVersion {
* Returns whether or not {@code s} is a keyword, boolean literal,
* or null literal in the latest source version.
* This method returns {@code false} for <i>restricted
* keywords</i> and {@code "var"}.
* keywords</i> and <i>restricted identifiers</i>.
*
* @param s the string to check
* @return {@code true} if {@code s} is a keyword, or boolean
@ -355,7 +355,7 @@ public enum SourceVersion {
* Returns whether or not {@code s} is a keyword, boolean literal,
* or null literal in the given source version.
* This method returns {@code false} for <i>restricted
* keywords</i> and {@code "var"}.
* keywords</i> and <i>restricted identifiers</i>.
*
* @param s the string to check
* @param version the version to use

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,8 +35,6 @@ import javax.lang.model.element.Name;
* break;
*
* break <em>label</em> ;
*
* break <em>expression</em> ;
* </pre>
*
* @jls 14.15 The break Statement
@ -52,17 +50,4 @@ public interface BreakTree extends StatementTree {
*/
Name getLabel();
/**
* Returns the expression for this {@code break} statement.
*
* @return the expression
* @since 12
*
* @deprecated This method is modeling value breaks, which are part of
* a preview feature and may be removed if the preview feature
* is removed.
*
*/
@Deprecated(forRemoval=true, since="12")
ExpressionTree getValue();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -656,7 +656,21 @@ public interface Tree {
* An implementation-reserved node. This is the not the node
* you are looking for.
*/
OTHER(null);
OTHER(null),
/**
* Used for instances of {@link YieldTree}.
*
* @since 13
*
* @deprecated
* This enum constant is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
YIELD(YieldTree.class);
Kind(Class<? extends Tree> intf) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -555,4 +555,20 @@ public interface TreeVisitor<R,P> {
* @return a result value
*/
R visitOther(Tree node, P p);
/**
* Visits a YieldTree node.
* @param node the node being visited
* @param p a parameter value
* @return a result value
* @since 13
*
* @deprecated
* This method is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
R visitYield(YieldTree node, P p);
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.source.tree;
/**
* A tree node for a {@code yield} statement.
*
* For example:
* <pre>
* yield <em>expression</em> ;
* </pre>
*
* @jls section TODO
*
* @since 13
*
* @deprecated This class is modeling yield from switch expressions,
* which are part of a preview feature and may be removed if
* the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
public interface YieldTree extends StatementTree {
/**
* Returns the expression for this {@code yield} statement.
*
* @return the expression
*/
ExpressionTree getValue();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -782,4 +782,18 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
public R visitOther(Tree node, P p) {
return defaultAction(node, p);
}
/**
* {@inheritDoc} This implementation calls {@code defaultAction}.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*/
@Override
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
public R visitYield(YieldTree node, P p) {
return defaultAction(node, p);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -467,9 +467,8 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
* @return the result of scanning
*/
@Override
@SuppressWarnings("removal")
public R visitBreak(BreakTree node, P p) {
return scan(node.getValue(), p);
return null;
}
/**
@ -935,4 +934,23 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
public R visitErroneous(ErroneousTree node, P p) {
return null;
}
/**
* {@inheritDoc} This implementation returns {@code null}.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of scanning
*
* @deprecated
* This method is modeling switch expressions,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Override
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
public R visitYield(YieldTree node, P p) {
return scan(node.getValue(), p);
}
}

@ -71,7 +71,7 @@ public class Kinds {
HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target
STATICERR(Category.RESOLUTION_TARGET), // overloaded? target
MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target
BAD_VAR(Category.RESOLUTION), // not overloaded non-target
BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target
ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target
WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target
WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,7 +43,6 @@ 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;
@ -77,6 +76,7 @@ import static com.sun.tools.javac.code.TypeTag.DEFERRED;
import static com.sun.tools.javac.code.TypeTag.FORALL;
import static com.sun.tools.javac.code.TypeTag.METHOD;
import static com.sun.tools.javac.code.TypeTag.VOID;
import com.sun.tools.javac.tree.JCTree.JCYield;
/**
* This class performs attribution of method/constructor arguments when target-typing is enabled
@ -468,7 +468,7 @@ public class ArgumentAttr extends JCTree.Visitor {
*/
class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
/** List of break expressions (lazily populated). */
Optional<List<JCBreak>> breakExpressions = Optional.empty();
Optional<List<JCYield>> yieldExpressions = Optional.empty();
SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
this(tree, env, speculativeCond, new HashMap<>());
@ -487,7 +487,7 @@ public class ArgumentAttr extends JCTree.Visitor {
return attr.types.createErrorType(resultInfo.pt);
} else {
//poly
for (JCBreak brk : breakExpressions()) {
for (JCYield brk : yieldExpressions()) {
checkSpeculative(brk.value, brk.value.type, resultInfo);
}
return localInfo.pt;
@ -495,19 +495,20 @@ public class ArgumentAttr extends JCTree.Visitor {
}
/** Compute return expressions (if needed). */
List<JCBreak> breakExpressions() {
return breakExpressions.orElseGet(() -> {
final List<JCBreak> res;
ListBuffer<JCBreak> buf = new ListBuffer<>();
List<JCYield> yieldExpressions() {
return yieldExpressions.orElseGet(() -> {
final List<JCYield> res;
ListBuffer<JCYield> buf = new ListBuffer<>();
new SwitchExpressionScanner() {
@Override
public void visitBreak(JCBreak tree) {
public void visitYield(JCYield tree) {
if (tree.target == speculativeTree)
buf.add(tree);
super.visitYield(tree);
}
}.scan(speculativeTree.cases);
res = buf.toList();
breakExpressions = Optional.of(res);
yieldExpressions = Optional.of(res);
return res;
});
}

@ -77,6 +77,8 @@ import static com.sun.tools.javac.code.TypeTag.WILDCARD;
import com.sun.tools.javac.comp.Analyzer.AnalyzerMode;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
/** This is the main context-dependent analysis phase in GJC. It
* encompasses name resolution, type checking and constant folding as
@ -358,7 +360,7 @@ public class Attr extends JCTree.Visitor {
Name name = (Name)node.getIdentifier();
if (site.kind == PCK) {
env.toplevel.packge = (PackageSymbol)site;
return rs.findIdentInPackage(env, (TypeSymbol)site, name,
return rs.findIdentInPackage(null, env, (TypeSymbol)site, name,
KindSelector.TYP_PCK);
} else {
env.enclClass.sym = (ClassSymbol)site;
@ -368,7 +370,7 @@ public class Attr extends JCTree.Visitor {
@Override @DefinedBy(Api.COMPILER_TREE)
public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) {
return rs.findIdent(env, (Name)node.getName(), KindSelector.TYP_PCK);
return rs.findIdent(null, env, (Name)node.getName(), KindSelector.TYP_PCK);
}
}
@ -1425,16 +1427,16 @@ public class Attr extends JCTree.Visitor {
ListBuffer<Type> caseTypes = new ListBuffer<>();
handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
caseEnv.info.breakResult = condInfo;
caseEnv.info.yieldResult = condInfo;
attribStats(c.stats, caseEnv);
new TreeScanner() {
@Override
public void visitBreak(JCBreak brk) {
public void visitYield(JCYield brk) {
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);
super.visitYield(brk);
}
@Override public void visitClassDef(JCClassDecl tree) {}
@ -1864,67 +1866,19 @@ public class Attr extends JCTree.Visitor {
}
public void visitBreak(JCBreak tree) {
if (env.info.breakResult != null) {
if (tree.value == null) {
tree.target = findJumpTarget(tree.pos(), tree.getTag(), null, env);
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
log.error(tree.pos(), Errors.BreakMissingValue);
}
} else {
if (env.info.breakResult.pt.hasTag(VOID)) {
//can happen?
env.info.breakResult.checkContext.report(tree.value.pos(),
diags.fragment(Fragments.UnexpectedRetVal));
}
boolean attribute = true;
if (tree.value.hasTag(IDENT)) {
//disambiguate break <LABEL> and break <ident-as-an-expression>:
Name label = ((JCIdent) tree.value).name;
Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tree.getTag(), label, env);
tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
result = null;
}
if (jumpTarget.fst != null) {
JCTree speculative = deferredAttr.attribSpeculative(tree.value, env, unknownExprInfo);
if (!speculative.type.hasTag(ERROR)) {
log.error(tree.pos(), Errors.BreakAmbiguousTarget(label));
if (jumpTarget.snd == null) {
tree.target = jumpTarget.fst;
attribute = false;
} else {
//nothing
}
} else {
if (jumpTarget.snd != null) {
log.error(tree.pos(), jumpTarget.snd);
}
tree.target = jumpTarget.fst;
attribute = false;
}
}
}
if (attribute) {
attribTree(tree.value, env, env.info.breakResult);
JCTree immediateTarget = findJumpTarget(tree.pos(), tree.getTag(), null, env);
if (immediateTarget.getTag() != SWITCH_EXPRESSION) {
log.error(tree.pos(), Errors.BreakExprNotImmediate(immediateTarget.getTag()));
Env<AttrContext> env1 = env;
while (env1 != null && env1.tree.getTag() != SWITCH_EXPRESSION) {
env1 = env1.next;
}
Assert.checkNonNull(env1);
tree.target = env1.tree;
} else {
tree.target = immediateTarget;
}
}
}
public void visitYield(JCYield tree) {
if (env.info.yieldResult != null) {
attribTree(tree.value, env, env.info.yieldResult);
tree.target = findJumpTarget(tree.pos(), tree.getTag(), names.empty, env);
} else {
if (tree.value == null || tree.value.hasTag(IDENT)) {
Name label = tree.value != null ? ((JCIdent) tree.value).name : null;
tree.target = findJumpTarget(tree.pos(), tree.getTag(), label, env);
} else {
log.error(tree.pos(), Errors.BreakComplexValueNoSwitchExpression);
attribTree(tree.value, env, unknownExprInfo);
}
log.error(tree.pos(), tree.value.hasTag(PARENS)
? Errors.NoSwitchExpressionQualify
: Errors.NoSwitchExpression);
attribTree(tree.value, env, unknownExprInfo);
}
result = null;
}
@ -1934,8 +1888,8 @@ public class Attr extends JCTree.Visitor {
result = null;
}
//where
/** Return the target of a break or continue statement, if it exists,
* report an error if not.
/** Return the target of a break, continue or yield statement,
* if it exists, report an error if not.
* Note: The target of a labelled break or continue is the
* (non-labelled) statement tree referred to by the label,
* not the tree representing the labelled statement itself.
@ -2009,12 +1963,10 @@ public class Attr extends JCTree.Visitor {
if (label == null && tag == BREAK) return Pair.of(env1.tree, null);
break;
case SWITCH_EXPRESSION:
if (tag == BREAK) {
if (label == null) {
return Pair.of(env1.tree, null);
} else {
pendingError = Errors.BreakOutsideSwitchExpression;
}
if (tag == YIELD) {
return Pair.of(env1.tree, null);
} else if (tag == BREAK) {
pendingError = Errors.BreakOutsideSwitchExpression;
} else {
pendingError = Errors.ContinueOutsideSwitchExpression;
}
@ -2029,6 +1981,8 @@ public class Attr extends JCTree.Visitor {
}
if (label != null)
return Pair.of(null, Errors.UndefLabel(label));
else if (pendingError != null)
return Pair.of(null, pendingError);
else if (tag == CONTINUE)
return Pair.of(null, Errors.ContOutsideLoop);
else
@ -2040,7 +1994,7 @@ public class Attr extends JCTree.Visitor {
// nested within than the enclosing class.
if (env.info.returnResult == null) {
log.error(tree.pos(), Errors.RetOutsideMeth);
} else if (env.info.breakResult != null) {
} else if (env.info.yieldResult != null) {
log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression);
} else {
// Attribute return expression, if it exists, and check that
@ -3136,7 +3090,7 @@ public class Attr extends JCTree.Visitor {
} else {
lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
}
lambdaEnv.info.breakResult = null;
lambdaEnv.info.yieldResult = null;
return lambdaEnv;
}
@ -3916,7 +3870,7 @@ public class Attr extends JCTree.Visitor {
switch (site.getTag()) {
case PACKAGE:
return rs.accessBase(
rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind),
rs.findIdentInPackage(pos, env, site.tsym, name, resultInfo.pkind),
pos, location, site, name, true);
case ARRAY:
case CLASS:
@ -3931,7 +3885,7 @@ public class Attr extends JCTree.Visitor {
return syms.getClassField(site, types);
} else {
// We are seeing a plain identifier as selector.
Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind);
Symbol sym = rs.findIdentInType(pos, env, site, name, resultInfo.pkind);
sym = rs.accessBase(sym, pos, location, site, name, true);
return sym;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -101,10 +101,10 @@ public class AttrContext {
*/
Attr.ResultInfo returnResult = null;
/** ResultInfo to be used for attributing 'break' statement expressions
/** ResultInfo to be used for attributing 'yield' statement expressions
* (set by Attr.visitSwitchExpression)
*/
Attr.ResultInfo breakResult = null;
Attr.ResultInfo yieldResult = null;
/** Symbol corresponding to the site of a qualified default super call
*/
@ -129,7 +129,7 @@ public class AttrContext {
info.lint = lint;
info.enclVar = enclVar;
info.returnResult = returnResult;
info.breakResult = breakResult;
info.yieldResult = yieldResult;
info.defaultSuperCallSite = defaultSuperCallSite;
info.isSerializable = isSerializable;
info.isLambda = isLambda;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1161,7 +1161,7 @@ public class DeferredAttr extends JCTree.Visitor {
SwitchExpressionScanner() {
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
FORLOOP, IF, BREAK, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
FORLOOP, IF, SYNCHRONIZED, SWITCH, TRY, WHILELOOP, YIELD));
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -314,6 +314,12 @@ public class Flow {
JCTree getTarget(JCTree tree) {
return ((JCContinue)tree).target;
}
},
YIELD(JCTree.Tag.YIELD) {
@Override
JCTree getTarget(JCTree tree) {
return ((JCYield)tree).target;
}
};
final JCTree.Tag treeTag;
@ -386,6 +392,11 @@ public class Flow {
return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
}
/** Resolve all yields of this statement. */
Liveness resolveYields(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
return resolveJump(tree, oldPendingExits, JumpKind.YIELD);
}
@Override
public void scan(JCTree tree) {
if (tree != null && (
@ -400,9 +411,15 @@ public class Flow {
}
protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
JCBreak brk = make.at(Position.NOPOS).Break(null);
brk.target = swtch;
scan(brk);
if (swtch.hasTag(SWITCH_EXPRESSION)) {
JCYield brk = make.at(Position.NOPOS).Yield(null);
brk.target = swtch;
scan(brk);
} else {
JCBreak brk = make.at(Position.NOPOS).Break(null);
brk.target = swtch;
scan(brk);
}
}
}
@ -517,7 +534,8 @@ public class Flow {
while (exits.nonEmpty()) {
PendingExit exit = exits.head;
exits = exits.tail;
Assert.check(exit.tree.hasTag(RETURN));
Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
}
} finally {
lint = lintPrev;
@ -677,7 +695,7 @@ public class Flow {
log.error(tree, Errors.NotExhaustive);
}
alive = prevAlive;
alive = alive.or(resolveBreaks(tree, prevPendingExits));
alive = alive.or(resolveYields(tree, prevPendingExits));
}
public void visitTry(JCTry tree) {
@ -745,8 +763,12 @@ public class Flow {
}
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak())
scan(tree.value);
recordExit(new PendingExit(tree));
}
@Override
public void visitYield(JCYield tree) {
scan(tree.value);
recordExit(new PendingExit(tree));
}
@ -1032,7 +1054,8 @@ public class Flow {
PendingExit exit = exits.head;
exits = exits.tail;
if (!(exit instanceof ThrownPendingExit)) {
Assert.check(exit.tree.hasTag(RETURN));
Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
} else {
// uncaught throws will be reported later
pendingExits.append(exit);
@ -1126,7 +1149,11 @@ public class Flow {
scan(c.pats);
scan(c.stats);
}
resolveBreaks(tree, prevPendingExits);
if (tree.hasTag(SWITCH_EXPRESSION)) {
resolveYields(tree, prevPendingExits);
} else {
resolveBreaks(tree, prevPendingExits);
}
}
public void visitTry(JCTry tree) {
@ -1267,8 +1294,11 @@ public class Flow {
}
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak())
scan(tree.value);
recordExit(new PendingExit(tree));
}
public void visitYield(JCYield tree) {
scan(tree.value);
recordExit(new PendingExit(tree));
}
@ -1357,7 +1387,8 @@ public class Flow {
PendingExit exit = exits.head;
exits = exits.tail;
if (!(exit instanceof ThrownPendingExit)) {
Assert.check(exit.tree.hasTag(RETURN));
Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
} else {
// uncaught throws will be reported later
pendingExits.append(exit);
@ -1977,7 +2008,9 @@ public class Flow {
while (exits.nonEmpty()) {
PendingExit exit = exits.head;
exits = exits.tail;
Assert.check(exit.tree.hasTag(RETURN), exit.tree);
Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()),
exit.tree);
if (isInitialConstructor) {
Assert.check(exit instanceof AssignPendingExit);
inits.assign(((AssignPendingExit) exit).exit_inits);
@ -2232,7 +2265,11 @@ public class Flow {
inits.andSet(initsSwitch);
}
}
resolveBreaks(tree, prevPendingExits);
if (tree.hasTag(SWITCH_EXPRESSION)) {
resolveYields(tree, prevPendingExits);
} else {
resolveBreaks(tree, prevPendingExits);
}
nextadr = nextadrPrev;
}
// where
@ -2397,37 +2434,39 @@ public class Flow {
@Override
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) {
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
if (expr.type.hasTag(BOOLEAN)) {
scanCond(tree.value);
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
PendingExit exit = new PendingExit(tree) {
@Override
void resolveJump() {
if (!inits.isReset()) {
split(true);
}
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
}
};
merge();
recordExit(exit);
return ;
}
}
scan(tree.value);
}
recordExit(new AssignPendingExit(tree, inits, uninits));
}
@Override
public void visitYield(JCYield tree) {
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
if (expr != null && expr.type.hasTag(BOOLEAN)) {
scanCond(tree.value);
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
PendingExit exit = new PendingExit(tree) {
@Override
void resolveJump() {
if (!inits.isReset()) {
split(true);
}
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
}
};
merge();
recordExit(exit);
return ;
} else {
scan(tree.value);
recordExit(new AssignPendingExit(tree, inits, uninits));
}
}
@Override
public void visitContinue(JCContinue tree) {
recordExit(new AssignPendingExit(tree, inits, uninits));
@ -2788,9 +2827,8 @@ public class Flow {
}
@Override
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak())
scan(tree.value);
public void visitYield(JCYield tree) {
scan(tree.value);
}
public void visitModuleDef(JCModuleDecl tree) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -272,9 +272,8 @@ public class Lower extends TreeTranslator {
}
@Override
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak())
scan(tree.value);
public void visitYield(JCYield tree) {
scan(tree.value);
}
}
@ -1887,7 +1886,7 @@ public class Lower extends TreeTranslator {
ClassSymbol c = types.boxedClass(type);
Symbol typeSym =
rs.accessBase(
rs.findIdentInType(attrEnv, c.type, names.TYPE, KindSelector.VAR),
rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR),
pos, c.type, names.TYPE, true);
if (typeSym.kind == VAR)
((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
@ -3224,6 +3223,11 @@ public class Lower extends TreeTranslator {
if (tree.target == src)
tree.target = dest;
}
public void visitYield(JCYield tree) {
if (tree.target == src)
tree.target = dest;
scan(tree.value);
}
public void visitContinue(JCContinue tree) {
if (tree.target == src)
tree.target = dest;
@ -3676,9 +3680,12 @@ public class Lower extends TreeTranslator {
@Override
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) {
tree.value = translate(tree.value, tree.target.type);
}
result = tree;
}
@Override
public void visitYield(JCYield tree) {
tree.value = translate(tree.value, tree.target.type);
result = tree;
}

@ -245,7 +245,7 @@ public class MemberEnter extends JCTree.Visitor {
tree.sym.type.getReturnType());
}
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
localEnv.info.breakResult = null;
localEnv.info.yieldResult = null;
return localEnv;
}

@ -43,6 +43,7 @@ import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
@ -52,6 +53,7 @@ import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
import com.sun.tools.javac.util.JCDiagnostic.Warning;
import java.util.Arrays;
import java.util.Collection;
@ -63,6 +65,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
@ -105,6 +108,7 @@ public class Resolve {
public final boolean checkVarargsAccessAfterResolution;
private final boolean compactMethodDiags;
private final boolean allowLocalVariableTypeInference;
private final boolean allowYieldStatement;
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
WriteableScope polymorphicSignatureScope;
@ -128,6 +132,7 @@ public class Resolve {
moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
Preview preview = Preview.instance(context);
Source source = Source.instance(context);
Options options = Options.instance(context);
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
@ -136,6 +141,8 @@ public class Resolve {
Target target = Target.instance(context);
allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source);
allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
Feature.SWITCH_EXPRESSION.allowedInSource(source);
checkVarargsAccessAfterResolution =
Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
@ -2330,13 +2337,15 @@ public class Resolve {
}
/** Find an unqualified identifier which matches a specified kind set.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP, PCK).
*/
Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) {
return checkVarType(findIdentInternal(env, name, kind), name);
Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
return checkRestrictedType(pos, findIdentInternal(env, name, kind), name);
}
Symbol findIdentInternal(Env<AttrContext> env, Name name, KindSelector kind) {
@ -2362,14 +2371,17 @@ public class Resolve {
}
/** Find an identifier in a package which matches a specified kind set.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a nonempty subset of TYP, PCK).
*/
Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck,
Symbol findIdentInPackage(DiagnosticPosition pos,
Env<AttrContext> env, TypeSymbol pck,
Name name, KindSelector kind) {
return checkVarType(findIdentInPackageInternal(env, pck, name, kind), name);
return checkRestrictedType(pos, findIdentInPackageInternal(env, pck, name, kind), name);
}
Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck,
@ -2395,15 +2407,18 @@ public class Resolve {
}
/** Find an identifier among the members of a given type `site'.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment.
* @param site The type containing the symbol to be found.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP).
*/
Symbol findIdentInType(Env<AttrContext> env, Type site,
Symbol findIdentInType(DiagnosticPosition pos,
Env<AttrContext> env, Type site,
Name name, KindSelector kind) {
return checkVarType(findIdentInTypeInternal(env, site, name, kind), name);
return checkRestrictedType(pos, findIdentInTypeInternal(env, site, name, kind), name);
}
Symbol findIdentInTypeInternal(Env<AttrContext> env, Type site,
@ -2424,10 +2439,17 @@ public class Resolve {
return bestSoFar;
}
private Symbol checkVarType(Symbol bestSoFar, Name name) {
if (allowLocalVariableTypeInference && name.equals(names.var) &&
(bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP)) {
bestSoFar = new BadVarTypeError();
private Symbol checkRestrictedType(DiagnosticPosition pos, Symbol bestSoFar, Name name) {
if (bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP) {
if (allowLocalVariableTypeInference && name.equals(names.var)) {
bestSoFar = new BadRestrictedTypeError(names.var);
} else if (name.equals(names.yield)) {
if (allowYieldStatement) {
bestSoFar = new BadRestrictedTypeError(names.yield);
} else if (pos != null) {
log.warning(pos, Warnings.IllegalRefToRestrictedType(names.yield));
}
}
}
return bestSoFar;
}
@ -2597,7 +2619,7 @@ public class Resolve {
Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
Name name, KindSelector kind) {
return accessBase(
findIdent(env, name, kind),
findIdent(pos, env, name, kind),
pos, env.enclClass.sym.type, name, false);
}
@ -3833,14 +3855,16 @@ public class Resolve {
}
}
class BadVarTypeError extends ResolveError {
BadVarTypeError() {
super(Kind.BAD_VAR, "bad var use");
class BadRestrictedTypeError extends ResolveError {
private final Name typeName;
BadRestrictedTypeError(Name typeName) {
super(Kind.BAD_RESTRICTED_TYPE, "bad var use");
this.typeName = typeName;
}
@Override
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.var.type");
return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.restricted.type", typeName);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -620,11 +620,14 @@ public class TransTypes extends TreeTranslator {
@Override
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) {
tree.value = translate(tree.value, erasure(tree.value.type));
tree.value.type = erasure(tree.value.type);
tree.value = retype(tree.value, tree.value.type, pt);
}
result = tree;
}
@Override
public void visitYield(JCYield tree) {
tree.value = translate(tree.value, erasure(tree.value.type));
tree.value.type = erasure(tree.value.type);
tree.value = retype(tree.value, tree.value.type, pt);
result = tree;
}

@ -71,6 +71,7 @@ import com.sun.tools.javac.tree.JCTree.JCProvides;
import com.sun.tools.javac.tree.JCTree.JCRequires;
import com.sun.tools.javac.tree.JCTree.JCReturn;
import com.sun.tools.javac.tree.JCTree.JCSwitch;
import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
import com.sun.tools.javac.tree.JCTree.JCSynchronized;
import com.sun.tools.javac.tree.JCTree.JCThrow;
import com.sun.tools.javac.tree.JCTree.JCTry;
@ -84,6 +85,7 @@ import com.sun.tools.javac.tree.JCTree.JCUses;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
import com.sun.tools.javac.tree.JCTree.JCYield;
import com.sun.tools.javac.tree.JCTree.LetExpr;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
import com.sun.tools.javac.tree.TreeInfo;
@ -259,6 +261,12 @@ public class TreeDiffer extends TreeScanner {
@Override
public void visitBreak(JCBreak tree) {
JCBreak that = (JCBreak) parameter;
result = tree.label == that.label;
}
@Override
public void visitYield(JCYield tree) {
JCYield that = (JCYield) parameter;
result = scan(tree.value, that.value);
}
@ -498,6 +506,12 @@ public class TreeDiffer extends TreeScanner {
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
}
@Override
public void visitSwitchExpression(JCSwitchExpression tree) {
JCSwitchExpression that = (JCSwitchExpression) parameter;
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
}
@Override
public void visitSynchronized(JCSynchronized tree) {
JCSynchronized that = (JCSynchronized) parameter;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -377,6 +377,11 @@ implements CRTFlags {
result = sr;
}
public void visitYield(JCYield tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitContinue(JCContinue tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;

@ -1716,47 +1716,49 @@ public class Gen extends JCTree.Visitor {
}
public void visitBreak(JCBreak tree) {
Assert.check(code.isStatementStart());
final Env<GenContext> targetEnv = unwindBreak(tree.target);
targetEnv.info.addExit(code.branch(goto_));
endFinalizerGaps(env, targetEnv);
}
public void visitYield(JCYield tree) {
Assert.check(code.isStatementStart());
final Env<GenContext> targetEnv;
if (tree.isValueBreak()) {
//restore stack as it was before the switch expression:
for (LocalItem li : stackBeforeSwitchExpression) {
li.load();
}
if (inCondSwitchExpression) {
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
Chain falseJumps = value.jumpFalse();
targetEnv = unwindBreak(tree);
code.resolve(value.trueJumps);
Chain trueJumps = code.branch(goto_);
if (switchExpressionTrueChain == null) {
switchExpressionTrueChain = trueJumps;
} else {
switchExpressionTrueChain =
Code.mergeChains(switchExpressionTrueChain, trueJumps);
}
if (switchExpressionFalseChain == null) {
switchExpressionFalseChain = falseJumps;
} else {
switchExpressionFalseChain =
Code.mergeChains(switchExpressionFalseChain, falseJumps);
}
//restore stack as it was before the switch expression:
for (LocalItem li : stackBeforeSwitchExpression) {
li.load();
}
if (inCondSwitchExpression) {
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
Chain falseJumps = value.jumpFalse();
targetEnv = unwindBreak(tree.target);
code.resolve(value.trueJumps);
Chain trueJumps = code.branch(goto_);
if (switchExpressionTrueChain == null) {
switchExpressionTrueChain = trueJumps;
} else {
genExpr(tree.value, pt).load();
code.state.forceStackTop(tree.target.type);
targetEnv = unwindBreak(tree);
targetEnv.info.addExit(code.branch(goto_));
switchExpressionTrueChain =
Code.mergeChains(switchExpressionTrueChain, trueJumps);
}
if (switchExpressionFalseChain == null) {
switchExpressionFalseChain = falseJumps;
} else {
switchExpressionFalseChain =
Code.mergeChains(switchExpressionFalseChain, falseJumps);
}
} else {
targetEnv = unwindBreak(tree);
genExpr(tree.value, pt).load();
code.state.forceStackTop(tree.target.type);
targetEnv = unwindBreak(tree.target);
targetEnv.info.addExit(code.branch(goto_));
}
endFinalizerGaps(env, targetEnv);
}
//where:
private Env<GenContext> unwindBreak(JCBreak tree) {
private Env<GenContext> unwindBreak(JCTree target) {
int tmpPos = code.pendingStatPos;
Env<GenContext> targetEnv = unwind(tree.target, env);
Env<GenContext> targetEnv = unwind(target, env);
code.pendingStatPos = tmpPos;
return targetEnv;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -182,6 +182,8 @@ public class JavacParser implements Parser {
this.keepLineMap = keepLineMap;
this.errorTree = F.Erroneous();
endPosTable = newEndPosTable(keepEndPositions);
this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
Feature.SWITCH_EXPRESSION.allowedInSource(source);
}
protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
@ -211,6 +213,10 @@ public class JavacParser implements Parser {
*/
boolean allowThisIdent;
/** Switch: is yield statement allowed in this source level?
*/
boolean allowYieldStatement;
/** The type of the method receiver, as specified by a first "this" parameter.
*/
JCVariableDecl receiverParam;
@ -769,9 +775,10 @@ public class JavacParser implements Parser {
public JCExpression unannotatedType(boolean allowVar) {
JCExpression result = term(TYPE);
Name restrictedTypeName;
if (!allowVar && isRestrictedLocalVarTypeName(result, true)) {
syntaxError(result.pos, Errors.VarNotAllowedHere);
if (!allowVar && (restrictedTypeName = restrictedTypeName(result, true)) != null) {
syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
}
return result;
@ -1377,6 +1384,7 @@ public class JavacParser implements Parser {
break;
case SWITCH:
checkSourceLevel(Feature.SWITCH_EXPRESSION);
allowYieldStatement = true;
int switchPos = token.pos;
nextToken();
JCExpression selector = parExpression();
@ -1436,7 +1444,7 @@ public class JavacParser implements Parser {
kind = JCCase.RULE;
} else {
JCExpression value = parseExpression();
stats = List.of(to(F.at(value).Break(value)));
stats = List.of(to(F.at(value).Yield(value)));
body = value;
kind = JCCase.RULE;
accept(SEMI);
@ -1607,7 +1615,7 @@ public class JavacParser implements Parser {
int depth = 0;
boolean type = false;
ParensResult defaultResult = ParensResult.PARENS;
outer: for (int lookahead = 0 ; ; lookahead++) {
outer: for (int lookahead = 0; ; lookahead++) {
TokenKind tk = S.token(lookahead).kind;
switch (tk) {
case COMMA:
@ -1782,12 +1790,13 @@ public class JavacParser implements Parser {
if (explicitParams) {
LambdaClassifier lambdaClassifier = new LambdaClassifier();
for (JCVariableDecl param: params) {
Name restrictedTypeName;
if (param.vartype != null &&
isRestrictedLocalVarTypeName(param.vartype, false) &&
(restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
param.vartype.hasTag(TYPEARRAY)) {
log.error(DiagnosticFlag.SYNTAX, param.pos,
Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
? Errors.VarNotAllowedArray : Errors.VarNotAllowedHere);
? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
}
lambdaClassifier.addParameter(param);
if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
@ -1799,7 +1808,7 @@ public class JavacParser implements Parser {
}
for (JCVariableDecl param: params) {
if (param.vartype != null
&& isRestrictedLocalVarTypeName(param.vartype, true)) {
&& restrictedTypeName(param.vartype, true) != null) {
checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
param.startPos = TreeInfo.getStartPos(param.vartype);
param.vartype = null;
@ -1837,7 +1846,7 @@ public class JavacParser implements Parser {
void addParameter(JCVariableDecl param) {
if (param.vartype != null && param.name != names.empty) {
if (isRestrictedLocalVarTypeName(param.vartype, false)) {
if (restrictedTypeName(param.vartype, false) != null) {
reduce(LambdaParameterKind.VAR);
} else {
reduce(LambdaParameterKind.EXPLICIT);
@ -1944,10 +1953,27 @@ public class JavacParser implements Parser {
return args.toList();
}
JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
int pos = token.pos;
List<JCExpression> args = arguments();
return toP(F.at(pos).Apply(typeArgs, t, args));
JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
((JCIdent) t).name)) {
log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
mi = F.Erroneous(List.of(mi));
}
return toP(mi);
}
boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
if (name == names.yield) {
if (allowYieldStatement) {
return true;
} else {
log.warning(pos, Warnings.InvalidYield);
}
}
return false;
}
/** TypeArgumentsOpt = [ TypeArguments ]
@ -2506,6 +2532,7 @@ public class JavacParser implements Parser {
/**This method parses a statement appearing inside a block.
*/
@SuppressWarnings("fallthrough")
List<JCStatement> blockStatement() {
//todo: skip to anchor on error(?)
int pos = token.pos;
@ -2543,6 +2570,52 @@ public class JavacParser implements Parser {
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
dc = token.comment(CommentStyle.JAVADOC);
return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
case IDENTIFIER:
if (token.name() == names.yield && allowYieldStatement) {
Token next = S.token(1);
boolean isYieldStatement;
switch (next.kind) {
case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
case NULL: case IDENTIFIER: case TRUE: case FALSE:
case NEW: case SWITCH: case THIS: case SUPER:
isYieldStatement = true;
break;
case PLUSPLUS: case SUBSUB:
isYieldStatement = S.token(2).kind != SEMI;
break;
case LPAREN:
int lookahead = 2;
int balance = 1;
boolean hasComma = false;
Token l;
while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
switch (l.kind) {
case LPAREN: balance++; break;
case RPAREN: balance--; break;
case COMMA: if (balance == 1) hasComma = true; break;
}
lookahead++;
}
isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
break;
case SEMI: //error recovery - this is not a valid statement:
isYieldStatement = true;
break;
default:
isYieldStatement = false;
break;
}
if (isYieldStatement) {
nextToken();
JCExpression t = term(EXPR);
accept(SEMI);
return List.of(toP(F.at(pos).Yield(t)));
}
//else intentional fall-through
}
default:
Token prevToken = token;
JCExpression t = term(EXPR | TYPE);
@ -2702,9 +2775,9 @@ public class JavacParser implements Parser {
}
case BREAK: {
nextToken();
JCExpression value = token.kind == SEMI ? null : parseExpression();
Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
accept(SEMI);
JCBreak t = toP(F.at(pos).Break(value));
JCBreak t = toP(F.at(pos).Break(label));
return t;
}
case CONTINUE: {
@ -3181,14 +3254,14 @@ public class JavacParser implements Parser {
int startPos = Position.NOPOS;
if (elemType.hasTag(IDENT)) {
Name typeName = ((JCIdent)elemType).name;
if (isRestrictedLocalVarTypeName(typeName, pos, !compound && localDecl)) {
if (isRestrictedTypeName(typeName, pos, !compound && localDecl)) {
if (type.hasTag(TYPEARRAY) && !compound) {
//error - 'var' and arrays
reportSyntaxError(pos, Errors.VarNotAllowedArray);
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedArray(typeName));
} else {
if(compound)
//error - 'var' in compound local var decl
reportSyntaxError(pos, Errors.VarNotAllowedCompound);
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
startPos = TreeInfo.getStartPos(mods);
if (startPos == Position.NOPOS)
startPos = TreeInfo.getStartPos(type);
@ -3204,23 +3277,30 @@ public class JavacParser implements Parser {
return result;
}
boolean isRestrictedLocalVarTypeName(JCExpression e, boolean shouldWarn) {
Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
switch (e.getTag()) {
case IDENT:
return isRestrictedLocalVarTypeName(((JCIdent)e).name, e.pos, shouldWarn);
return isRestrictedTypeName(((JCIdent)e).name, e.pos, shouldWarn) ? ((JCIdent)e).name : null;
case TYPEARRAY:
return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
default:
return false;
return null;
}
}
boolean isRestrictedLocalVarTypeName(Name name, int pos, boolean shouldWarn) {
boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
if (name == names.var) {
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
return true;
} else if (shouldWarn) {
log.warning(pos, Warnings.VarNotAllowed);
log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
}
}
if (name == names.yield) {
if (allowYieldStatement) {
return true;
} else if (shouldWarn) {
log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
}
}
return false;
@ -3614,8 +3694,8 @@ public class JavacParser implements Parser {
Name typeName() {
int pos = token.pos;
Name name = ident();
if (isRestrictedLocalVarTypeName(name, pos, true)) {
reportSyntaxError(pos, Errors.VarNotAllowed);
if (isRestrictedTypeName(name, pos, true)) {
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
}
return name;
}

@ -188,17 +188,14 @@ compiler.err.bad.initializer=\
compiler.err.break.outside.switch.loop=\
break outside switch or loop
compiler.err.break.missing.value=\
missing break value
compiler.err.break.outside.switch.expression=\
break outside of enclosing switch expression
attempt to break out of a switch expression
compiler.err.continue.outside.switch.expression=\
continue outside of enclosing switch expression
attempt to continue out of a switch expression
compiler.err.return.outside.switch.expression=\
return outside of enclosing switch expression
attempt to return out of a switch expression
compiler.err.rule.completes.normally=\
switch rule completes without providing a value\n\
@ -208,17 +205,20 @@ compiler.err.switch.expression.completes.normally=\
switch expression completes without providing a value\n\
(switch expressions must either provide a value or throw for all possible input values)
# 0: name
compiler.err.break.ambiguous.target=\
ambiguous reference to ''{0}''\n\
(''{0}'' is both a label and an expression)
compiler.err.no.switch.expression =\
yield outside of switch expression
# 0: tree tag
compiler.err.break.expr.not.immediate=\
value break not supported in ''{0}''
compiler.err.no.switch.expression.qualify=\
yield outside of switch expression\n\
(to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.err.break.complex.value.no.switch.expression=\
unexpected value break
compiler.err.invalid.yield=\
invalid use of a restricted identifier ''yield''\n\
(to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.warn.invalid.yield=\
''yield'' may become a restricted identifier in a future release\n\
(to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.err.switch.expression.empty=\
switch expression does not have any case clauses
@ -1267,29 +1267,43 @@ compiler.err.io.exception=\
compiler.err.undef.label=\
undefined label: {0}
compiler.err.illegal.ref.to.var.type=\
illegal reference to restricted type ''var''
# 0: name
compiler.err.illegal.ref.to.restricted.type=\
illegal reference to restricted type ''{0}''
compiler.err.var.not.allowed=\
''var'' not allowed here\n\
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations
# 0: name
compiler.warn.illegal.ref.to.restricted.type=\
illegal reference to restricted type ''{0}''
compiler.warn.var.not.allowed=\
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations or as the element type of an array
# 0: name, 1: source
compiler.err.restricted.type.not.allowed=\
''{0}'' not allowed here\n\
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations
# 0: name, 1: source
compiler.warn.restricted.type.not.allowed=\
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations or as the element type of an array
# 0: name, 1: source
compiler.warn.restricted.type.not.allowed.preview=\
''{0}'' may become a restricted type name in a future release and may be unusable for type declarations or as the element type of an array
# 0: name (variable), 1: message segment
compiler.err.cant.infer.local.var.type=\
cannot infer type for local variable {0}\n\
({1})
compiler.err.var.not.allowed.here=\
''var'' is not allowed here
# 0: name
compiler.err.restricted.type.not.allowed.here=\
''{0}'' is not allowed here
compiler.err.var.not.allowed.array=\
''var'' is not allowed as an element type of an array
# 0: name
compiler.err.restricted.type.not.allowed.array=\
''{0}'' is not allowed as an element type of an array
compiler.err.var.not.allowed.compound=\
''var'' is not allowed in a compound declaration
# 0: name
compiler.err.restricted.type.not.allowed.compound=\
''{0}'' is not allowed in a compound declaration
# 0: fragment
compiler.err.invalid.lambda.parameter.declaration=\
@ -2666,22 +2680,6 @@ compiler.misc.kindname.static.init=\
compiler.misc.kindname.instance.init=\
instance initializer
# the following are names of tree kinds:
compiler.misc.tree.tag.forloop=\
for
compiler.misc.tree.tag.foreachloop=\
for
compiler.misc.tree.tag.whileloop=\
while
compiler.misc.tree.tag.doloop=\
do
compiler.misc.tree.tag.switch=\
switch
#####
compiler.misc.no.args=\

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -187,6 +187,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
BREAK,
/** Yield statements, of type Yield.
*/
YIELD,
/** Continue statements, of type Continue.
*/
CONTINUE,
@ -1551,10 +1555,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
* A break from a loop or switch.
*/
public static class JCBreak extends JCStatement implements BreakTree {
public JCExpression value;
public Name label;
public JCTree target;
protected JCBreak(JCExpression value, JCTree target) {
this.value = value;
protected JCBreak(Name label, JCTree target) {
this.label = label;
this.target = target;
}
@Override
@ -1567,11 +1571,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Kind getKind() { return Kind.BREAK; }
@DefinedBy(Api.COMPILER_TREE)
public Name getLabel() {
return value != null && value.getKind() == Kind.IDENTIFIER ? ((JCIdent) value).getName() : null;
return label;
}
@DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
public JCExpression getValue() { return value; }
@Override @DefinedBy(Api.COMPILER_TREE)
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitBreak(this, d);
@ -1582,6 +1583,33 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
/**
* A break-with from a switch expression.
*/
@SuppressWarnings("removal")
public static class JCYield extends JCStatement implements YieldTree {
public JCExpression value;
public JCTree target;
protected JCYield(JCExpression value, JCTree target) {
this.value = value;
this.target = target;
}
@Override
public void accept(Visitor v) { v.visitYield(this); }
@DefinedBy(Api.COMPILER_TREE)
public Kind getKind() { return Kind.YIELD; }
@DefinedBy(Api.COMPILER_TREE)
public JCExpression getValue() { return value; }
@Override @DefinedBy(Api.COMPILER_TREE)
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitYield(this, d);
}
@Override
public Tag getTag() {
return YIELD;
}
}
/**
* A continue of a loop.
*/
@ -3091,7 +3119,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
JCExpression elsepart);
JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart);
JCExpressionStatement Exec(JCExpression expr);
JCBreak Break(JCExpression value);
JCBreak Break(Name label);
JCYield Yield(JCExpression value);
JCContinue Continue(Name label);
JCReturn Return(JCExpression expr);
JCThrow Throw(JCExpression expr);
@ -3162,6 +3191,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitIf(JCIf that) { visitTree(that); }
public void visitExec(JCExpressionStatement that) { visitTree(that); }
public void visitBreak(JCBreak that) { visitTree(that); }
public void visitYield(JCYield that) { visitTree(that); }
public void visitContinue(JCContinue that) { visitTree(that); }
public void visitReturn(JCReturn that) { visitTree(that); }
public void visitThrow(JCThrow that) { visitTree(that); }

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -982,7 +982,18 @@ public class Pretty extends JCTree.Visitor {
public void visitBreak(JCBreak tree) {
try {
print("break");
if (tree.value != null) print(" " + tree.value);
if (tree.label != null) print(" " + tree.label);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitYield(JCYield tree) {
try {
print("yield");
print(" ");
printExpr(tree.value);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -140,8 +140,15 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
@DefinedBy(Api.COMPILER_TREE)
public JCTree visitBreak(BreakTree node, P p) {
JCBreak t = (JCBreak) node;
return M.at(t.pos).Break(t.label);
}
@DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
public JCTree visitYield(YieldTree node, P p) {
JCYield t = (JCYield) node;
JCExpression value = copy(t.value, p);
return M.at(t.pos).Break(value);
return M.at(t.pos).Yield(value);
}
@DefinedBy(Api.COMPILER_TREE)

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -333,12 +333,18 @@ public class TreeMaker implements JCTree.Factory {
return tree;
}
public JCBreak Break(JCExpression label) {
public JCBreak Break(Name label) {
JCBreak tree = new JCBreak(label, null);
tree.pos = pos;
return tree;
}
public JCYield Yield(JCExpression value) {
JCYield tree = new JCYield(value, null);
tree.pos = pos;
return tree;
}
public JCContinue Continue(Name label) {
JCContinue tree = new JCContinue(label, null);
tree.pos = pos;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -219,6 +219,9 @@ public class TreeScanner extends Visitor {
}
public void visitBreak(JCBreak tree) {
}
public void visitYield(JCYield tree) {
scan(tree.value);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -258,8 +258,11 @@ public class TreeTranslator extends JCTree.Visitor {
}
public void visitBreak(JCBreak tree) {
if (tree.isValueBreak())
tree.value = translate(tree.value);
result = tree;
}
public void visitYield(JCYield tree) {
tree.value = translate(tree.value);
result = tree;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -554,6 +554,13 @@ public class Log extends AbstractLog {
}
}
/**Is an error reported at the given pos (inside the current source)?*/
public boolean hasErrorOn(DiagnosticPosition pos) {
JavaFileObject file = source != null ? source.fileObject : null;
return file != null && recorded.contains(new Pair<>(file, pos.getPreferredPosition()));
}
/** Prompt user after an error.
*/
public void prompt() {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,6 +70,7 @@ public class Names {
public final Name uses;
public final Name open;
public final Name with;
public final Name yield;
// field and method names
public final Name _name;
@ -219,6 +220,7 @@ public class Names {
uses = fromString("uses");
open = fromString("open");
with = fromString("with");
yield = fromString("yield");
// field and method names
_name = fromString("name");

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.var.not.allowed.array
// key: compiler.err.restricted.type.not.allowed.array
import java.util.function.*;

@ -1,65 +0,0 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.break.expr.not.immediate
// key: compiler.misc.tree.tag.doloop
// key: compiler.misc.tree.tag.foreachloop
// key: compiler.misc.tree.tag.forloop
// key: compiler.misc.tree.tag.switch
// key: compiler.misc.tree.tag.whileloop
// key: compiler.note.note
// key: compiler.err.error
// key: compiler.misc.count.error.plural
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// key: compiler.note.note
// options: --enable-preview -source ${jdk.version}
// run: backdoor
class BreakExprNotImmediate {
int t(int i) {
return switch (i) {
case 0:
for (; ;) {
break 1 + 1;
}
case 1:
for (String s : new String[0]) {
break 1 + 1;
}
case 2:
while (true) {
break 1 + 1;
}
case 3:
do {
break 1 + 1;
} while (true);
case 4:
switch (i) {
default: break 1 + 1;
}
break 0;
};
}
}

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.warn.var.not.allowed
// key: compiler.warn.restricted.type.not.allowed
// options: --release 9
class var { }

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.warn.illegal.ref.to.restricted.type
// key: compiler.warn.restricted.type.not.allowed.preview
class IllegalRefToVarType {
yield list() { return null; }
public class yield {}
}

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.illegal.ref.to.var.type
// key: compiler.err.illegal.ref.to.restricted.type
import java.util.List;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -21,16 +21,14 @@
* questions.
*/
// key: compiler.err.break.ambiguous.target
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: --enable-preview -source ${jdk.version}
// key: compiler.err.invalid.yield
// options: --enable-preview --source 13
class BreakAmbiguousTarget {
void m(int i, int j) {
j: print(switch (i) {
default: break j;
});
class BreakComplexValueNoSwitchExpressions {
void t() {
while (true) {
yield(1, 2);
}
}
void print(int i) { }
private void yield(int i, int j) {}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -21,12 +21,14 @@
* questions.
*/
// key: compiler.err.break.complex.value.no.switch.expression
// key: compiler.warn.invalid.yield
// options: --source 13
class BreakComplexValueNoSwitchExpressions {
void t() {
while (true) {
break 1 + 1;
yield(1, 2);
}
}
private void yield(int i, int j) {}
}

@ -21,15 +21,13 @@
* questions.
*/
// key: compiler.err.break.missing.value
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: --enable-preview -source ${jdk.version}
// key: compiler.err.no.switch.expression
// options: --enable-preview --source 13
class BreakMissingValue {
int t(int i) {
return switch (i) {
default: break;
};
class BreakComplexValueNoSwitchExpressions {
void t() {
while (true) {
yield 1 + 1;
}
}
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.no.switch.expression.qualify
// options: --enable-preview --source 13
class BreakComplexValueNoSwitchExpressions {
void t() {
while (true) {
yield(1 + 1);
}
}
private void yield(int i) {}
}

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.warn.restricted.type.not.allowed.preview
class yield { }

@ -28,7 +28,7 @@
class SwitchExpressions {
int m(int i) {
return switch (i) {
default: break -1;
default: yield -1;
};
}
}

@ -21,6 +21,6 @@
* questions.
*/
// key: compiler.err.var.not.allowed
// key: compiler.err.restricted.type.not.allowed
class var { }

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.var.not.allowed.array
// key: compiler.err.restricted.type.not.allowed.array
class VarNotAllowedArray {
void test(String[] s) {

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.var.not.allowed.compound
// key: compiler.err.restricted.type.not.allowed.compound
class VarNotAllowedCompound {
void test() {

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.var.not.allowed.here
// key: compiler.err.restricted.type.not.allowed.here
class VarNotAllowedField {
var s = "";

@ -48,11 +48,12 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
private static final String INT_ESWITCH_DEFAULT = "int res = switch (x) { default -> { # } };";
private static final String IF = "if (cond) { # } else throw new RuntimeException();";
private static final String BLOCK = "{ # }";
private static final String BREAK_Z = "break 0;";
private static final String BREAK_S = "break \"hello world\";";
private static final String BREAK_INT_FN = "break () -> 0 ;";
private static final String YIELD_Z = "yield 0;";
private static final String YIELD_S = "yield \"hello world\";";
private static final String YIELD_INT_FN = "yield () -> 0 ;";
private static final String BREAK_N = "break;";
private static final String BREAK_L = "break label;";
private static final String YIELD_L = "yield label;";
private static final String RETURN_Z = "return 0;";
private static final String RETURN_N = "return;";
private static final String RETURN_S = "return \"Hello\";";
@ -136,11 +137,11 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
assertOK(RUNNABLE, NOTHING);
assertOK(INT_FN, RETURN_Z);
assertFail("compiler.err.break.outside.switch.loop", RUNNABLE, BREAK_N);
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_S);
assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_Z);
assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_S);
assertFail("compiler.err.break.outside.switch.loop", INT_FN, BREAK_N);
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_S);
assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_Z);
assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_S);
assertFail("compiler.err.cont.outside.loop", RUNNABLE, CONTINUE_N);
assertFail("compiler.err.undef.label", RUNNABLE, BREAK_L);
assertFail("compiler.err.undef.label", RUNNABLE, CONTINUE_L);
@ -155,92 +156,94 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
public void testEswitch() {
//Int-valued switch expressions
assertOK(ESWITCH_Z, BREAK_Z);
assertOK(LABEL, BLOCK, ESWITCH_Z, BREAK_Z);
assertFail("compiler.err.break.missing.value", ESWITCH_Z, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_Z, BREAK_S);
assertFail("compiler.err.cant.resolve.location", ESWITCH_Z, BREAK_L);
assertOK(ESWITCH_Z, YIELD_Z);
assertOK(LABEL, BLOCK, ESWITCH_Z, YIELD_Z);
assertFail("compiler.err.break.outside.switch.expression", ESWITCH_Z, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_Z, YIELD_S);
assertFail("compiler.err.undef.label", ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.undef.label", ESWITCH_Z, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", ESWITCH_Z, CONTINUE_N);
assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_Z, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_Z);
assertOK(INT_ESWITCH_DEFAULT, BREAK_Z);
assertFail("compiler.err.break.missing.value", INT_ESWITCH_DEFAULT, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, BREAK_S);
assertFail("compiler.err.cant.resolve.location", INT_ESWITCH_DEFAULT, BREAK_L);
assertOK(INT_ESWITCH_DEFAULT, YIELD_Z);
assertFail("compiler.err.break.outside.switch.expression", INT_ESWITCH_DEFAULT, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, YIELD_S);
assertFail("compiler.err.undef.label", INT_ESWITCH_DEFAULT, BREAK_L);
// String-valued switch expressions
assertOK(ESWITCH_S, BREAK_S);
assertOK(LABEL, BLOCK, ESWITCH_S, BREAK_S);
assertFail("compiler.err.break.missing.value", ESWITCH_S, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_S, BREAK_Z);
assertFail("compiler.err.cant.resolve.location", ESWITCH_S, BREAK_L);
assertOK(ESWITCH_S, YIELD_S);
assertOK(LABEL, BLOCK, ESWITCH_S, YIELD_S);
assertFail("compiler.err.break.outside.switch.expression", ESWITCH_S, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_S, YIELD_Z);
assertFail("compiler.err.undef.label", ESWITCH_S, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_S, BREAK_L);
assertFail("compiler.err.undef.label", ESWITCH_S, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", ESWITCH_S, CONTINUE_N);
assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_S, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_S);
// Function-valued switch expression
assertOK(INT_FN_ESWITCH, BREAK_INT_FN);
assertFail("compiler.err.break.missing.value", INT_FN_ESWITCH, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_Z);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_S);
assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
assertFail("compiler.err.break.outside.switch.expression", INT_FN_ESWITCH, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_Z);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_S);
assertFail("compiler.err.cant.resolve.location", INT_FN_ESWITCH, BREAK_L);
assertFail("compiler.err.undef.label", INT_FN_ESWITCH, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, INT_FN_ESWITCH, BREAK_L);
assertFail("compiler.err.undef.label", INT_FN_ESWITCH, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", INT_FN_ESWITCH, CONTINUE_N);
assertFail("compiler.err.continue.outside.switch.expression", INT_FN_ESWITCH, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_S);
}
public void testNestedInExpSwitch() {
assertOK(ESWITCH_Z, IF, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, YIELD_Z);
//
assertOK(ESWITCH_Z, IF, IF, BREAK_Z);
assertOK(ESWITCH_Z, IF, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, IF, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, YIELD_Z);
//
assertOK(ESWITCH_Z, IF, IF, IF, BREAK_Z);
assertOK(ESWITCH_Z, IF, IF, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, IF, BLOCK, IF, BREAK_Z);
assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, IF, IF, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, BREAK_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, BREAK_Z);
assertOK(ESWITCH_Z, IF, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, YIELD_Z);
//
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, BREAK_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", ESWITCH_Z, INT_FN, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, SSWITCH, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, FOR, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, WHILE, IF, BREAK_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, DO, IF, BREAK_Z);
assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, FOR, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, WHILE, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, DO, YIELD_Z);
assertFail("compiler.err.no.switch.expression", ESWITCH_Z, INT_FN, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, FOR, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, WHILE, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, DO, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, SSWITCH, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, FOR, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, WHILE, IF, YIELD_Z);
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, DO, IF, YIELD_Z);
}
public void testBreakExpressionLabelDisambiguation() {
assertOK(DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.ambiguous.target", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, ESWITCH_Z, LABEL, FOR, BREAK_L); //label break
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L); //expression break
assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_L);
assertFail("compiler.err.undef.label", DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_Z, LABEL, FOR, BREAK_L); //label break
assertFail("compiler.err.break.outside.switch.expression", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L);
assertOK(DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, YIELD_L); //expression break
//
}
public void testFunReturningSwitchExp() {
assertOK(INT_FN_ESWITCH, BREAK_INT_FN);
assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
}
public void testContinueLoops() {

@ -160,6 +160,9 @@ public class Deduplication {
group((Consumer<Integer>) x -> Deduplication.this.f());
}
}
group((Function<Integer, Integer>) x -> switch (x) { default: yield x; },
(Function<Integer, Integer>) x -> switch (x) { default: yield x; });
}
void f() {}

@ -84,6 +84,7 @@ public class DeduplicationTest {
Listener diagnosticListener = new Listener();
Path testSrc = Paths.get(System.getProperty("test.src"));
Path file = testSrc.resolve("Deduplication.java");
String sourceVersion = Integer.toString(Runtime.version().feature());
JavacTask task =
javacTool.getTask(
null,
@ -93,7 +94,8 @@ public class DeduplicationTest {
"-d",
".",
"-XDdebug.dumpLambdaToMethodDeduplication",
"-XDdebug.dumpLambdaToMethodStats"),
"-XDdebug.dumpLambdaToMethodStats",
"--enable-preview", "-source", sourceVersion),
null,
fileManager.getJavaFileObjects(file));
Map<JCLambda, JCLambda> dedupedLambdas = new LinkedHashMap<>();
@ -192,6 +194,9 @@ public class DeduplicationTest {
(JCLambda) d.getDiagnosticPosition().getTree(),
(MethodSymbol) d.getArgs()[0]);
break;
case "compiler.note.preview.filename":
case "compiler.note.preview.recompile":
break; //ignore
default:
unexpected.add(diagnostic);
}

@ -782,6 +782,11 @@ public class DPrinter {
@Override
public void visitBreak(JCBreak tree) {
printName("label", tree.label);
}
@Override
public void visitYield(JCYield tree) {
printTree("value", tree.value);
}

@ -1,24 +1,24 @@
ParserTest.java:14:18: compiler.err.var.not.allowed
ParserTest.java:16:22: compiler.err.var.not.allowed
ParserTest.java:20:19: compiler.err.var.not.allowed
ParserTest.java:24:14: compiler.err.var.not.allowed
ParserTest.java:28:20: compiler.err.var.not.allowed
ParserTest.java:36:27: compiler.err.var.not.allowed
ParserTest.java:38:5: compiler.err.var.not.allowed.here
ParserTest.java:41:15: compiler.err.var.not.allowed.array
ParserTest.java:42:13: compiler.err.var.not.allowed.array
ParserTest.java:43:17: compiler.err.var.not.allowed.array
ParserTest.java:44:13: compiler.err.var.not.allowed.array
ParserTest.java:45:15: compiler.err.var.not.allowed.array
ParserTest.java:46:13: compiler.err.var.not.allowed.array
ParserTest.java:49:24: compiler.err.var.not.allowed.compound
ParserTest.java:54:5: compiler.err.var.not.allowed.here
ParserTest.java:58:16: compiler.err.var.not.allowed.here
ParserTest.java:59:14: compiler.err.var.not.allowed.here
ParserTest.java:60:24: compiler.err.var.not.allowed.here
ParserTest.java:61:22: compiler.err.var.not.allowed.here
ParserTest.java:63:22: compiler.err.var.not.allowed.here
ParserTest.java:64:18: compiler.err.var.not.allowed.here
ParserTest.java:68:35: compiler.err.var.not.allowed.here
ParserTest.java:69:22: compiler.err.var.not.allowed.here
ParserTest.java:14:18: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:16:22: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:20:19: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:24:14: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:28:20: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:36:27: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:38:5: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:41:15: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:42:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:43:17: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:44:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:45:15: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:46:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:49:24: compiler.err.restricted.type.not.allowed.compound: var
ParserTest.java:54:5: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:58:16: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:59:14: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:60:24: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:61:22: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:63:22: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:64:18: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:68:35: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:69:22: compiler.err.restricted.type.not.allowed.here: var
23 errors

@ -1,31 +1,31 @@
ParserTest.java:14:18: compiler.warn.var.not.allowed
ParserTest.java:16:22: compiler.warn.var.not.allowed
ParserTest.java:20:19: compiler.warn.var.not.allowed
ParserTest.java:24:14: compiler.warn.var.not.allowed
ParserTest.java:28:20: compiler.warn.var.not.allowed
ParserTest.java:36:27: compiler.warn.var.not.allowed
ParserTest.java:38:5: compiler.warn.var.not.allowed
ParserTest.java:41:15: compiler.warn.var.not.allowed
ParserTest.java:42:13: compiler.warn.var.not.allowed
ParserTest.java:43:17: compiler.warn.var.not.allowed
ParserTest.java:44:13: compiler.warn.var.not.allowed
ParserTest.java:45:15: compiler.warn.var.not.allowed
ParserTest.java:46:13: compiler.warn.var.not.allowed
ParserTest.java:47:23: compiler.warn.var.not.allowed
ParserTest.java:48:13: compiler.warn.var.not.allowed
ParserTest.java:49:13: compiler.warn.var.not.allowed
ParserTest.java:50:23: compiler.warn.var.not.allowed
ParserTest.java:51:23: compiler.warn.var.not.allowed
ParserTest.java:54:5: compiler.warn.var.not.allowed
ParserTest.java:58:16: compiler.warn.var.not.allowed
ParserTest.java:59:14: compiler.warn.var.not.allowed
ParserTest.java:60:24: compiler.warn.var.not.allowed
ParserTest.java:61:22: compiler.warn.var.not.allowed
ParserTest.java:63:22: compiler.warn.var.not.allowed
ParserTest.java:63:40: compiler.warn.var.not.allowed
ParserTest.java:64:18: compiler.warn.var.not.allowed
ParserTest.java:68:35: compiler.warn.var.not.allowed
ParserTest.java:69:22: compiler.warn.var.not.allowed
ParserTest.java:73:24: compiler.warn.var.not.allowed
ParserTest.java:74:18: compiler.warn.var.not.allowed
30 warnings
ParserTest.java:14:18: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:16:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:20:19: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:24:14: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:28:20: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:36:27: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:38:5: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:41:15: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:42:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:43:17: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:44:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:45:15: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:46:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:47:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:48:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:49:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:50:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:51:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:54:5: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:58:16: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:59:14: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:60:24: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:61:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:63:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:63:40: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:64:18: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:68:35: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:69:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:73:24: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:74:18: compiler.warn.restricted.type.not.allowed: var, 10
30 warnings

@ -1,3 +1,3 @@
BadTypeReference.java:14:9: compiler.err.illegal.ref.to.var.type
BadTypeReference.java:15:21: compiler.err.illegal.ref.to.var.type
BadTypeReference.java:14:9: compiler.err.illegal.ref.to.restricted.type: var
BadTypeReference.java:15:21: compiler.err.illegal.ref.to.restricted.type: var
2 errors

@ -1083,12 +1083,12 @@ public class JavacParserTest extends TestCase {
" }" +
" int j = switch (i) {" +
" case 0 -> i + 1;" +
" case 1 -> { break i + 1; }" +
" case 1 -> { yield i + 1; }" +
" default -> throw new RuntimeException();" +
" };" +
" int k = switch (i) {" +
" case 0: break i + 1;" +
" case 1: { break i + 1; }" +
" case 0: yield i + 1;" +
" case 1: { yield i + 1; }" +
" default: throw new RuntimeException();" +
" };" +
" }" +
@ -1120,7 +1120,7 @@ public class JavacParserTest extends TestCase {
List<String> expectedSpans = List.of(
"i++;", "{ i++; }", "throw new RuntimeException();", "if (true) ;", "i++;",
"<null>", "<null>", "<null>", "<null>", "<null>",
"i + 1"/*TODO semicolon?*/, "{ break i + 1; }", "throw new RuntimeException();",
"i + 1"/*TODO semicolon?*/, "{ yield i + 1; }", "throw new RuntimeException();",
"<null>", "<null>", "<null>");
assertEquals("the error spans are not correct; actual:" + spans, expectedSpans, spans);
String toString = normalize(cut.toString());
@ -1162,19 +1162,19 @@ public class JavacParserTest extends TestCase {
" \n" +
" }\n" +
" int j = switch (i) {\n" +
" case 0 -> break i + 1;\n" +
" case 0 -> yield i + 1;\n" +
" case 1 -> {\n" +
" break i + 1;\n" +
" yield i + 1;\n" +
" }\n" +
" default -> throw new RuntimeException();\n" +
" };\n" +
" int k = switch (i) {\n" +
" case 0:\n" +
" break i + 1;\n" +
" yield i + 1;\n" +
" \n" +
" case 1:\n" +
" {\n" +
" break i + 1;\n" +
" yield i + 1;\n" +
" }\n" +
" \n" +
" default:\n" +

@ -54,7 +54,7 @@ public class BreakTest {
" int t2(Integer i) {" +
" return switch (i) {" +
" case null: break LABEL;" +
" default: break 2;" +
" default: yield 2;" +
" }" +
" }" +
"}";
@ -79,7 +79,7 @@ public class BreakTest {
}
}.scan(ct.parse(), null);
List<String> expected = Arrays.asList("LABEL", null, "LABEL", null);
List<String> expected = Arrays.asList("LABEL", null, "LABEL");
if (!expected.equals(labels)) {
throw new AssertionError("Unexpected labels found: " + labels);

@ -37,8 +37,8 @@ public class DefiniteAssignment1 {
int x;
boolean t1 = (b && switch(a) {
case 0: break (x = 1) == 1 || true;
default: break false;
case 0: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t1) {
@ -50,8 +50,8 @@ public class DefiniteAssignment1 {
int x;
boolean t1 = (b && switch(a) {
case 0: break (x = 1) == 1 || isTrue();
default: break false;
case 0: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t1) {
@ -63,8 +63,8 @@ public class DefiniteAssignment1 {
int x;
boolean t1a = (b && switch(a) {
case 0: break (x = 1) == 1;
default: break false;
case 0: yield (x = 1) == 1;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t1a) {
@ -76,8 +76,8 @@ public class DefiniteAssignment1 {
int x;
boolean t1b = (switch(a) {
case 0: break (x = 1) == 1;
default: break false;
case 0: yield (x = 1) == 1;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t1b) {
@ -89,8 +89,8 @@ public class DefiniteAssignment1 {
int x;
boolean t2 = !(b && switch(a) {
case 0: break (x = 1) == 1 || true;
default: break false;
case 0: yield (x = 1) == 1 || true;
default: yield false;
}) || x == 1;
if (!t2) {
@ -102,8 +102,8 @@ public class DefiniteAssignment1 {
int x;
boolean t2 = !(b && switch(a) {
case 0: break (x = 1) == 1 || isTrue();
default: break false;
case 0: yield (x = 1) == 1 || isTrue();
default: yield false;
}) || x == 1;
if (!t2) {
@ -115,8 +115,8 @@ public class DefiniteAssignment1 {
int x;
boolean t3 = !(switch(a) {
case 0: break (x = 1) == 1 || true;
default: break false;
case 0: yield (x = 1) == 1 || true;
default: yield false;
}) || x == 2;
if (t3) {
@ -128,8 +128,8 @@ public class DefiniteAssignment1 {
int x;
boolean t3 = !(switch(a) {
case 0: break (x = 1) == 1 || isTrue();
default: break false;
case 0: yield (x = 1) == 1 || isTrue();
default: yield false;
}) || x == 2;
if (t3) {
@ -141,7 +141,7 @@ public class DefiniteAssignment1 {
int x;
boolean t4 = (b && switch(a) {
case 0: break (x = 1) == 1 || true;
case 0: yield (x = 1) == 1 || true;
default: throw new IllegalStateException();
}) && x == 1; //x is definitelly assigned here
@ -155,7 +155,7 @@ public class DefiniteAssignment1 {
int x;
boolean t4 = (b && switch(a) {
case 0: break (x = 1) == 1 || isTrue();
case 0: yield (x = 1) == 1 || isTrue();
default: throw new IllegalStateException();
}) && x == 1; //x is definitelly assigned here
@ -170,8 +170,8 @@ public class DefiniteAssignment1 {
String s = "a";
boolean t5 = (switch(s) {
case "a": break (x = 1) == 1 || true;
default: break false;
case "a": yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t5) {
@ -185,8 +185,8 @@ public class DefiniteAssignment1 {
String s = "a";
boolean t5 = (switch(s) {
case "a": break (x = 1) == 1 || isTrue();
default: break false;
case "a": yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t5) {
@ -199,8 +199,8 @@ public class DefiniteAssignment1 {
E e = E.B;
boolean t6 = (switch(e) {
case B: break (x = 1) == 1 || true;
default: break false;
case B: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t6) {
@ -213,8 +213,8 @@ public class DefiniteAssignment1 {
E e = E.B;
boolean t6 = (switch(e) {
case B: break (x = 1) == 1 || isTrue();
default: break false;
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t6) {
@ -251,9 +251,9 @@ public class DefiniteAssignment1 {
E e = E.B;
boolean t8 = (switch(e) {
case A: x = 1; break true;
case B: break (x = 1) == 1 || true;
default: break false;
case A: x = 1; yield true;
case B: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t8) {
@ -266,9 +266,9 @@ public class DefiniteAssignment1 {
E e = E.B;
boolean t8 = (switch(e) {
case A: x = 1; break isTrue();
case B: break (x = 1) == 1 || isTrue();
default: break false;
case A: x = 1; yield isTrue();
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t8) {
@ -281,9 +281,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean t9 = (switch(e) {
case A: x = 1; break true;
case B: break (x = 1) == 1 || true;
default: break false;
case A: x = 1; yield true;
case B: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t9) {
@ -296,9 +296,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean t9 = (switch(e) {
case A: x = 1; break isTrue();
case B: break (x = 1) == 1 || isTrue();
default: break false;
case A: x = 1; yield isTrue();
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!t9) {
@ -311,9 +311,9 @@ public class DefiniteAssignment1 {
E e = E.C;
boolean tA = (switch(e) {
case A: x = 1; break true;
case B: break (x = 1) == 1 || true;
default: break false;
case A: x = 1; yield true;
case B: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (tA) {
@ -326,9 +326,9 @@ public class DefiniteAssignment1 {
E e = E.C;
boolean tA = (switch(e) {
case A: x = 1; break isTrue();
case B: break (x = 1) == 1 || isTrue();
default: break false;
case A: x = 1; yield isTrue();
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (tA) {
@ -341,9 +341,9 @@ public class DefiniteAssignment1 {
E e = E.C;
boolean tA = (switch(e) {
case A: x = 1; break true;
case B: break (x = 2) == 2 || true;
default: break false;
case A: x = 1; yield true;
case B: yield (x = 2) == 2 || true;
default: yield false;
}) || (x = 3) == 3; //x is definitelly unassigned here
if (x != 3) {
@ -356,9 +356,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean tA = (switch(e) {
case A: break isTrue() && (x = 1) == 1;
case B: break (x = 1) == 1 || isTrue();
default: break false;
case A: yield isTrue() && (x = 1) == 1;
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!tA) {
@ -371,9 +371,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean tA = (switch(e) {
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: break (x = 1) == 1 || true;
default: break false;
case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: yield (x = 1) == 1 || true;
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!tA) {
@ -386,9 +386,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean tA = (switch(e) {
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: break (x = 1) == 1 || isTrue();
default: break false;
case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: yield (x = 1) == 1 || isTrue();
default: yield false;
}) && x == 1; //x is definitelly assigned here
if (!tA) {
@ -416,9 +416,9 @@ public class DefiniteAssignment1 {
E e = E.A;
boolean tA = (switch(e) {
case A -> { x = 1; break true; }
case B -> { x = 1; break true; }
case C -> { x = 1; break true; }
case A -> { x = 1; yield true; }
case B -> { x = 1; yield true; }
case C -> { x = 1; yield true; }
}) && x == 1; //x is definitelly assigned here
if (!tA) {

@ -15,8 +15,8 @@ public class DefiniteAssignment2 {
int x;
t = (b && switch(a) {
case 0: break (x = 1) == 1 || true;
default: break false;
case 0: yield (x = 1) == 1 || true;
default: yield false;
}) || x == 1;
}
@ -24,8 +24,8 @@ public class DefiniteAssignment2 {
int x;
t = (switch(a) {
case 0: break (x = 1) == 1;
default: break false;
case 0: yield (x = 1) == 1;
default: yield false;
}) || x == 1;
}
@ -33,9 +33,9 @@ public class DefiniteAssignment2 {
int x;
t = (switch(a) {
case 0: x = 1; break true;
case 1: break (x = 1) == 1;
default: break false;
case 0: x = 1; yield true;
case 1: yield (x = 1) == 1;
default: yield false;
}) || x == 1;
}
@ -43,9 +43,9 @@ public class DefiniteAssignment2 {
int x;
t = (switch(a) {
case 0: break true;
case 1: break (x = 1) == 1;
default: break false;
case 0: yield true;
case 1: yield (x = 1) == 1;
default: yield false;
}) && x == 1;
}
@ -53,9 +53,9 @@ public class DefiniteAssignment2 {
int x;
t = (switch(a) {
case 0: break false;
case 1: break isTrue() || (x = 1) == 1;
default: break false;
case 0: yield false;
case 1: yield isTrue() || (x = 1) == 1;
default: yield false;
}) && x == 1;
}
@ -63,9 +63,9 @@ public class DefiniteAssignment2 {
int x;
t = (switch(a) {
case 0: break false;
case 1: break isTrue() ? true : (x = 1) == 1;
default: break false;
case 0: yield false;
case 1: yield isTrue() ? true : (x = 1) == 1;
default: yield false;
}) && x == 1;
}
@ -73,9 +73,9 @@ public class DefiniteAssignment2 {
final int x;
t = (switch(a) {
case 0: break false;
case 1: break isTrue() ? true : (x = 1) == 1;
default: break false;
case 0: yield false;
case 1: yield isTrue() ? true : (x = 1) == 1;
default: yield false;
}) && (x = 1) == 1;
}
}

@ -39,15 +39,15 @@ public class ExpressionSwitch {
private String print(T t) {
return switch (t) {
case A -> "A";
case B -> { break "B"; }
default -> { break "other"; }
case B -> { yield "B"; }
default -> { yield "other"; }
};
}
private String exhaustive1(T t) {
return switch (t) {
case A -> "A";
case B -> { break "B"; }
case B -> { yield "B"; }
case C -> "C";
case D -> "D";
};
@ -64,25 +64,25 @@ public class ExpressionSwitch {
private String scopesIsolated(T t) {
return switch (t) {
case A -> { String res = "A"; break res;}
case B -> { String res = "B"; break res;}
default -> { String res = "default"; break res;}
case A -> { String res = "A"; yield res;}
case B -> { String res = "B"; yield res;}
default -> { String res = "default"; yield res;}
};
}
private Supplier<String> lambdas1(T t) {
return switch (t) {
case A -> () -> "A";
case B -> { break () -> "B"; }
case B -> { yield () -> "B"; }
default -> () -> "default";
};
}
private Supplier<String> lambdas2(T t) {
return switch (t) {
case A: break () -> "A";
case B: { break () -> "B"; }
default: break () -> "default";
case A: yield () -> "A";
case B: { yield () -> "B"; }
default: yield () -> "default";
};
}
@ -91,16 +91,16 @@ public class ExpressionSwitch {
? -2
: switch (s) {
case "A", "B" -> 0;
case "C" -> { break 1; }
case "C" -> { yield 1; }
default -> -1;
};
}
private int convert2(String s) {
return switch (s) {
case "A", "B": break 0;
case "C": break 1;
default: break -1;
case "A", "B": yield 0;
case "C": yield 1;
default: yield -1;
};
}
@ -112,7 +112,7 @@ public class ExpressionSwitch {
default: break STOP;
}
return switch (t) {
default: break good;
default: yield good;
};
}
}

@ -58,11 +58,11 @@ public class ExpressionSwitchBreaks1 {
case 0:
return switch (j) {
case 0:
if (true) break "0-0";
if (true) yield "0-0";
case 1:
break "0-1";
yield "0-1";
default:
break "0-X";
yield "0-X";
};
default: return "X";
}
@ -90,9 +90,9 @@ public class ExpressionSwitchBreaks1 {
r = "0-X";
break;
}
break r;
yield r;
case 1:
break "1";
yield "1";
case 2:
LOP: while (j-- > 0) {
if (k == 5) {
@ -102,9 +102,9 @@ public class ExpressionSwitchBreaks1 {
break LOP;
}
Supplier<String> getter = () -> { return "2-X-5"; };
break getter.get();
yield getter.get();
default:
break "X";
yield "X";
};
}

@ -12,7 +12,7 @@ public class ExpressionSwitchBreaks2 {
case 0:
return switch (j) {
case 0:
break "0-0";
yield "0-0";
case 1:
break ; //error: missing value
case 2:
@ -20,9 +20,9 @@ public class ExpressionSwitchBreaks2 {
case 3: {
int x = -1;
x: switch (i + j) {
case 0: break x; //error: cannot disambiguate, wrong type as well
case 0: break x;
}
break "X";
yield "X";
}
case 4: return "X"; //error: no returns from inside of the switch expression
case 5: continue; //error: no continue out of the switch expression
@ -31,17 +31,17 @@ public class ExpressionSwitchBreaks2 {
default: {
String x = "X";
x: switch (i + j) {
case 0: break ""; //error: cannot break from switch expression that is not immediatelly enclosing
case 0: yield ""; //error: cannot yield from switch expression that is not immediatelly enclosing
}
break "X";
yield "X";
}
};
case 1:
break "1" + undef; //error: complex value and no switch expression
yield "1" + undef; //error: complex value and no switch expression
}
}
j: print(switch (i) {
default: break j; //error: "j" is ambiguous (expression/label)
default: break j;
}, 0);
j2: print(switch (i) {
default: break j2;

@ -1,15 +1,12 @@
ExpressionSwitchBreaks2.java:17:25: compiler.err.break.missing.value
ExpressionSwitchBreaks2.java:19:25: compiler.err.break.outside.switch.expression
ExpressionSwitchBreaks2.java:23:37: compiler.err.break.ambiguous.target: x
ExpressionSwitchBreaks2.java:27:29: compiler.err.return.outside.switch.expression
ExpressionSwitchBreaks2.java:28:29: compiler.err.continue.outside.switch.expression
ExpressionSwitchBreaks2.java:29:29: compiler.err.continue.outside.switch.expression
ExpressionSwitchBreaks2.java:30:29: compiler.err.undef.label: UNKNOWN
ExpressionSwitchBreaks2.java:34:37: compiler.err.break.expr.not.immediate: compiler.misc.tree.tag.switch
ExpressionSwitchBreaks2.java:40:17: compiler.err.break.complex.value.no.switch.expression
ExpressionSwitchBreaks2.java:40:17: compiler.err.no.switch.expression
ExpressionSwitchBreaks2.java:40:29: compiler.err.cant.resolve.location: kindname.variable, undef, , , (compiler.misc.location: kindname.class, ExpressionSwitchBreaks2, null)
ExpressionSwitchBreaks2.java:44:22: compiler.err.break.ambiguous.target: j
ExpressionSwitchBreaks2.java:44:22: compiler.err.break.outside.switch.expression
ExpressionSwitchBreaks2.java:47:22: compiler.err.break.outside.switch.expression
- compiler.note.preview.filename: ExpressionSwitchBreaks2.java
- compiler.note.preview.recompile
12 errors
9 errors

@ -34,47 +34,49 @@ public class ExpressionSwitchBugs {
new ExpressionSwitchBugs().testNested();
new ExpressionSwitchBugs().testAnonymousClasses();
new ExpressionSwitchBugs().testFields();
check(3, new C(-1, 3).test(false));
check(3, new C(3, -1).test(true));
}
private void testNested() {
int i = 0;
check(42, id(switch (42) {
default: i++; break 42;
default: i++; yield 42;
}));
i = 0;
check(43, id(switch (42) {
case 42: while (i == 0) {
i++;
}
break 42 + i;
default: i++; break 42;
yield 42 + i;
default: i++; yield 42;
}));
i = 0;
check(42, id(switch (42) {
case 42: if (i == 0) {
break 42;
yield 42;
}
default: i++; break 43;
default: i++; yield 43;
}));
i = 0;
check(42, id(switch (42) {
case 42: if (i == 0) {
break 41 + switch (0) {
yield 41 + switch (0) {
case 0 -> 1;
default -> -1;
};
}
default: i++; break 43;
default: i++; yield 43;
}));
}
private void testAnonymousClasses() {
for (int i : new int[] {1, 2}) {
check(3, id((switch (i) {
case 1: break new I() {
case 1: yield new I() {
public int g() { return 3; }
};
default: break (I) () -> { return 3; };
default: yield (I) () -> { return 3; };
}).g()));
check(3, id((switch (i) {
case 1 -> new I() {
@ -96,7 +98,7 @@ public class ExpressionSwitchBugs {
case 2 -> {
int temp = 0;
temp += 3;
break temp;
yield temp;
}
default -> throw new IllegalStateException();
});
@ -107,7 +109,7 @@ public class ExpressionSwitchBugs {
case 2 -> {
int temp = 0;
temp += 3;
break temp;
yield temp;
}
default -> throw new IllegalStateException();
});
@ -120,7 +122,7 @@ public class ExpressionSwitchBugs {
return -1;
}
private void check(int actual, int expected) {
private static void check(int actual, int expected) {
if (actual != expected) {
throw new AssertionError("Unexpected result: " + actual);
}
@ -129,4 +131,32 @@ public class ExpressionSwitchBugs {
public interface I {
public int g();
}
static class Super {
public final int i;
public Super(int i) {
this.i = i;
}
}
static class C extends Super {
public final int i;
public C(int superI, int i) {
super(superI);
this.i = i;
}
public int test(boolean fromSuper) {
return switch (fromSuper ? 0 : 1) {
case 0 -> {
yield super.i;
}
default -> {
yield this.i;
}
};
}
}
}

@ -70,7 +70,7 @@ public class ExpressionSwitchDA {
int i;
int j = 0;
int k = switch (j) {
case 0 -> { i=42; break 42; }
case 0 -> { i=42; yield 42; }
default -> i=42;
};
System.out.println(i);
@ -80,7 +80,7 @@ public class ExpressionSwitchDA {
int j = 0;
int k = switch (j) {
case 0 -> i=42;
default -> { i=42; break 42; }
default -> { i=42; yield 42; }
};
System.out.println(i);
}
@ -88,8 +88,8 @@ public class ExpressionSwitchDA {
int i;
int j = 0;
int k = switch (j) {
case 0 -> { i=42; break 42; }
default -> { i=42; break 42; }
case 0 -> { i=42; yield 42; }
default -> { i=42; yield 42; }
};
System.out.println(i);
}

@ -39,19 +39,19 @@ public class ExpressionSwitchEmbedding {
int i = 6;
int o = 0;
while (switch (i) {
case 1: i = 0; break true;
case 2: i = 1; break true;
case 1: i = 0; yield true;
case 2: i = 1; yield true;
case 3, 4: i--;
if (i == 2 || i == 4) {
break switch (i) {
yield switch (i) {
case 2 -> true;
case 4 -> false;
default -> throw new IllegalStateException();
};
} else {
break true;
yield true;
}
default: i--; break switch (i) {
default: i--; yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -67,8 +67,8 @@ public class ExpressionSwitchEmbedding {
int i = 6;
int o = 0;
while (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4:
try {
new ExpressionSwitchEmbedding().throwException();
@ -76,16 +76,16 @@ public class ExpressionSwitchEmbedding {
i--;
if (i == 2 || i == 4) {
try {
break switch (i) {
yield switch (i) {
case 2 -> throw new ResultException(true);
case 4 -> false;
default -> throw new IllegalStateException();
};
} catch (ResultException ex) {
break ex.result;
yield ex.result;
}
} else {
break true;
yield true;
}
}
default:
@ -93,7 +93,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) {
i--;
break switch (i) {
yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -111,19 +111,19 @@ public class ExpressionSwitchEmbedding {
int i = 6;
int o = 0;
if (switch (i) {
case 1: i = 0; break true;
case 2: i = 1; break true;
case 1: i = 0; yield true;
case 2: i = 1; yield true;
case 3, 4: i--;
if (i == 2 || i == 4) {
break (switch (i) {
yield (switch (i) {
case 2 -> 3;
case 4 -> 5;
default -> throw new IllegalStateException();
}) == i + 1;
} else {
break true;
yield true;
}
default: i--; break switch (i) {
default: i--; yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -139,8 +139,8 @@ public class ExpressionSwitchEmbedding {
int i = 6;
int o = 0;
if (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4:
try {
new ExpressionSwitchEmbedding().throwException();
@ -148,16 +148,16 @@ public class ExpressionSwitchEmbedding {
i--;
if (i == 2 || i == 4) {
try {
break switch (i) {
yield switch (i) {
case 2 -> throw new ResultException(true);
case 4 -> false;
default -> throw new IllegalStateException();
};
} catch (ResultException ex) {
break ex.result;
yield ex.result;
}
} else {
break true;
yield true;
}
}
default:
@ -165,7 +165,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) {
i--;
break switch (i) {
yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -182,19 +182,19 @@ public class ExpressionSwitchEmbedding {
{
int o = 0;
for (int i = 6; (switch (i) {
case 1: i = 0; break true;
case 2: i = 1; break true;
case 1: i = 0; yield true;
case 2: i = 1; yield true;
case 3, 4: i--;
if (i == 2 || i == 4) {
break switch (i) {
yield switch (i) {
case 2 -> true;
case 4 -> false;
default -> throw new IllegalStateException();
};
} else {
break true;
yield true;
}
default: i--; break switch (i) {
default: i--; yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -209,8 +209,8 @@ public class ExpressionSwitchEmbedding {
{
int o = 0;
for (int i = 6; (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4:
try {
new ExpressionSwitchEmbedding().throwException();
@ -218,16 +218,16 @@ public class ExpressionSwitchEmbedding {
i--;
if (i == 2 || i == 4) {
try {
break switch (i) {
yield switch (i) {
case 2 -> throw new ResultException(true);
case 4 -> false;
default -> throw new IllegalStateException();
};
} catch (ResultException ex) {
break ex.result;
yield ex.result;
}
} else {
break true;
yield true;
}
}
default:
@ -235,7 +235,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) {
i--;
break switch (i) {
yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -255,19 +255,19 @@ public class ExpressionSwitchEmbedding {
do {
o++;
} while (switch (i) {
case 1: i = 0; break true;
case 2: i = 1; break true;
case 1: i = 0; yield true;
case 2: i = 1; yield true;
case 3, 4: i--;
if (i == 2 || i == 4) {
break switch (i) {
yield switch (i) {
case 2 -> true;
case 4 -> false;
default -> throw new IllegalStateException();
};
} else {
break true;
yield true;
}
default: i--; break switch (i) {
default: i--; yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;
@ -283,8 +283,8 @@ public class ExpressionSwitchEmbedding {
do {
o++;
} while (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4:
try {
new ExpressionSwitchEmbedding().throwException();
@ -292,16 +292,16 @@ public class ExpressionSwitchEmbedding {
i--;
if (i == 2 || i == 4) {
try {
break switch (i) {
yield switch (i) {
case 2 -> throw new ResultException(true);
case 4 -> false;
default -> throw new IllegalStateException();
};
} catch (ResultException ex) {
break ex.result;
yield ex.result;
}
} else {
break true;
yield true;
}
}
default:
@ -309,7 +309,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) {
i--;
break switch (i) {
yield switch (i) {
case -1 -> false;
case 3 -> true;
default -> true;

@ -53,7 +53,7 @@ public class ExpressionSwitchFallThrough {
return switch (t) {
case A: help = "a";
case B: help += "b";
default: break help;
default: yield help;
};
}
@ -62,7 +62,7 @@ public class ExpressionSwitchFallThrough {
return switch (t) {
case A: help = "a";
case B: help += "b";
default: break help;
default: yield help;
};
}

@ -50,8 +50,8 @@ public class ExpressionSwitchFallThrough1 {
return switch (p) {
case 0: result += "0";
case 1: result += "1";
break result;
default: break "other";
yield result;
default: yield "other";
};
}
@ -60,7 +60,7 @@ public class ExpressionSwitchFallThrough1 {
switch (p) {
case 0: result += "0";
case 1: result += "1";
break ;
break;
default: result = "other";
break;
}

@ -9,7 +9,7 @@ public class ExpressionSwitchFlow {
private String test1(int i) {
return switch (i) {
case 0 -> {}
default -> { break "other"; }
default -> { yield "other"; }
};
}
private String test2(int i) {
@ -27,7 +27,7 @@ public class ExpressionSwitchFlow {
}
private String test4(int i) {
return switch (i) {
case 0 -> { break "other"; }
case 0 -> { yield "other"; }
default -> {}
};
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,11 +43,11 @@ public class ExpressionSwitchInExpressionSwitch {
default -> {
int k = switch (j) {
default -> {
break 42;
yield 42;
}
};
System.out.println("didn't break to the top level");
break 43;
System.out.println("didn't yield to the top level");
yield 43;
}
};
if (i!=43) {

@ -27,7 +27,7 @@ public class ExpressionSwitchInfer {
String str = switch (param) {
case "" -> {
break 0;
yield 0;
} default ->"default";
};

@ -26,9 +26,9 @@ public class ExpressionSwitchNotExhaustive {
s = "42";
break;
}
break s;
yield s;
default:
break "43";
yield "43";
};
}
enum E {

@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Verify Tree.toString() related to switch expressions
* @modules jdk.compiler
*/
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import javax.tools.*;
import com.sun.source.util.JavacTask;
public class ExpressionSwitchToString {
private static final String CODE =
"public class C {" +
" void t1(Integer i) {" +
" switch (i) {" +
" case null: i++; break;" +
" case 0, 1: i++; break;" +
" default: i++; break;" +
" }" +
" }" +
" int t2(Integer i) {" +
" return switch (i) {" +
" case null: yield 0;" +
" case 0, 1: yield 1;" +
" default: yield 2;" +
" }" +
" }" +
"}";
private static final String EXPECTED =
"\n" +
"public class C {\n" +
" \n" +
" void t1(Integer i) {\n" +
" switch (i) {\n" +
" case null:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" case 0, 1:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" default:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" }\n" +
" }\n" +
" \n" +
" int t2(Integer i) {\n" +
" return switch (i) {\n" +
" case null:\n" +
" yield 0;\n" +
" \n" +
" case 0, 1:\n" +
" yield 1;\n" +
" \n" +
" default:\n" +
" yield 2;\n" +
" \n" +
" };\n" +
" }\n" +
"}";
public static void main(String[] args) throws Exception {
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
assert tool != null;
DiagnosticListener<JavaFileObject> noErrors = d -> {};
String sourceVersion = Integer.toString(Runtime.version().feature());
JavacTask ct = (JavacTask) tool.getTask(null, null, noErrors,
List.of("-XDdev", "--enable-preview", "-source", sourceVersion), null,
Arrays.asList(new MyFileObject(CODE)));
String actualCode = ct.parse().iterator().next().toString();
actualCode = actualCode.replace(System.getProperty("line.separator"), "\n");
if (!EXPECTED.equals(actualCode)) {
throw new AssertionError("Unexpected toString outcome: " +
actualCode);
}
}
static class MyFileObject extends SimpleJavaFileObject {
private String text;
public MyFileObject(String text) {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
this.text = text;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return text;
}
}
}

@ -11,44 +11,44 @@ public class ExpressionSwitchUnreachable {
int z = 42;
int i = switch (z) {
case 0 -> {
break 42;
yield 42;
System.out.println("Unreachable"); //Unreachable
}
default -> 0;
};
i = switch (z) {
case 0 -> {
break 42;
break 42; //Unreachable
yield 42;
yield 42; //Unreachable
}
default -> 0;
};
i = switch (z) {
case 0:
System.out.println("0");
break 42;
yield 42;
System.out.println("1"); //Unreachable
default : break 42;
default : yield 42;
};
i = switch (z) {
case 0 -> 42;
default -> {
break 42;
yield 42;
System.out.println("Unreachable"); //Unreachable
}
};
i = switch (z) {
case 0: break 42;
case 0: yield 42;
default:
System.out.println("0");
break 42;
yield 42;
System.out.println("1"); //Unreachable
};
i = switch (z) {
case 0:
default:
System.out.println("0");
break 42;
yield 42;
System.out.println("1"); //Unreachable
};
}

@ -50,9 +50,9 @@ public class ParseIncomplete {
" }" +
" int t2(Integer i) {" +
" return switch (i) {" +
" case null: break 0;" +
" case 0, 1: break 1;" +
" default: break 2;" +
" case null: yield 0;" +
" case 0, 1: yield 1;" +
" default: yield 2;" +
" }" +
" }" +
"}";

@ -38,7 +38,7 @@ public class SwitchExpressionIsNotAConstant {
int dummy = 1 + switch (i) {
default -> {
i++;
break 1;
yield 1;
}
};
if (i != 1) {
@ -51,7 +51,7 @@ public class SwitchExpressionIsNotAConstant {
case -1 -> 1;
default -> {
i++;
break 1;
yield 1;
}
};
if (i != 1) {
@ -63,7 +63,7 @@ public class SwitchExpressionIsNotAConstant {
int dummy = 1 + switch (i) {
default :
i++;
break 1;
yield 1;
};
if (i != 1) {
throw new IllegalStateException("Side effects missing.");
@ -72,10 +72,10 @@ public class SwitchExpressionIsNotAConstant {
{
i = 0;
int dummy = 1 + switch (i) {
case -1: break 1;
case -1: yield 1;
default:
i++;
break 1;
yield 1;
};
if (i != 1) {
throw new IllegalStateException("Side effects missing.");

@ -9,9 +9,9 @@ public class SwitchExpressionScopesIsolated {
private String scopesIsolated(int i) {
return switch (i) {
case 0 -> { String res = ""; break res; }
case 1 -> { res = ""; break res; }
default -> { res = ""; break res; }
case 0 -> { String res = ""; yield res; }
case 1 -> { res = ""; yield res; }
default -> { res = ""; yield res; }
};
}

@ -38,6 +38,7 @@ import javax.tools.*;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.SwitchExpressionTree;
import com.sun.source.tree.YieldTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.SimpleTreeVisitor;
@ -53,12 +54,13 @@ public class SwitchExpressionSimpleVisitorTest {
String code = "class Test {\n" +
" int t(int i) {\n" +
" return switch(i) {\n" +
" default: break -1;\n" +
" default: yield -1;\n" +
" }\n" +
" }\n" +
"}\n";
int[] callCount = new int[1];
int[] switchExprNodeCount = new int[1];
int[] yieldNodeCount = new int[1];
new TreePathScanner<Void, Void>() {
@Override
public Void visitSwitchExpression(SwitchExpressionTree node, Void p) {
@ -74,11 +76,27 @@ public class SwitchExpressionSimpleVisitorTest {
}, null);
return super.visitSwitchExpression(node, p);
}
@Override
public Void visitYield(YieldTree node, Void p) {
node.accept(new SimpleTreeVisitor<Void, Void>() {
@Override
protected Void defaultAction(Tree defaultActionNode, Void p) {
callCount[0]++;
if (node == defaultActionNode) {
yieldNodeCount[0]++;
}
return null;
}
}, null);
return super.visitYield(node, p);
}
}.scan(parse(code), null);
if (callCount[0] != 1 || switchExprNodeCount[0] != 1) {
if (callCount[0] != 2 || switchExprNodeCount[0] != 1 ||
yieldNodeCount[0] != 1) {
throw new AssertionError("Unexpected counts; callCount=" + callCount[0] +
", switchExprNodeCount=" + switchExprNodeCount[0]);
", switchExprNodeCount=" + switchExprNodeCount[0] +
", yieldNodeCount=" + yieldNodeCount[0]);
}
}

@ -38,34 +38,34 @@ public class TryCatch {
case 1:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
default: break -1;
default: yield -1;
};
case 1 -> {
try {
break new TryCatch().id(switch (p + 1) {
yield new TryCatch().id(switch (p + 1) {
case 2:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
throw ex;
}
default: break -1;
default: yield -1;
});
} catch(Throwable ex) {
break val;
yield val;
}
}
default -> {
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
}
} - 1);
@ -83,34 +83,34 @@ public class TryCatch {
case 1:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
default: break false;
default: yield false;
};
case 1 -> {
try {
break new TryCatch().id(switch (p + 1) {
yield new TryCatch().id(switch (p + 1) {
case 2:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
throw ex;
}
default: break false;
default: yield false;
});
} catch(Throwable ex) {
break true;
yield true;
}
}
default -> {
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
}
} && (x = 1) == 1 && x == 1 ? val : -1);
@ -127,34 +127,34 @@ public class TryCatch {
case B:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
default: break -1;
default: yield -1;
};
case B -> {
try {
break new TryCatch().id(switch (e.next()) {
yield new TryCatch().id(switch (e.next()) {
case C:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
throw ex;
}
default: break -1;
default: yield -1;
});
} catch(Throwable ex) {
break val;
yield val;
}
}
default -> {
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
}
} - 1);
@ -172,34 +172,34 @@ public class TryCatch {
case B:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
default: break false;
default: yield false;
};
case B -> {
try {
break new TryCatch().id(switch (e.next()) {
yield new TryCatch().id(switch (e.next()) {
case C:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
throw ex;
}
default: break false;
default: yield false;
});
} catch(Throwable ex) {
break true;
yield true;
}
}
default -> {
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
}
} && (x = 1) == 1 && x == 1 ? val : -1);
@ -216,34 +216,34 @@ public class TryCatch {
case "c":
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
default: break -1;
default: yield -1;
};
case "a" -> {
try {
break new TryCatch().id(switch (s + "c") {
yield new TryCatch().id(switch (s + "c") {
case "ac":
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
throw ex;
}
default: break -1;
default: yield -1;
});
} catch(Throwable ex) {
break val;
yield val;
}
}
default -> {
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
break val;
yield val;
}
}
} - 1);
@ -261,34 +261,34 @@ public class TryCatch {
case "c":
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
default: break false;
default: yield false;
};
case "a" -> {
try {
break new TryCatch().id(switch (s + "c") {
yield new TryCatch().id(switch (s + "c") {
case "ac":
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
throw ex;
}
default: break false;
default: yield false;
});
} catch(Throwable ex) {
break true;
yield true;
}
}
default -> {
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
break true;
yield true;
}
}
} && (x = 1) == 1 && x == 1 ? val : -1);
@ -330,75 +330,75 @@ public class TryCatch {
static class FieldHolder {
private final int intTest = switch (0) {
case -1: break -1;
case -1: yield -1;
default:
try {
break new TryCatch().id(switch (2) {
yield new TryCatch().id(switch (2) {
case 2:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
throw ex;
}
default: break -1;
default: yield -1;
});
} catch(Throwable ex) {
break 3;
yield 3;
}
};
private static final int intStaticTest = switch (0) {
case -1: break -1;
case -1: yield -1;
default:
try {
break new TryCatch().id(switch (2) {
yield new TryCatch().id(switch (2) {
case 2:
try {
new TryCatch().throwException();
break -1;
yield -1;
} catch(Throwable ex) {
throw ex;
}
default: break -1;
default: yield -1;
});
} catch(Throwable ex) {
break 3;
yield 3;
}
};
private final boolean booleanTest = switch (0) {
case -1: break false;
case -1: yield false;
default:
try {
break new TryCatch().id(switch (2) {
yield new TryCatch().id(switch (2) {
case 2:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
throw ex;
}
default: break false;
default: yield false;
});
} catch(Throwable ex) {
break true;
yield true;
}
};
private static final boolean booleanStaticTest = switch (0) {
case -1: break false;
case -1: yield false;
default:
try {
break new TryCatch().id(switch (2) {
yield new TryCatch().id(switch (2) {
case 2:
try {
new TryCatch().throwException();
break false;
yield false;
} catch(Throwable ex) {
throw ex;
}
default: break false;
default: yield false;
});
} catch(Throwable ex) {
break true;
yield true;
}
};
}

@ -0,0 +1,162 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Verify correct warnings w.r.t. yield
* @compile/ref=WarnWrongYieldTest.out -source 13 -XDrawDiagnostics -XDshould-stop.at=ATTR WarnWrongYieldTest.java
*/
package t;
//ERROR - type called yield:
import t.WarnWrongYieldTest.yield;
public class WarnWrongYieldTest {
// ERROR - class called yield
class yield { }
// OK to have fields called yield
String[] yield = null;
// ERROR - field of type yield
yield y;
// OK to have methods called yield
// Nullary yield method
String[] yield() {
return null;
}
// Unary yield method
String[] yield(int i) {
return null;
}
// Binary yield method
String[] yield(int i, int j) {
return null;
}
// OK to declare a local called yield
void LocalDeclaration1() {
int yield;
}
// OK to declare and initialise a local called yield
void LocalDeclaration2() {
int yield = 42;
}
void YieldTypedLocals(int i) {
// ERROR - Parsed as yield statement, and y1 is unknown
yield y1 = null;
// ERROR - Parsed as yield statement, and y2 is unknown
yield y2 = new yield();
// ERROR - can not create an yield-valued local of type Object
Object y3 = new yield();
// ERROR - can not create a final yield-valued local of type yield
final yield y4 = new yield();
// ERROR - can create a non-final local of type yield using qualified typename
WarnWrongYieldTest.yield y5 = new yield();
}
void MethodInvocation(int i) {
// OK - can access a field called yield
String[] x = this.yield;
// ERROR - calling nullary yield method using simple name parsed as yield statement
yield();
// OK - can call nullary yield method using qualified name
this.yield();
// ERROR - Calling unary yield method using simple name is parsed as yield statement
yield(2);
// OK - calling unary yield method using qualified name
this.yield(2);
// ERROR - Calling binary yield method using simple name is parsed as yield statement
yield(2, 2); //error
// OK - calling binary yield method using qualified name
this.yield(2, 2);
// ERROR - nullary yield method as receiver is parsed as yield statement
yield().toString();
// OK - nullary yield method as receiver using qualified name
this.yield().toString();
// ERROR - unary yield method as receiver is parsed as yield statement
yield(2).toString();
// OK - unary yield method as receiver using qualified name
this.yield(2).toString();
// ERROR - binary yield method as receiver is parsed as yield statement
yield(2, 2).toString();
// OK - binary yield method as receiver using qualified name
this.yield(2, 2).toString();
// OK - yield method call is in an expression position
String str = yield(2).toString();
//OK - yield is a variable
yield.toString();
// OK - parsed as method call (with qualified local yield as receiver)
this.yield.toString();
yield[0].toString(); //error
}
private void yieldLocalVar1(int i) {
int yield = 0;
//OK - yield is a variable:
yield++;
yield--;
//OK - yield is a variable:
yield = 3;
//OK - yield is a variable:
for (int j = 0; j < 3; j++)
yield += 1;
//OK - yield is a variable and not at the beginning of the statement:
yieldLocalVar1(yield);
//ERROR - unqualified yield method invocation:
yieldLocalVar1(yield().length);
yieldLocalVar1(yield.class.getModifiers());
}
private void yieldLocalVar2(int i) {
int[] yield = new int[1];
//OK - yield is a variable:
yield[0] = 5;
}
}

@ -0,0 +1,25 @@
WarnWrongYieldTest.java:39:11: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:45:5: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:72:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:75:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:81:21: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:93:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:98:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:103:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:108:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:113:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:118:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:123:22: compiler.warn.invalid.yield
WarnWrongYieldTest.java:152:24: compiler.warn.invalid.yield
WarnWrongYieldTest.java:34:28: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:45:5: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:72:9: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:75:9: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:75:24: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:78:25: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:81:15: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:81:30: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:84:27: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:84:43: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:153:24: compiler.warn.illegal.ref.to.restricted.type: yield
24 warnings

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Ensure javac is not crashing for wrong breaks.
* @compile/fail/ref=WrongBreakTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=FLOW WrongBreakTest.java
*/
public class WrongBreakTest {
void test(int i) {
int s = 0;
int j = switch (s) { default: break; };
test(switch (s) { default: yield; });
Runnable r = () -> {
yield 15;
};
while (true) {
yield 15;
}
}
void test(Object o) {}
}

@ -0,0 +1,8 @@
WrongBreakTest.java:36:41: compiler.err.illegal.start.of.expr
WrongBreakTest.java:35:39: compiler.err.break.outside.switch.expression
WrongBreakTest.java:36:9: compiler.err.ref.ambiguous: test, kindname.method, test(int), WrongBreakTest, kindname.method, test(java.lang.Object), WrongBreakTest
WrongBreakTest.java:38:13: compiler.err.no.switch.expression
WrongBreakTest.java:41:13: compiler.err.no.switch.expression
- compiler.note.preview.filename: WrongBreakTest.java
- compiler.note.preview.recompile
5 errors

@ -0,0 +1,225 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Ensure proper errors are returned for yields.
* @compile/fail/ref=WrongYieldTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=ATTR WrongYieldTest.java
*/
package t;
//ERROR - type called yield:
import t.WrongYieldTest.yield;
public class WrongYieldTest {
// ERROR - class called yield
class yield { }
// OK to have fields called yield
String[] yield = null;
// ERROR - field of type yield
yield y;
// OK to have methods called yield
// Nullary yield method
String[] yield() {
return null;
}
// Unary yield method
String[] yield(int i) {
return null;
}
// Binary yield method
String[] yield(int i, int j) {
return null;
}
// OK to declare a local called yield
void LocalDeclaration1() {
int yield;
}
// OK to declare and initialise a local called yield
void LocalDeclaration2() {
int yield = 42;
}
// ERROR can't refer to a local called yield in the initialiser
void LocalDeclaration3() {
int yield = yield + 1;
}
// OK yield gets interpreted as an identifier in a local declaration
void LocalDeclaration4(int i) {
int local = switch (i) {
default -> {
int yield = yield + 1;
yield 42;
}
};
}
// OK - yield a local called yield
void LocalDeclaration5(int i) {
int yield = 42;
int temp = switch (i) {
default -> {
yield yield;
}
};
}
void YieldTypedLocals(int i) {
// ERROR - Parsed as yield statement, and y1 is unknown
yield y1 = null;
// ..whereas..
// ERROR - parsed as yield statement, which has no switch target
Object y1;
yield y1 = null;
// ERROR - Parsed as yield statement, and y2 is unknown
yield y2 = new yield();
// OK - Parsed as yield statement that assigns local y
Object y;
Object o = switch (i) {
default :
yield y = null;
};
// ERROR - Parsed as yield statement that assigns local y,
//but the initializer refers to restricted identifier:
Object y2;
Object o2 = switch (i) {
default :
yield y2 = new yield();
};
// ERROR - can not create an yield-valued local of type Object
Object y3 = new yield();
// ERROR - can not create a final yield-valued local of type yield
final yield y4 = new yield();
// ERROR - can create a non-final local of type yield using qualified typename
WrongYieldTest.yield y5 = new yield();
}
void MethodInvocation(int i) {
// OK - can access a field called yield
String[] x = this.yield;
// ERROR - calling nullary yield method using simple name parsed as yield statement
yield();
// OK - can call nullary yield method using qualified name
this.yield();
// ERROR - Calling unary yield method using simple name is parsed as yield statement
yield(2);
// OK - calling unary yield method using qualified name
this.yield(2);
// ERROR - Calling binary yield method using simple name is parsed as yield statement
yield(2, 2); //error
// OK - calling binary yield method using qualified name
this.yield(2, 2);
// ERROR - nullary yield method as receiver is parsed as yield statement
yield().toString();
// OK - nullary yield method as receiver using qualified name
this.yield().toString();
// ERROR - unary yield method as receiver is parsed as yield statement
yield(2).toString();
// OK - unary yield method as receiver using qualified name
this.yield(2).toString();
// ERROR - binary yield method as receiver is parsed as yield statement
yield(2, 2).toString();
// OK - binary yield method as receiver using qualified name
this.yield(2, 2).toString();
// OK - yield method call is in an expression position
String str = yield(2).toString();
//OK - yield is a variable
yield.toString();
// OK - parsed as method call (with qualified local yield as receiver)
this.yield.toString();
yield[0].toString(); //error
// OK - parsed as yield statement in switch expression
int j = switch (i) {
default:
yield(2);
};
// ERROR - second yield is an unreachable statement.
x = switch (i) {
default: {
yield x = null;
yield null;
}
};
}
private void yieldLocalVar1(int i) {
int yield = 0;
//OK - yield is a variable:
yield++;
yield--;
//ERROR - yield is a statement, but no enclosing switch expr:
yield ++i;
yield --i;
//OK - yield is a variable:
yield = 3;
//OK - yield is a variable:
for (int j = 0; j < 3; j++)
yield += 1;
//OK - yield is a variable and not at the beginning of the statement:
yieldLocalVar1(yield);
//ERROR - unqualified yield method invocation:
yieldLocalVar1(yield().length);
yieldLocalVar1(yield.class.getModifiers());
}
private void yieldLocalVar2(int i) {
int[] yield = new int[1];
//OK - yield is a variable:
yield[0] = 5;
}
}

@ -0,0 +1,29 @@
WrongYieldTest.java:39:11: compiler.err.restricted.type.not.allowed: yield, 13
WrongYieldTest.java:45:5: compiler.err.restricted.type.not.allowed.here: yield
WrongYieldTest.java:136:9: compiler.err.invalid.yield
WrongYieldTest.java:146:9: compiler.err.invalid.yield
WrongYieldTest.java:151:9: compiler.err.invalid.yield
WrongYieldTest.java:161:9: compiler.err.invalid.yield
WrongYieldTest.java:166:22: compiler.err.invalid.yield
WrongYieldTest.java:215:24: compiler.err.invalid.yield
WrongYieldTest.java:34:24: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:95:9: compiler.err.no.switch.expression
WrongYieldTest.java:95:15: compiler.err.cant.resolve.location: kindname.variable, y1, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
WrongYieldTest.java:99:9: compiler.err.no.switch.expression
WrongYieldTest.java:102:9: compiler.err.no.switch.expression
WrongYieldTest.java:102:15: compiler.err.cant.resolve.location: kindname.variable, y2, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
WrongYieldTest.java:102:24: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:116:32: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:120:25: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:123:30: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:126:23: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:126:39: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:141:9: compiler.err.no.switch.expression.qualify
WrongYieldTest.java:156:9: compiler.err.no.switch.expression
WrongYieldTest.java:156:17: compiler.err.cant.deref: int
WrongYieldTest.java:201:9: compiler.err.no.switch.expression
WrongYieldTest.java:202:9: compiler.err.no.switch.expression
WrongYieldTest.java:216:24: compiler.err.illegal.ref.to.restricted.type: yield
- compiler.note.preview.filename: WrongYieldTest.java
- compiler.note.preview.recompile
26 errors

@ -0,0 +1,116 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Verify that definite assignment works (legal code)
* @compile --enable-preview -source ${jdk.version} DefiniteAssignment1.java
* @run main/othervm --enable-preview DefiniteAssignment1
*/
public class DefiniteAssignment1 {
public static void main(String[] args) {
int a = 0;
{
int x;
switch(a) {
case 0: x = 0; break;
default: x = 1; break;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 1: x = 1; break;
case 0:
default: x = 0; break;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 1: x = 1; break;
case 0:
default: x = 0;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 0 -> x = 0;
default -> x = 1;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
try {
switch(a) {
case 1: x = 1; break;
case 0:
default: throw new UnsupportedOperationException();
}
throw new IllegalStateException("Unexpected value: " + x);
} catch (UnsupportedOperationException ex) {
//OK
}
}
{
int x;
switch(a) {
case 0 -> x = 0;
default -> throw new IllegalStateException();
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
}
enum E {
A, B, C;
}
}

@ -0,0 +1,80 @@
/**
* @test /nodynamiccopyright/
* @summary Verify that definite assignment works (illegal code)
* @compile/fail/ref=DefiniteAssignment2.out -XDrawDiagnostics --enable-preview -source ${jdk.version} DefiniteAssignment2.java
*/
public class DefiniteAssignment2 {
public static void main(String[] args) {
int a = 0;
E e = E.A;
{
int x;
switch(a) {
case 0: break;
default: x = 1; break;
}
System.err.println(x);
}
{
int x;
switch(a) {
case 0 -> {}
default -> x = 1;
}
System.err.println(x);
}
{
int x;
switch(a) {
case 0: x = 0; break;
default:
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B, C -> x = 0;
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B, C -> { x = 0; }
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B -> { x = 0; }
case C -> throw new IllegalStateException();
}
System.err.println(x);
}
}
enum E {
A, B, C;
}
}

@ -0,0 +1,9 @@
DefiniteAssignment2.java:20:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:31:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:42:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:52:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:62:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:73:28: compiler.err.var.might.not.have.been.initialized: x
- compiler.note.preview.filename: DefiniteAssignment2.java
- compiler.note.preview.recompile
6 errors

@ -30,7 +30,7 @@ public class MultipleLabelsExpression {
private String expression1(T t) {
return switch (t) {
case A -> "A";
case B, C -> { break "B-C"; }
case B, C -> { yield "B-C"; }
case D -> "D";
default -> "other";
};

@ -2,5 +2,5 @@ VarInImplicitLambdaNegTest01.java:12:28: compiler.err.invalid.lambda.parameter.d
VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.array
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.array: var
5 errors

@ -1,6 +1,6 @@
- compiler.warn.source.no.bootclasspath: 10
VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.here
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.here: var
3 errors
1 warning