6476118: compiler bug causes runtime ClassCastException for generics overloading
Compiler allows bridge methods to override unrelated method Reviewed-by: jjg
This commit is contained in:
parent
e8d1ae243d
commit
929d3fd3f5
@ -495,6 +495,11 @@ public class Scope {
|
||||
return shadowed;
|
||||
}
|
||||
|
||||
public Entry next(Filter<Symbol> sf) {
|
||||
if (shadowed.sym == null || sf.accepts(shadowed.sym)) return shadowed;
|
||||
else return shadowed.next(sf);
|
||||
}
|
||||
|
||||
public Scope getOrigin() {
|
||||
// The origin is only recorded for import scopes. For all
|
||||
// other scope entries, the "enclosing" type is available
|
||||
|
@ -1103,18 +1103,24 @@ public abstract class Symbol implements Element {
|
||||
impl == null && is.nonEmpty();
|
||||
is = is.tail) {
|
||||
TypeSymbol i = is.head.tsym;
|
||||
for (Scope.Entry e = i.members().lookup(name);
|
||||
impl == null && e.scope != null;
|
||||
e = e.next()) {
|
||||
if (this.overrides(e.sym, (TypeSymbol)owner, types, true) &&
|
||||
// FIXME: I suspect the following requires a
|
||||
// subst() for a parametric return type.
|
||||
types.isSameType(type.getReturnType(),
|
||||
types.memberType(owner.type, e.sym).getReturnType())) {
|
||||
impl = e.sym;
|
||||
}
|
||||
if (impl == null)
|
||||
impl = implemented(i, types);
|
||||
impl = implementedIn(i, types);
|
||||
if (impl == null)
|
||||
impl = implemented(i, types);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
public Symbol implementedIn(TypeSymbol c, Types types) {
|
||||
Symbol impl = null;
|
||||
for (Scope.Entry e = c.members().lookup(name);
|
||||
impl == null && e.scope != null;
|
||||
e = e.next()) {
|
||||
if (this.overrides(e.sym, (TypeSymbol)owner, types, true) &&
|
||||
// FIXME: I suspect the following requires a
|
||||
// subst() for a parametric return type.
|
||||
types.isSameType(type.getReturnType(),
|
||||
types.memberType(owner.type, e.sym).getReturnType())) {
|
||||
impl = e.sym;
|
||||
}
|
||||
}
|
||||
return impl;
|
||||
|
@ -2026,7 +2026,7 @@ public class Types {
|
||||
TypeSymbol c = t.tsym;
|
||||
for (Scope.Entry e = c.members().lookup(ms.name, implFilter);
|
||||
e.scope != null;
|
||||
e = e.next()) {
|
||||
e = e.next(implFilter)) {
|
||||
if (e.sym != null &&
|
||||
e.sym.overrides(ms, origin, types, checkResult))
|
||||
return (MethodSymbol)e.sym;
|
||||
|
@ -676,6 +676,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
// If we override any other methods, check that we do so properly.
|
||||
// JLS ???
|
||||
chk.checkClashes(tree.pos(), env.enclClass.type, m);
|
||||
chk.checkOverride(tree, m);
|
||||
|
||||
// Create a new environment with local scope
|
||||
|
@ -1668,12 +1668,6 @@ public class Check {
|
||||
checkOverride(tree, m, (MethodSymbol)e.sym, origin);
|
||||
}
|
||||
}
|
||||
else if (!checkNameClash(origin, e.sym, m)) {
|
||||
log.error(tree,
|
||||
"name.clash.same.erasure.no.override",
|
||||
m, m.location(),
|
||||
e.sym, e.sym.location());
|
||||
}
|
||||
e = e.next();
|
||||
}
|
||||
}
|
||||
@ -2022,6 +2016,60 @@ public class Check {
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that all non-override equivalent methods accessible from 'site'
|
||||
* are mutually compatible (JLS 8.4.8/9.4.1).
|
||||
*
|
||||
* @param pos Position to be used for error reporting.
|
||||
* @param site The class whose methods are checked.
|
||||
* @param sym The method symbol to be checked.
|
||||
*/
|
||||
void checkClashes(DiagnosticPosition pos, Type site, Symbol sym) {
|
||||
List<Type> supertypes = types.closure(site);
|
||||
for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
|
||||
for (List<Type> m = supertypes; m.nonEmpty(); m = m.tail) {
|
||||
checkClashes(pos, l.head, m.head, site, sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Reports an error whenever 'sym' seen as a member of type 't1' clashes with
|
||||
* some unrelated method defined in 't2'.
|
||||
*/
|
||||
private void checkClashes(DiagnosticPosition pos, Type t1, Type t2, Type site, Symbol s1) {
|
||||
ClashFilter cf = new ClashFilter(site);
|
||||
s1 = ((MethodSymbol)s1).implementedIn(t1.tsym, types);
|
||||
if (s1 == null) return;
|
||||
Type st1 = types.memberType(site, s1);
|
||||
for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name, cf); e2.scope != null; e2 = e2.next(cf)) {
|
||||
Symbol s2 = e2.sym;
|
||||
if (s1 == s2) continue;
|
||||
Type st2 = types.memberType(site, s2);
|
||||
if (!types.overrideEquivalent(st1, st2) &&
|
||||
!checkNameClash((ClassSymbol)site.tsym, s1, s2)) {
|
||||
log.error(pos,
|
||||
"name.clash.same.erasure.no.override",
|
||||
s1, s1.location(),
|
||||
s2, s2.location());
|
||||
}
|
||||
}
|
||||
}
|
||||
//where
|
||||
private class ClashFilter implements Filter<Symbol> {
|
||||
|
||||
Type site;
|
||||
|
||||
ClashFilter(Type site) {
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
public boolean accepts(Symbol s) {
|
||||
return s.kind == MTH &&
|
||||
(s.flags() & SYNTHETIC) == 0 &&
|
||||
s.isInheritedIn(site.tsym, types) &&
|
||||
!s.isConstructor();
|
||||
}
|
||||
}
|
||||
|
||||
/** Report a conflict between a user symbol and a synthetic symbol.
|
||||
*/
|
||||
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
|
||||
|
16
langtools/test/tools/javac/generics/6476118/T6476118a.java
Normal file
16
langtools/test/tools/javac/generics/6476118/T6476118a.java
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 6476118
|
||||
* @summary compiler bug causes runtime ClassCastException for generics overloading
|
||||
* @compile/fail/ref=T6476118a.out -XDrawDiagnostics T6476118a.java
|
||||
*/
|
||||
|
||||
class T6476118a {
|
||||
static class A {
|
||||
public int compareTo(Object o) { return 0; }
|
||||
}
|
||||
|
||||
static class B extends A implements Comparable<B>{
|
||||
public int compareTo(B b){ return 0; }
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
T6476118a.java:14:20: compiler.err.name.clash.same.erasure.no.override: compareTo(T), java.lang.Comparable, compareTo(java.lang.Object), T6476118a.A
|
||||
1 error
|
14
langtools/test/tools/javac/generics/6476118/T6476118b.java
Normal file
14
langtools/test/tools/javac/generics/6476118/T6476118b.java
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 6476118 6533652
|
||||
* @summary compiler bug causes runtime ClassCastException for generics overloading
|
||||
* @compile/fail/ref=T6476118b.out -XDrawDiagnostics T6476118b.java
|
||||
*/
|
||||
|
||||
class T6476118b {
|
||||
public final int compareTo(Object o) { return 0; }
|
||||
|
||||
static class B extends T6476118b implements Comparable<B> {
|
||||
public int compareTo(B b){ return 0; }
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
T6476118b.java:12:20: compiler.err.name.clash.same.erasure.no.override: compareTo(T), java.lang.Comparable, compareTo(java.lang.Object), T6476118b
|
||||
1 error
|
23
langtools/test/tools/javac/generics/6476118/T6476118c.java
Normal file
23
langtools/test/tools/javac/generics/6476118/T6476118c.java
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 6476118
|
||||
* @summary compiler bug causes runtime ClassCastException for generics overloading
|
||||
* @compile/fail/ref=T6476118c.out -XDrawDiagnostics T6476118c.java
|
||||
*/
|
||||
|
||||
class T6476118b {
|
||||
static class A<T> {
|
||||
public void foo(T t) { }
|
||||
}
|
||||
|
||||
static class B<T extends Number> extends A<T> {
|
||||
public void foo(T t) { }
|
||||
}
|
||||
|
||||
static class C extends B<Integer> {
|
||||
public void foo(Object o) { }
|
||||
public void foo(Number o) { }
|
||||
}
|
||||
|
||||
static class D extends C {} //check that no spurious diags generated here!
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
T6476118c.java:18:21: compiler.err.name.clash.same.erasure.no.override: foo(java.lang.Object), T6476118b.C, foo(T), T6476118b.A
|
||||
T6476118c.java:19:21: compiler.err.name.clash.same.erasure.no.override: foo(java.lang.Number), T6476118b.C, foo(T), T6476118b.B
|
||||
2 errors
|
39
langtools/test/tools/javac/generics/6476118/T6476118d.java
Normal file
39
langtools/test/tools/javac/generics/6476118/T6476118d.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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 6476118
|
||||
* @summary compiler bug causes runtime ClassCastException for generics overloading
|
||||
* @compile T6476118d.java
|
||||
*/
|
||||
|
||||
class T6476118d {
|
||||
int m = 3;
|
||||
|
||||
interface m { }
|
||||
|
||||
int m () {
|
||||
return m;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user