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
|
||||
List<Type> typeargtypes = null;
|
||||
List<Type> typeargtypes = List.nil();
|
||||
if (that.typeargs != null) {
|
||||
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) {
|
||||
// stop here
|
||||
result = that.type = target;
|
||||
|
@ -288,21 +288,20 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
JCExpression init;
|
||||
switch(tree.kind) {
|
||||
|
||||
case IMPLICIT_INNER: /** Inner # new */
|
||||
case SUPER: /** super # instMethod */
|
||||
case IMPLICIT_INNER: /** Inner :: new */
|
||||
case SUPER: /** super :: instMethod */
|
||||
init = makeThis(
|
||||
localContext.owner.owner.asType(),
|
||||
localContext.owner);
|
||||
break;
|
||||
|
||||
case BOUND: /** Expr # instMethod */
|
||||
case BOUND: /** Expr :: instMethod */
|
||||
init = tree.getQualifierExpression();
|
||||
break;
|
||||
|
||||
case STATIC_EVAL: /** Expr # staticMethod */
|
||||
case UNBOUND: /** Type # instMethod */
|
||||
case STATIC: /** Type # staticMethod */
|
||||
case TOPLEVEL: /** Top level # new */
|
||||
case UNBOUND: /** Type :: instMethod */
|
||||
case STATIC: /** Type :: staticMethod */
|
||||
case TOPLEVEL: /** Top level :: new */
|
||||
init = null;
|
||||
break;
|
||||
|
||||
@ -315,14 +314,6 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
|
||||
//build a sam instance using an indy call to the meta-factory
|
||||
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
|
||||
ReferenceKind referenceKind(Symbol sym) {
|
||||
if (sym.isStatic()) {
|
||||
return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
|
||||
ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
|
||||
return ReferenceKind.STATIC;
|
||||
} else {
|
||||
Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
|
||||
return selName != null && selName == names._super ?
|
||||
|
@ -215,6 +215,12 @@ compiler.err.invalid.mref=\
|
||||
compiler.misc.invalid.mref=\
|
||||
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
|
||||
compiler.err.cant.assign.val.to.final.var=\
|
||||
cannot assign a value to final variable {0}
|
||||
|
@ -1829,8 +1829,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
STATIC(ReferenceMode.INVOKE, false),
|
||||
/** Expr # instMethod */
|
||||
BOUND(ReferenceMode.INVOKE, false),
|
||||
/** Expr # staticMethod */
|
||||
STATIC_EVAL(ReferenceMode.INVOKE, false),
|
||||
/** Inner # new */
|
||||
IMPLICIT_INNER(ReferenceMode.NEW, false),
|
||||
/** 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);
|
||||
}
|
||||
|
||||
static void m() { }
|
||||
void m() { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
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.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.m(2);
|
||||
|
||||
|
@ -133,15 +133,6 @@ public class SamConversion {
|
||||
} catch (Exception e) {
|
||||
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)");
|
||||
}
|
||||
|
||||
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() {
|
||||
SN0 var = MethodReferenceTestKindsBase::new;
|
||||
assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)");
|
||||
@ -142,17 +128,7 @@ public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup {
|
||||
SN1 var = MethodReferenceTestKindsBase::new;
|
||||
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() {
|
||||
SN0 var = MethodReferenceTestKinds.In::new;
|
||||
assertEquals(var.make().toString(), "In(blank)");
|
||||
|
Loading…
x
Reference in New Issue
Block a user