8004101: Add checks for method reference well-formedness
Bring method reference type-checking in sync with latest EDR Reviewed-by: jjg
This commit is contained in:
parent
0db60b7bb2
commit
c76c08e82a
@ -2458,7 +2458,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//attrib type-arguments
|
//attrib type-arguments
|
||||||
List<Type> typeargtypes = null;
|
List<Type> typeargtypes = List.nil();
|
||||||
if (that.typeargs != null) {
|
if (that.typeargs != null) {
|
||||||
typeargtypes = attribTypes(that.typeargs, localEnv);
|
typeargtypes = attribTypes(that.typeargs, localEnv);
|
||||||
}
|
}
|
||||||
@ -2528,6 +2528,26 @@ public class Attr extends JCTree.Visitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
|
||||||
|
if (refSym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) &&
|
||||||
|
exprType.getTypeArguments().nonEmpty()) {
|
||||||
|
//static ref with class type-args
|
||||||
|
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
|
||||||
|
diags.fragment("static.mref.with.targs"));
|
||||||
|
result = that.type = types.createErrorType(target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refSym.isStatic() && !TreeInfo.isStaticSelector(that.expr, names) &&
|
||||||
|
!lookupHelper.referenceKind(refSym).isUnbound()) {
|
||||||
|
//no static bound mrefs
|
||||||
|
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
|
||||||
|
diags.fragment("static.bound.mref"));
|
||||||
|
result = that.type = types.createErrorType(target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (desc.getReturnType() == Type.recoveryType) {
|
if (desc.getReturnType() == Type.recoveryType) {
|
||||||
// stop here
|
// stop here
|
||||||
result = that.type = target;
|
result = that.type = target;
|
||||||
|
@ -288,21 +288,20 @@ public class LambdaToMethod extends TreeTranslator {
|
|||||||
JCExpression init;
|
JCExpression init;
|
||||||
switch(tree.kind) {
|
switch(tree.kind) {
|
||||||
|
|
||||||
case IMPLICIT_INNER: /** Inner # new */
|
case IMPLICIT_INNER: /** Inner :: new */
|
||||||
case SUPER: /** super # instMethod */
|
case SUPER: /** super :: instMethod */
|
||||||
init = makeThis(
|
init = makeThis(
|
||||||
localContext.owner.owner.asType(),
|
localContext.owner.owner.asType(),
|
||||||
localContext.owner);
|
localContext.owner);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOUND: /** Expr # instMethod */
|
case BOUND: /** Expr :: instMethod */
|
||||||
init = tree.getQualifierExpression();
|
init = tree.getQualifierExpression();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATIC_EVAL: /** Expr # staticMethod */
|
case UNBOUND: /** Type :: instMethod */
|
||||||
case UNBOUND: /** Type # instMethod */
|
case STATIC: /** Type :: staticMethod */
|
||||||
case STATIC: /** Type # staticMethod */
|
case TOPLEVEL: /** Top level :: new */
|
||||||
case TOPLEVEL: /** Top level # new */
|
|
||||||
init = null;
|
init = null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -315,14 +314,6 @@ public class LambdaToMethod extends TreeTranslator {
|
|||||||
|
|
||||||
//build a sam instance using an indy call to the meta-factory
|
//build a sam instance using an indy call to the meta-factory
|
||||||
result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args);
|
result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args);
|
||||||
|
|
||||||
//if we had a static reference with non-static qualifier, add a let
|
|
||||||
//expression to force the evaluation of the qualifier expr
|
|
||||||
if (tree.hasKind(ReferenceKind.STATIC_EVAL)) {
|
|
||||||
VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
|
|
||||||
JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
|
|
||||||
result = make.LetExpr(recDef, result).setType(tree.type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2617,8 +2617,7 @@ public class Resolve {
|
|||||||
@Override
|
@Override
|
||||||
ReferenceKind referenceKind(Symbol sym) {
|
ReferenceKind referenceKind(Symbol sym) {
|
||||||
if (sym.isStatic()) {
|
if (sym.isStatic()) {
|
||||||
return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
|
return ReferenceKind.STATIC;
|
||||||
ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
|
|
||||||
} else {
|
} else {
|
||||||
Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
|
Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
|
||||||
return selName != null && selName == names._super ?
|
return selName != null && selName == names._super ?
|
||||||
|
@ -215,6 +215,12 @@ compiler.err.invalid.mref=\
|
|||||||
compiler.misc.invalid.mref=\
|
compiler.misc.invalid.mref=\
|
||||||
invalid {0} reference; {1}
|
invalid {0} reference; {1}
|
||||||
|
|
||||||
|
compiler.misc.static.mref.with.targs=\
|
||||||
|
parameterized qualifier on static method reference
|
||||||
|
|
||||||
|
compiler.misc.static.bound.mref=\
|
||||||
|
static bound method reference
|
||||||
|
|
||||||
# 0: symbol
|
# 0: symbol
|
||||||
compiler.err.cant.assign.val.to.final.var=\
|
compiler.err.cant.assign.val.to.final.var=\
|
||||||
cannot assign a value to final variable {0}
|
cannot assign a value to final variable {0}
|
||||||
|
@ -1829,8 +1829,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
STATIC(ReferenceMode.INVOKE, false),
|
STATIC(ReferenceMode.INVOKE, false),
|
||||||
/** Expr # instMethod */
|
/** Expr # instMethod */
|
||||||
BOUND(ReferenceMode.INVOKE, false),
|
BOUND(ReferenceMode.INVOKE, false),
|
||||||
/** Expr # staticMethod */
|
|
||||||
STATIC_EVAL(ReferenceMode.INVOKE, false),
|
|
||||||
/** Inner # new */
|
/** Inner # new */
|
||||||
IMPLICIT_INNER(ReferenceMode.NEW, false),
|
IMPLICIT_INNER(ReferenceMode.NEW, false),
|
||||||
/** Toplevel # new */
|
/** Toplevel # new */
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.invalid.mref
|
||||||
|
// key: compiler.misc.static.bound.mref
|
||||||
|
|
||||||
|
class StaticBoundMref {
|
||||||
|
|
||||||
|
Runnable r = new StaticBoundMref()::m;
|
||||||
|
|
||||||
|
static void m() { }
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.invalid.mref
|
||||||
|
// key: compiler.misc.static.mref.with.targs
|
||||||
|
|
||||||
|
class StaticMrefWithTargs<X> {
|
||||||
|
|
||||||
|
Runnable r = StaticMrefWithTargs<String>::m;
|
||||||
|
|
||||||
|
static void m() { }
|
||||||
|
}
|
@ -46,7 +46,7 @@ public class MethodReference30 {
|
|||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void m() { }
|
void m() { }
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SAM s = new MethodReference30()::m;
|
SAM s = new MethodReference30()::m;
|
||||||
|
45
langtools/test/tools/javac/lambda/MethodReference55.java
Normal file
45
langtools/test/tools/javac/lambda/MethodReference55.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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 8004101
|
||||||
|
* @summary Add checks for method reference well-formedness
|
||||||
|
* @compile/fail/ref=MethodReference55.out -XDrawDiagnostics MethodReference55.java
|
||||||
|
*/
|
||||||
|
class MethodReference55<X> {
|
||||||
|
|
||||||
|
interface V {
|
||||||
|
void m(Object o);
|
||||||
|
}
|
||||||
|
|
||||||
|
V v = new MethodReference55<String>()::m;
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
g(new MethodReference55<String>()::m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g(V v) { }
|
||||||
|
|
||||||
|
static void m(Object o) { };
|
||||||
|
}
|
3
langtools/test/tools/javac/lambda/MethodReference55.out
Normal file
3
langtools/test/tools/javac/lambda/MethodReference55.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MethodReference55.java:36:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
|
||||||
|
MethodReference55.java:39:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
|
||||||
|
2 errors
|
45
langtools/test/tools/javac/lambda/MethodReference56.java
Normal file
45
langtools/test/tools/javac/lambda/MethodReference56.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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 8004101
|
||||||
|
* @summary Add checks for method reference well-formedness
|
||||||
|
* @compile/fail/ref=MethodReference56.out -XDrawDiagnostics MethodReference56.java
|
||||||
|
*/
|
||||||
|
class MethodReference56<X> {
|
||||||
|
|
||||||
|
interface V {
|
||||||
|
void m(Object o);
|
||||||
|
}
|
||||||
|
|
||||||
|
V v = MethodReference56<String>::m;
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
g(MethodReference56<String>::m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g(V v) { }
|
||||||
|
|
||||||
|
static void m(Object o) { };
|
||||||
|
}
|
3
langtools/test/tools/javac/lambda/MethodReference56.out
Normal file
3
langtools/test/tools/javac/lambda/MethodReference56.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MethodReference56.java:36:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
|
||||||
|
MethodReference56.java:39:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
|
||||||
|
2 errors
|
@ -70,9 +70,6 @@ public class MethodRef1 {
|
|||||||
b = MethodRef1::foo; //static reference to foo(int)
|
b = MethodRef1::foo; //static reference to foo(int)
|
||||||
b.m(1);
|
b.m(1);
|
||||||
|
|
||||||
b = new MethodRef1()::foo; //instance reference to static methods, supported for now
|
|
||||||
b.m(1);
|
|
||||||
|
|
||||||
b = MethodRef1::bar; //static reference to bar(int)
|
b = MethodRef1::bar; //static reference to bar(int)
|
||||||
b.m(2);
|
b.m(2);
|
||||||
|
|
||||||
|
@ -133,15 +133,6 @@ public class SamConversion {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
assertTrue(false);
|
assertTrue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bar = new A()::method6;
|
|
||||||
try {
|
|
||||||
bar.m(1);
|
|
||||||
assertTrue(false);
|
|
||||||
} catch (MyException e) {
|
|
||||||
} catch (Exception e) {
|
|
||||||
assertTrue(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,20 +119,6 @@ public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup {
|
|||||||
assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
|
assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMRStaticEval() {
|
|
||||||
MethodReferenceTestKinds evalCheck;
|
|
||||||
S0 var = (evalCheck = inst("discard"))::staticMethod0;
|
|
||||||
assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
|
|
||||||
assertEquals(var.get(), "SM:0");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMRStaticEvalArg() {
|
|
||||||
MethodReferenceTestKinds evalCheck;
|
|
||||||
S1 var = (evalCheck = inst("discard"))::staticMethod1;
|
|
||||||
assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
|
|
||||||
assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMRTopLevel() {
|
public void testMRTopLevel() {
|
||||||
SN0 var = MethodReferenceTestKindsBase::new;
|
SN0 var = MethodReferenceTestKindsBase::new;
|
||||||
assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)");
|
assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)");
|
||||||
@ -142,17 +128,7 @@ public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup {
|
|||||||
SN1 var = MethodReferenceTestKindsBase::new;
|
SN1 var = MethodReferenceTestKindsBase::new;
|
||||||
assertEquals(var.make("name").toString(), "MethodReferenceTestKindsBase(name)");
|
assertEquals(var.make("name").toString(), "MethodReferenceTestKindsBase(name)");
|
||||||
}
|
}
|
||||||
/* unbound inner case not supported anymore (dropped by EG)
|
|
||||||
public void testMRUnboundInner() {
|
|
||||||
SXN0 var = MethodReferenceTestKinds.In::new;
|
|
||||||
assertEquals(var.make(inst("out")).toString(), "In(blank)");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMRUnboundInnerArg() {
|
|
||||||
SXN1 var = MethodReferenceTestKinds.In::new;
|
|
||||||
assertEquals(var.make(inst("out"), "name").toString(), "In(name)");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public void testMRImplicitInner() {
|
public void testMRImplicitInner() {
|
||||||
SN0 var = MethodReferenceTestKinds.In::new;
|
SN0 var = MethodReferenceTestKinds.In::new;
|
||||||
assertEquals(var.make().toString(), "In(blank)");
|
assertEquals(var.make().toString(), "In(blank)");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user