mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
7196163: Project Coin: Allow effectively final variables to be used as resources in try-with-resources
Allowing final variables as operands to try-with-resources; also reviewed by Sergei Pikalev. Reviewed-by: darcy, mcimadamore, vromero
This commit is contained in:
parent
9d6d069c22
commit
a2b0a2413e
20 changed files with 398 additions and 19 deletions
|
@ -168,6 +168,7 @@ public class Kinds {
|
|||
public static final KindSelector MTH = new KindSelector(0x10);
|
||||
public static final KindSelector ERR = new KindSelector(0x3f);
|
||||
public static final KindSelector POLY = new KindSelector(0x20);
|
||||
public static final KindSelector ASG = new KindSelector(0x44);
|
||||
|
||||
//common derived selectors
|
||||
public static final KindSelector TYP_PCK = of(TYP, PCK);
|
||||
|
|
|
@ -140,6 +140,9 @@ public enum Source {
|
|||
public boolean allowTryWithResources() {
|
||||
return compareTo(JDK1_7) >= 0;
|
||||
}
|
||||
public boolean allowEffectivelyFinalVariablesInTryWithResources() {
|
||||
return compareTo(JDK1_9) >= 0;
|
||||
}
|
||||
public boolean allowBinaryLiterals() {
|
||||
return compareTo(JDK1_7) >= 0;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ public class Attr extends JCTree.Visitor {
|
|||
identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false);
|
||||
|
||||
statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
|
||||
varInfo = new ResultInfo(KindSelector.VAR, Type.noType);
|
||||
varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
|
||||
unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
|
||||
unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
|
||||
unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
|
||||
|
@ -498,7 +498,7 @@ public class Attr extends JCTree.Visitor {
|
|||
}
|
||||
|
||||
final ResultInfo statInfo;
|
||||
final ResultInfo varInfo;
|
||||
final ResultInfo varAssignmentInfo;
|
||||
final ResultInfo unknownAnyPolyInfo;
|
||||
final ResultInfo unknownExprInfo;
|
||||
final ResultInfo unknownTypeInfo;
|
||||
|
@ -1293,7 +1293,7 @@ public class Attr extends JCTree.Visitor {
|
|||
}
|
||||
};
|
||||
ResultInfo twrResult =
|
||||
new ResultInfo(KindSelector.VAL,
|
||||
new ResultInfo(KindSelector.VAR,
|
||||
syms.autoCloseableType,
|
||||
twrContext);
|
||||
if (resource.hasTag(VARDEF)) {
|
||||
|
@ -2942,7 +2942,7 @@ public class Attr extends JCTree.Visitor {
|
|||
}
|
||||
|
||||
public void visitAssign(JCAssign tree) {
|
||||
Type owntype = attribTree(tree.lhs, env.dup(tree), varInfo);
|
||||
Type owntype = attribTree(tree.lhs, env.dup(tree), varAssignmentInfo);
|
||||
Type capturedType = capture(owntype);
|
||||
attribExpr(tree.rhs, env, owntype);
|
||||
result = check(tree, capturedType, KindSelector.VAL, resultInfo);
|
||||
|
@ -2950,7 +2950,7 @@ public class Attr extends JCTree.Visitor {
|
|||
|
||||
public void visitAssignop(JCAssignOp tree) {
|
||||
// Attribute arguments.
|
||||
Type owntype = attribTree(tree.lhs, env, varInfo);
|
||||
Type owntype = attribTree(tree.lhs, env, varAssignmentInfo);
|
||||
Type operand = attribExpr(tree.rhs, env);
|
||||
// Find operator.
|
||||
Symbol operator = tree.operator = rs.resolveBinaryOperator(
|
||||
|
@ -2976,7 +2976,7 @@ public class Attr extends JCTree.Visitor {
|
|||
public void visitUnary(JCUnary tree) {
|
||||
// Attribute arguments.
|
||||
Type argtype = (tree.getTag().isIncOrDecUnaryOp())
|
||||
? attribTree(tree.arg, env, varInfo)
|
||||
? attribTree(tree.arg, env, varAssignmentInfo)
|
||||
: chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env));
|
||||
|
||||
// Find operator.
|
||||
|
@ -3156,7 +3156,7 @@ public class Attr extends JCTree.Visitor {
|
|||
|
||||
// If we are expecting a variable (as opposed to a value), check
|
||||
// that the variable is assignable in the current environment.
|
||||
if (pkind() == KindSelector.VAR)
|
||||
if (KindSelector.ASG.subset(pkind()))
|
||||
checkAssignable(tree.pos(), v, null, env);
|
||||
}
|
||||
|
||||
|
@ -3255,7 +3255,7 @@ public class Attr extends JCTree.Visitor {
|
|||
|
||||
// If we are expecting a variable (as opposed to a value), check
|
||||
// that the variable is assignable in the current environment.
|
||||
if (pkind() == KindSelector.VAR)
|
||||
if (KindSelector.ASG.subset(pkind()))
|
||||
checkAssignable(tree.pos(), v, tree.selected, env);
|
||||
}
|
||||
|
||||
|
@ -3538,7 +3538,7 @@ public class Attr extends JCTree.Visitor {
|
|||
// Test (4): if symbol is an instance field of a raw type,
|
||||
// which is being assigned to, issue an unchecked warning if
|
||||
// its type changes under erasure.
|
||||
if (resultInfo.pkind == KindSelector.VAR &&
|
||||
if (KindSelector.ASG.subset(pkind()) &&
|
||||
v.owner.kind == TYP &&
|
||||
(v.flags() & STATIC) == 0 &&
|
||||
(site.hasTag(CLASS) || site.hasTag(TYPEVAR))) {
|
||||
|
|
|
@ -2562,6 +2562,8 @@ public class Flow {
|
|||
* This pass implements the last step of the dataflow analysis, namely
|
||||
* the effectively-final analysis check. This checks that every local variable
|
||||
* reference from a lambda body/local inner class is either final or effectively final.
|
||||
* Additional this also checks that every variable that is used as an operand to
|
||||
* try-with-resources is final or effectively final.
|
||||
* As effectively final variables are marked as such during DA/DU, this pass must run after
|
||||
* AssignAnalyzer.
|
||||
*/
|
||||
|
@ -2690,6 +2692,18 @@ public class Flow {
|
|||
}
|
||||
}
|
||||
|
||||
public void visitTry(JCTry tree) {
|
||||
for (JCTree resource : tree.resources) {
|
||||
if (!resource.hasTag(VARDEF)) {
|
||||
Symbol var = TreeInfo.symbol(resource);
|
||||
if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
|
||||
log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitTry(tree);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* main method
|
||||
*************************************************************************/
|
||||
|
|
|
@ -145,6 +145,8 @@ public class JavacParser implements Parser {
|
|||
this.names = fac.names;
|
||||
this.source = fac.source;
|
||||
this.allowTWR = source.allowTryWithResources();
|
||||
this.allowEffectivelyFinalVariablesInTWR =
|
||||
source.allowEffectivelyFinalVariablesInTryWithResources();
|
||||
this.allowDiamond = source.allowDiamond();
|
||||
this.allowMulticatch = source.allowMulticatch();
|
||||
this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
|
||||
|
@ -184,6 +186,10 @@ public class JavacParser implements Parser {
|
|||
*/
|
||||
boolean allowTWR;
|
||||
|
||||
/** Switch: should we allow (effectively) final variables as resources in try-with-resources?
|
||||
*/
|
||||
boolean allowEffectivelyFinalVariablesInTWR;
|
||||
|
||||
/** Switch: should we fold strings?
|
||||
*/
|
||||
boolean allowStringFolding;
|
||||
|
@ -3003,14 +3009,28 @@ public class JavacParser implements Parser {
|
|||
return defs.toList();
|
||||
}
|
||||
|
||||
/** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
|
||||
/** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
|
||||
* | Expression
|
||||
*/
|
||||
protected JCTree resource() {
|
||||
JCModifiers optFinal = optFinal(Flags.FINAL);
|
||||
JCExpression type = parseType();
|
||||
int pos = token.pos;
|
||||
Name ident = ident();
|
||||
return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
|
||||
int startPos = token.pos;
|
||||
if (token.kind == FINAL || token.kind == MONKEYS_AT) {
|
||||
JCModifiers mods = optFinal(Flags.FINAL);
|
||||
JCExpression t = parseType();
|
||||
return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
|
||||
}
|
||||
JCExpression t = term(EXPR | TYPE);
|
||||
if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
|
||||
JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
|
||||
return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
|
||||
} else {
|
||||
checkVariableInTryWithResources(startPos);
|
||||
if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
|
||||
log.error(t.pos(), "try.with.resources.expr.needs.var");
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
/** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
|
||||
|
@ -3933,6 +3953,12 @@ public class JavacParser implements Parser {
|
|||
allowTWR = true;
|
||||
}
|
||||
}
|
||||
void checkVariableInTryWithResources(int startPos) {
|
||||
if (!allowEffectivelyFinalVariablesInTWR) {
|
||||
error(startPos, "var.in.try.with.resources.not.supported.in.source", source.name);
|
||||
allowEffectivelyFinalVariablesInTWR = true;
|
||||
}
|
||||
}
|
||||
void checkLambda() {
|
||||
if (!allowLambda) {
|
||||
log.error(token.pos, "lambda.not.supported.in.source", source.name);
|
||||
|
|
|
@ -252,6 +252,14 @@ compiler.err.cant.assign.val.to.final.var=\
|
|||
compiler.err.cant.ref.non.effectively.final.var=\
|
||||
local variables referenced from {1} must be final or effectively final
|
||||
|
||||
compiler.err.try.with.resources.expr.needs.var=\
|
||||
the try-with-resources resource must either be a variable declaration or an expression denoting \
|
||||
a reference to a final or effectively final variable
|
||||
|
||||
# 0: symbol
|
||||
compiler.err.try.with.resources.expr.effectively.final.var=\
|
||||
variable {0} used as a try-with-resources resource neither final nor effectively final
|
||||
|
||||
|
||||
compiler.misc.lambda=\
|
||||
a lambda expression
|
||||
|
@ -2262,6 +2270,11 @@ compiler.err.try.with.resources.not.supported.in.source=\
|
|||
try-with-resources is not supported in -source {0}\n\
|
||||
(use -source 7 or higher to enable try-with-resources)
|
||||
|
||||
# 0: string
|
||||
compiler.err.var.in.try.with.resources.not.supported.in.source=\
|
||||
variables in try-with-resources not supported in -source {0}\n\
|
||||
(use -source 9 or higher to enable variables in try-with-resources)
|
||||
|
||||
compiler.warn.underscore.as.identifier=\
|
||||
''_'' used as an identifier\n\
|
||||
(use of ''_'' as an identifier might not be supported in releases after Java SE 8)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.type
|
||||
BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr
|
||||
1 error
|
||||
|
|
|
@ -13,6 +13,11 @@ public class ResDeclOutsideTry implements AutoCloseable {
|
|||
String test1() {
|
||||
try (tr1 = new ResDeclOutsideTry(); tr2;) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
ResDeclOutsideTry.java:14:17: compiler.err.expected: token.identifier
|
||||
ResDeclOutsideTry.java:14:48: compiler.err.expected: token.identifier
|
||||
2 errors
|
||||
ResDeclOutsideTry.java:14:18: compiler.err.try.with.resources.expr.needs.var
|
||||
1 error
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* @test /nodynamiccopyright/
|
||||
* @bug 7196163
|
||||
* @summary Verify that variables can be used as operands to try-with-resources
|
||||
* @compile/fail/ref=TwrForVariable1.out -source 8 -XDrawDiagnostics -Xlint:-options TwrForVariable1.java
|
||||
* @compile TwrForVariable1.java
|
||||
* @run main TwrForVariable1
|
||||
*/
|
||||
public class TwrForVariable1 implements AutoCloseable {
|
||||
private static int closeCount = 0;
|
||||
public static void main(String... args) {
|
||||
TwrForVariable1 v = new TwrForVariable1();
|
||||
|
||||
try (v) {
|
||||
assertCloseCount(0);
|
||||
}
|
||||
try (/**@deprecated*/v) {
|
||||
assertCloseCount(1);
|
||||
}
|
||||
try (v.finalWrapper.finalField) {
|
||||
assertCloseCount(2);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try (new TwrForVariable1() { }.finalWrapper.finalField) {
|
||||
assertCloseCount(3);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try ((args.length > 0 ? v : new TwrForVariable1()).finalWrapper.finalField) {
|
||||
assertCloseCount(4);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
throw new CloseableException();
|
||||
} catch (CloseableException ex) {
|
||||
try (ex) {
|
||||
assertCloseCount(5);
|
||||
}
|
||||
}
|
||||
|
||||
assertCloseCount(6);
|
||||
}
|
||||
|
||||
static void assertCloseCount(int expectedCloseCount) {
|
||||
if (closeCount != expectedCloseCount)
|
||||
throw new RuntimeException("bad closeCount: " + closeCount +
|
||||
"; expected: " + expectedCloseCount);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
closeCount++;
|
||||
}
|
||||
|
||||
final FinalWrapper finalWrapper = new FinalWrapper();
|
||||
|
||||
static class FinalWrapper {
|
||||
public final AutoCloseable finalField = new AutoCloseable() {
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
closeCount++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static class CloseableException extends Exception implements AutoCloseable {
|
||||
@Override
|
||||
public void close() {
|
||||
closeCount++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
TwrForVariable1.java:13:14: compiler.err.var.in.try.with.resources.not.supported.in.source: 1.8
|
||||
1 error
|
|
@ -0,0 +1,39 @@
|
|||
/* @test /nodynamiccopyright/
|
||||
* @bug 7196163
|
||||
* @summary Verify that an improper combination of modifiers and variable is rejected
|
||||
* in an operand to try-with-resources
|
||||
* @compile/fail/ref=TwrForVariable2.out -XDrawDiagnostics -Xlint:-options TwrForVariable2.java
|
||||
*/
|
||||
public class TwrForVariable2 implements AutoCloseable {
|
||||
public static void main(String... args) {
|
||||
TwrForVariable2 v = new TwrForVariable2();
|
||||
TwrForVariable3[] v2 = new TwrForVariable3[1];
|
||||
|
||||
try (final v) {
|
||||
fail("no modifiers before variables");
|
||||
}
|
||||
try (@Deprecated v) {
|
||||
fail("no annotations before variables");
|
||||
}
|
||||
try (v;;) {
|
||||
fail("illegal double semicolon");
|
||||
}
|
||||
try ((v)) {
|
||||
fail("parentheses not allowed");
|
||||
}
|
||||
try (v2[0]) {
|
||||
fail("array access not allowed");
|
||||
}
|
||||
try (args.length == 0 ? v : v) {
|
||||
fail("general expressions not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
static void fail(String reason) {
|
||||
throw new RuntimeException(reason);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
TwrForVariable2.java:12:21: compiler.err.expected: token.identifier
|
||||
TwrForVariable2.java:15:27: compiler.err.expected: token.identifier
|
||||
TwrForVariable2.java:18:16: compiler.err.illegal.start.of.expr
|
||||
TwrForVariable2.java:21:14: compiler.err.try.with.resources.expr.needs.var
|
||||
TwrForVariable2.java:24:16: compiler.err.try.with.resources.expr.needs.var
|
||||
TwrForVariable2.java:27:31: compiler.err.try.with.resources.expr.needs.var
|
||||
6 errors
|
|
@ -0,0 +1,29 @@
|
|||
/* @test /nodynamiccopyright/
|
||||
* @bug 7196163
|
||||
* @summary Verify that improper expressions used as an operand to try-with-resources are rejected.
|
||||
* @compile/fail/ref=TwrForVariable3.out -XDrawDiagnostics -Xlint:-options TwrForVariable3.java
|
||||
*/
|
||||
public class TwrForVariable3 implements AutoCloseable {
|
||||
public static void main(String... args) {
|
||||
TwrForVariable3 v1 = new TwrForVariable3();
|
||||
Object v2 = new Object();
|
||||
|
||||
try (v2) {
|
||||
fail("no an AutoCloseable");
|
||||
}
|
||||
try (java.lang.Object) {
|
||||
fail("not a variable access");
|
||||
}
|
||||
try (java.lang) {
|
||||
fail("not a variable access");
|
||||
}
|
||||
}
|
||||
|
||||
static void fail(String reason) {
|
||||
throw new RuntimeException(reason);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
TwrForVariable3.java:11:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable))
|
||||
TwrForVariable3.java:14:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null)
|
||||
TwrForVariable3.java:17:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null)
|
||||
3 errors
|
|
@ -0,0 +1,45 @@
|
|||
/* @test /nodynamiccopyright/
|
||||
* @bug 7196163
|
||||
* @summary Verify that variable used as an operand to try-with-resources is rejected if it is not
|
||||
* definitelly assigned before use and or not final or effectivelly final.
|
||||
* @compile/fail/ref=TwrForVariable4.out -XDrawDiagnostics -Xlint:-options TwrForVariable4.java
|
||||
*/
|
||||
public class TwrForVariable4 implements AutoCloseable {
|
||||
public static void main(String... args) {
|
||||
TwrForVariable4 uninitialized;
|
||||
|
||||
try (uninitialized) {
|
||||
fail("must be initialized before use");
|
||||
}
|
||||
uninitialized = new TwrForVariable4();
|
||||
|
||||
TwrForVariable4 notEffectivellyFinal1 = new TwrForVariable4();
|
||||
|
||||
notEffectivellyFinal1 = new TwrForVariable4();
|
||||
|
||||
try (notEffectivellyFinal1) {
|
||||
fail("not effectivelly final");
|
||||
}
|
||||
|
||||
TwrForVariable4 notEffectivellyFinal2 = new TwrForVariable4();
|
||||
|
||||
try (notEffectivellyFinal2) {
|
||||
notEffectivellyFinal2 = new TwrForVariable4();
|
||||
fail("not effectivelly final");
|
||||
}
|
||||
|
||||
try (notFinal) {
|
||||
fail("not final");
|
||||
}
|
||||
}
|
||||
|
||||
static TwrForVariable4 notFinal = new TwrForVariable4();
|
||||
|
||||
static void fail(String reason) {
|
||||
throw new RuntimeException(reason);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
TwrForVariable4.java:11:14: compiler.err.var.might.not.have.been.initialized: uninitialized
|
||||
TwrForVariable4.java:20:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal1
|
||||
TwrForVariable4.java:26:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal2
|
||||
TwrForVariable4.java:31:14: compiler.err.try.with.resources.expr.effectively.final.var: notFinal
|
||||
4 errors
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.try.with.resources.expr.effectively.final.var
|
||||
|
||||
class TryWithResourcesExprEffectivelyFinalVar {
|
||||
void m() {
|
||||
CloseableImpl ac = new CloseableImpl();
|
||||
|
||||
try (ac) {
|
||||
ac = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CloseableImpl implements AutoCloseable {
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.try.with.resources.expr.needs.var
|
||||
|
||||
class TryWithResourcesExprNeedsVar {
|
||||
void m() {
|
||||
try (new CloseableImpl()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CloseableImpl implements AutoCloseable {
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.var.in.try.with.resources.not.supported.in.source
|
||||
// key: compiler.warn.source.no.bootclasspath
|
||||
// options: -source 8
|
||||
|
||||
class VarInTryWithResourcesNotSupportedInSource {
|
||||
void m() {
|
||||
AutoCloseable ac = new CloseableImpl();
|
||||
|
||||
try (ac) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CloseableImpl implements AutoCloseable {
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue