8008436: javac should not issue a warning for overriding equals without hasCode if hashCode has been overriden by a superclass
Reviewed-by: jjg, mcimadamore
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Tue Feb 26 09:04:19 2013 +0000
@@ -1305,7 +1305,7 @@
return implementation(origin, types, checkResult, implementation_filter);
}
// where
- private static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
+ public static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
public boolean accepts(Symbol s) {
return s.kind == Kinds.MTH &&
(s.flags() & SYNTHETIC) == 0;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Feb 26 09:04:19 2013 +0000
@@ -3992,7 +3992,7 @@
attribClassBody(env, c);
chk.checkDeprecatedAnnotation(env.tree.pos(), c);
- chk.checkClassOverrideEqualsAndHash(c);
+ chk.checkClassOverrideEqualsAndHash(env.tree.pos(), c);
} finally {
env.info.returnResult = prevReturnRes;
log.useSource(prev);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Feb 26 09:04:19 2013 +0000
@@ -1964,28 +1964,29 @@
}
}
- public void checkClassOverrideEqualsAndHash(ClassSymbol someClass) {
+ private Filter<Symbol> equalsHasCodeFilter = new Filter<Symbol>() {
+ public boolean accepts(Symbol s) {
+ return MethodSymbol.implementation_filter.accepts(s) &&
+ (s.flags() & BAD_OVERRIDE) == 0;
+
+ }
+ };
+
+ public void checkClassOverrideEqualsAndHash(DiagnosticPosition pos,
+ ClassSymbol someClass) {
if (lint.isEnabled(LintCategory.OVERRIDES)) {
- boolean hasEquals = false;
- boolean hasHashCode = false;
-
- Scope.Entry equalsAtObject = syms.objectType.tsym.members().lookup(names.equals);
- Scope.Entry hashCodeAtObject = syms.objectType.tsym.members().lookup(names.hashCode);
- for (Symbol s: someClass.members().getElements(new Filter<Symbol>() {
- public boolean accepts(Symbol s) {
- return s.kind == Kinds.MTH &&
- (s.flags() & BAD_OVERRIDE) == 0;
- }
- })) {
- MethodSymbol m = (MethodSymbol)s;
- hasEquals |= m.name.equals(names.equals) &&
- m.overrides(equalsAtObject.sym, someClass, types, false);
-
- hasHashCode |= m.name.equals(names.hashCode) &&
- m.overrides(hashCodeAtObject.sym, someClass, types, false);
- }
- if (hasEquals && !hasHashCode) {
- log.warning(LintCategory.OVERRIDES, (DiagnosticPosition) null,
+ MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType
+ .tsym.members().lookup(names.equals).sym;
+ MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType
+ .tsym.members().lookup(names.hashCode).sym;
+
+ boolean overridesEquals = types.implementation(equalsAtObject,
+ someClass, false, equalsHasCodeFilter).owner == someClass;
+ boolean overridesHashCode = types.implementation(hashCodeAtObject,
+ someClass, false, equalsHasCodeFilter) != hashCodeAtObject;
+
+ if (overridesEquals && !overridesHashCode) {
+ log.warning(LintCategory.OVERRIDES, pos,
"override.equals.but.not.hashcode", someClass.fullname);
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Feb 26 09:04:19 2013 +0000
@@ -2071,8 +2071,7 @@
# 0: class name
compiler.warn.override.equals.but.not.hashcode=\
- Class {0}\n\
- overrides method equals but does not overrides method hashCode from Object
+ Class {0} overrides equals, but neither it nor any superclass overrides hashCode method
## The following are all possible strings for the first argument ({0}) of the
## above strings.
--- a/langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java Tue Feb 26 09:04:19 2013 +0000
@@ -1,22 +1,42 @@
/*
* @test /nodynamiccopyright/
- * @bug 6563143
+ * @bug 6563143 8008436
* @summary javac should issue a warning for overriding equals without hashCode
+ * @summary javac should not issue a warning for overriding equals without hasCode
+ * if hashCode has been overriden by a superclass
* @compile/ref=OverridesEqualsButNotHashCodeTest.out -Xlint:overrides -XDrawDiagnostics OverridesEqualsButNotHashCodeTest.java
*/
-@SuppressWarnings("overrides")
public class OverridesEqualsButNotHashCodeTest {
@Override
public boolean equals(Object o) {
return o == this;
}
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+}
+
+class SubClass extends OverridesEqualsButNotHashCodeTest {
+ @Override
+ public boolean equals(Object o) {
+ return o == this;
+ }
}
-class Other {
+@SuppressWarnings("overrides")
+class NoWarning {
@Override
public boolean equals(Object o) {
return o == this;
}
}
+class DoWarnMe {
+ @Override
+ public boolean equals(Object o) {
+ return o == this;
+ }
+}
--- a/langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out Sun Feb 24 11:36:58 2013 -0800
+++ b/langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out Tue Feb 26 09:04:19 2013 +0000
@@ -1,2 +1,2 @@
-- compiler.warn.override.equals.but.not.hashcode: Other
+OverridesEqualsButNotHashCodeTest.java:37:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe
1 warning