You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/05/19 16:11:48 UTC

[groovy] 02/03: GROOVY-10092: STC: cannot assign `boolean` to non-`boolean` primitives

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 83bca9c6d88f720a6a5b61074ed8cd9c77d2368b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed May 18 16:51:06 2022 -0500

    GROOVY-10092: STC: cannot assign `boolean` to non-`boolean` primitives
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 48 +++++++++++-----------
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 13 ++----
 2 files changed, 29 insertions(+), 32 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index a842fba3ea..b4a76624a8 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -121,9 +121,8 @@ import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
 import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
-import static org.codehaus.groovy.ast.tools.WideningCategories.isBigIntCategory;
 import static org.codehaus.groovy.ast.tools.WideningCategories.isFloatingCategory;
-import static org.codehaus.groovy.ast.tools.WideningCategories.isNumberCategory;
+import static org.codehaus.groovy.ast.tools.WideningCategories.isLongCategory;
 import static org.codehaus.groovy.ast.tools.WideningCategories.lowestUpperBound;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.closeQuietly;
@@ -691,22 +690,34 @@ public abstract class StaticTypeCheckingSupport {
         ClassNode rightRedirect = right.redirect();
         if (leftRedirect == rightRedirect) return true;
 
-        if (rightRedirect == void_WRAPPER_TYPE) return leftRedirect == VOID_TYPE;
-        if (rightRedirect == VOID_TYPE) return leftRedirect == void_WRAPPER_TYPE;
+        if (leftRedirect == VOID_TYPE) return rightRedirect == void_WRAPPER_TYPE;
+        if (leftRedirect == void_WRAPPER_TYPE) return rightRedirect == VOID_TYPE;
 
-        if (isNumberType(rightRedirect) || isNumberCategory(rightRedirect)) {
-            if (isBigDecimalType(leftRedirect) || Number_TYPE.equals(leftRedirect)) {
-                // any number can be assigned to BigDecimal or Number
+        if (isLongCategory(getUnwrapper(leftRedirect))) {
+            // byte, char, int, long or short can be assigned any base number
+            if (isNumberType(rightRedirect) /*|| rightRedirect == char_TYPE*/) {
                 return true;
             }
-            if (isBigIntegerType(leftRedirect)) {
-                return isBigIntCategory(getUnwrapper(rightRedirect)) || rightRedirect.isDerivedFrom(BigInteger_TYPE);
+        } else if (isFloatingCategory(getUnwrapper(leftRedirect))) {
+            // float or double can be assigned any base number type or BigDecimal
+            if (isNumberType(rightRedirect) || isBigDecimalType(rightRedirect)) {
+                return true;
+            }
+        } else if (isBigDecimalType(leftRedirect) || Number_TYPE.equals(leftRedirect)) {
+            // BigDecimal or Number can be assigned any derivitave of java.lang.Number
+            if (isNumberType(rightRedirect) || rightRedirect.isDerivedFrom(Number_TYPE)) {
+                return true;
+            }
+        } else if (isBigIntegerType(leftRedirect)) {
+            // BigInteger can be assigned byte, char, int, long, short or BigInteger
+            if (isLongCategory(getUnwrapper(rightRedirect)) || rightRedirect.isDerivedFrom(BigInteger_TYPE)) {
+                return true;
             }
+        } else if (isWildcardLeftHandSide(leftRedirect)) {
+            // Object, String, [Bb]oolean or Class can be assigned anything (except null to boolean)
+            return !(leftRedirect == boolean_TYPE && isNullConstant(rightExpression));
         }
 
-        // anything can be assigned to an Object, String, [Bb]oolean or Class receiver; except null to boolean
-        if (isWildcardLeftHandSide(left) && !(leftRedirect == boolean_TYPE && isNullConstant(rightExpression))) return true;
-
         if (leftRedirect == char_TYPE && rightRedirect == Character_TYPE) return true;
         if (leftRedirect == Character_TYPE && rightRedirect == char_TYPE) return true;
         if ((leftRedirect == char_TYPE || leftRedirect == Character_TYPE) && rightRedirect == STRING_TYPE) {
@@ -727,17 +738,8 @@ public abstract class StaticTypeCheckingSupport {
             return true;
         }
 
-        // simple check on being subclass
-        if (right.isDerivedFrom(left) || (left.isInterface() && right.implementsInterface(left))) return true;
-
-        // if left and right are primitives or numbers allow
-        if (isPrimitiveType(leftRedirect) && isPrimitiveType(rightRedirect)) return true;
-        if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) return true;
-
-        // left is a float/double and right is a BigDecimal
-        if (isFloatingCategory(leftRedirect) && isBigDecimalType(rightRedirect)) {
-            return true;
-        }
+        // simple sub-type check
+        if (!left.isInterface() ? right.isDerivedFrom(left) : GeneralUtils.isOrImplements(right, left)) return true;
 
         if (right.isDerivedFrom(CLOSURE_TYPE) && isSAMType(left)) {
             return true;
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index 7ec25953a8..45f0cd4a91 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -1104,15 +1104,10 @@ Printer
 
     // GROOVY-10092
     void testAssignBooleanValueToFloatLocalVariable() {
-        assertScript '''
-            class C {
-                void test() {
-                    float x = true // internal compiler error: Boolean cannot be cast to Number
-                }
-            }
-            //new C().test()
-            'TODO: STC error for incompatible assignment'
-        '''
+        shouldFailWithMessages '''
+            float x = true // internal compiler error: Boolean cannot be cast to Number
+        ''',
+        'Cannot assign value of type boolean to variable of type float'
     }
 
     // GROOVY-10424