# HG changeset patch # User vromero # Date 1361869459 0 # Node ID 92ba27b7aaf350da1783f8a0d45fd4342cfd3817 # Parent e586bfeb39c55cfc920126608ac92b0ff3953790 8008436: javac should not issue a warning for overriding equals without hasCode if hashCode has been overriden by a superclass Reviewed-by: jjg, mcimadamore diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java --- 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 implementation_filter = new Filter() { + public static final Filter implementation_filter = new Filter() { public boolean accepts(Symbol s) { return s.kind == Kinds.MTH && (s.flags() & SYNTHETIC) == 0; diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- 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); diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/src/share/classes/com/sun/tools/javac/comp/Check.java --- 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 equalsHasCodeFilter = new Filter() { + 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() { - 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); } } diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties --- 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. diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java --- 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; + } +} diff -r e586bfeb39c5 -r 92ba27b7aaf3 langtools/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out --- 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