Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_4_X b1896fead -> 9ff17a494


GROOVY-7876: ClassCastException when calling 
DefaultTypeTransformation#compareEqual (closes #368)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9ff17a49
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9ff17a49
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9ff17a49

Branch: refs/heads/GROOVY_2_4_X
Commit: 9ff17a494381a7532f4aa337926dc3ff51f5fd75
Parents: b1896fe
Author: paulk <pa...@asert.com.au>
Authored: Tue Jul 19 22:02:01 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Fri Jul 22 09:32:21 2016 +1000

----------------------------------------------------------------------
 .../typehandling/DefaultTypeTransformation.java |  9 ++++-
 src/test/groovy/bugs/Groovy7876Bug.groovy       | 39 ++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/9ff17a49/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
----------------------------------------------------------------------
diff --git 
a/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
 
b/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
index 95ddc00..bf9fe91 100644
--- 
a/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
+++ 
b/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
@@ -585,7 +585,14 @@ public class DefaultTypeTransformation {
                     || (right.getClass() != Object.class && 
right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
                     || (left instanceof GString && right instanceof String)) {
                 Comparable comparable = (Comparable) left;
-                return comparable.compareTo(right);
+                // GROOVY-7876: when comparing for equality we try to only 
call compareTo when an assignable
+                // relationship holds but with a container/holder class and 
because of erasure, we might still end
+                // up with the prospect of a ClassCastException which we want 
to ignore but only if testing equality
+                try {
+                    return comparable.compareTo(right);
+                } catch (ClassCastException cce) {
+                    if (!equalityCheckOnly) throw cce;
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/9ff17a49/src/test/groovy/bugs/Groovy7876Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7876Bug.groovy 
b/src/test/groovy/bugs/Groovy7876Bug.groovy
new file mode 100644
index 0000000..5ec368e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7876Bug.groovy
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package groovy.bugs
+
+class Groovy7876Bug extends GroovyTestCase {
+    void testClassCastExceptionsFromCompareToShouldNotLeakOutOfEqualityCheck() 
{
+        assertScript '''
+            enum E1 {A, B, C}
+            enum E2 {D, E, F}
+            class Holder<T> implements Comparable<T> {
+                final T thing
+                Holder(T thing) { this.thing = thing }
+                int compareTo(T other) { thing.compareTo(other.thing) }
+            }
+            def a = new Holder<E1>(E1.A)
+            def d = new Holder<E2>(E2.D)
+            assert E1.A != E2.D // control
+            assert a != d // invokes compareTo
+        '''
+    }
+}

Reply via email to