Skip to content

Commit f863d7e

Browse files
committed
GROOVY-8983, GROOVY-8984
1 parent 81f32c2 commit f863d7e

File tree

7 files changed

+215
-6
lines changed

7 files changed

+215
-6
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+134
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,140 @@ public void testTypeChecked8909a() {
766766
"----------\n");
767767
}
768768

769+
@Test
770+
public void testTypeChecked8983() {
771+
//@formatter:off
772+
String[] sources = {
773+
"Main.groovy",
774+
"List<String> m() { ['foo'] }\n" +
775+
"@groovy.transform.TypeChecked\n" +
776+
"void test(Set<String> set) {\n" +
777+
" String[] one = m()\n" +
778+
" String[] two = set\n" +
779+
" print(one + two)\n" +
780+
"}\n" +
781+
"test(['bar'].toSet())\n",
782+
};
783+
//@formatter:on
784+
785+
runConformTest(sources, "[foo, bar]");
786+
}
787+
788+
@Test
789+
public void testTypeChecked8983a() {
790+
//@formatter:off
791+
String[] sources = {
792+
"Main.groovy",
793+
"List<String> m() { ['foo'] }\n" +
794+
"@groovy.transform.TypeChecked\n" +
795+
"void test(Set<String> set) {\n" +
796+
" CharSequence[] one = m()\n" +
797+
" CharSequence[] two = set\n" +
798+
" print(one + two)\n" +
799+
"}\n" +
800+
"test(['bar'].toSet())\n",
801+
};
802+
//@formatter:on
803+
804+
runConformTest(sources, "[foo, bar]");
805+
}
806+
807+
@Test
808+
public void testTypeChecked8983b() {
809+
//@formatter:off
810+
String[] sources = {
811+
"Main.groovy",
812+
"List<String> m() { ['foo'] }\n" +
813+
"@groovy.transform.TypeChecked\n" +
814+
"void test(Set<String> set) {\n" +
815+
" Object[] one = m()\n" +
816+
" Object[] two = set\n" +
817+
" print(one + two)\n" +
818+
"}\n" +
819+
"test(['bar'].toSet())\n",
820+
};
821+
//@formatter:on
822+
823+
runConformTest(sources, "[foo, bar]");
824+
}
825+
826+
@Test
827+
public void testTypeChecked8983c() {
828+
//@formatter:off
829+
String[] sources = {
830+
"Main.groovy",
831+
"List<? extends CharSequence> m() { ['foo'] }\n" +
832+
"@groovy.transform.TypeChecked\n" +
833+
"void test(Set<? extends CharSequence> set) {\n" +
834+
" CharSequence[] one = m()\n" +
835+
" CharSequence[] two = set\n" +
836+
" print(one + two)\n" +
837+
"}\n" +
838+
"test(['bar'].toSet())\n",
839+
};
840+
//@formatter:on
841+
842+
runConformTest(sources, "[foo, bar]");
843+
}
844+
845+
@Test
846+
public void testTypeChecked8984() {
847+
//@formatter:off
848+
String[] sources = {
849+
"Main.groovy",
850+
"List<? super CharSequence> m() { [null] }\n" +
851+
"@groovy.transform.TypeChecked\n" +
852+
"void test(Set<? super CharSequence> set) {\n" +
853+
" CharSequence[] one = m()\n" +
854+
" CharSequence[] two = set\n" +
855+
"}\n" +
856+
"test([null].toSet())\n",
857+
};
858+
//@formatter:on
859+
860+
runNegativeTest(sources,
861+
"----------\n" +
862+
"1. ERROR in Main.groovy (at line 4)\n" +
863+
"\tCharSequence[] one = m()\n" +
864+
"\t ^^^\n" +
865+
"Groovy:[Static type checking] - Cannot assign value of type java.util.List <? super java.lang.CharSequence> to variable of type java.lang.CharSequence[]\n" +
866+
"----------\n" +
867+
"2. ERROR in Main.groovy (at line 5)\n" +
868+
"\tCharSequence[] two = set\n" +
869+
"\t ^^^\n" +
870+
"Groovy:[Static type checking] - Cannot assign value of type java.util.Set <? super java.lang.CharSequence> to variable of type java.lang.CharSequence[]\n" +
871+
"----------\n");
872+
}
873+
874+
@Test
875+
public void testTypeChecked8984a() {
876+
//@formatter:off
877+
String[] sources = {
878+
"Main.groovy",
879+
"List<String> m() { ['foo'] }\n" +
880+
"@groovy.transform.TypeChecked\n" +
881+
"void test(Set<String> set) {\n" +
882+
" Number[] one = m()\n" +
883+
" Number[] two = set\n" +
884+
"}\n" +
885+
"test(['bar'].toSet())\n",
886+
};
887+
//@formatter:on
888+
889+
runNegativeTest(sources,
890+
"----------\n" +
891+
"1. ERROR in Main.groovy (at line 4)\n" +
892+
"\tNumber[] one = m()\n" +
893+
"\t ^^^\n" +
894+
"Groovy:[Static type checking] - Cannot assign value of type java.util.List <String> to variable of type java.lang.Number[]\n" +
895+
"----------\n" +
896+
"2. ERROR in Main.groovy (at line 5)\n" +
897+
"\tNumber[] two = set\n" +
898+
"\t ^^^\n" +
899+
"Groovy:[Static type checking] - Cannot assign value of type java.util.Set <String> to variable of type java.lang.Number[]\n" +
900+
"----------\n");
901+
}
902+
769903
@Test
770904
public void testTypeChecked9460() {
771905
//@formatter:off

base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode t
255255
}
256256
return target;
257257
}
258+
if (hint.isGenericsPlaceHolder()) {
259+
ClassNode bound = hint.redirect();
260+
return parameterizeType(bound, target);
261+
}
262+
if (target.redirect().getGenericsTypes() == null) {
263+
return target;
264+
}
258265
if (!target.equals(hint) && implementsInterfaceOrIsSubclassOf(target, hint)) {
259266
ClassNode nextSuperClass = ClassHelper.getNextSuperClass(target, hint);
260267
if (!hint.equals(nextSuperClass)) {
@@ -425,9 +432,9 @@ public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpe
425432
String name = type.getName();
426433
ret = genericsSpec.get(name);
427434
}
428-
// GRECLIPSE add -- GROOVY-9891
435+
// GRECLIPSE add -- GROOVY-8984, GROOVY-9891
429436
else if (type.isWildcard()) {
430-
ret = type.getLowerBound(); // use lower or upper
437+
//ret = type.getLowerBound(); // use lower or upper
431438
if (ret == null && type.getUpperBounds() != null) {
432439
ret = type.getUpperBounds()[0]; // ? supports 1
433440
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+18
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.codehaus.groovy.ast.expr.MapExpression;
3737
import org.codehaus.groovy.ast.expr.VariableExpression;
3838
import org.codehaus.groovy.ast.stmt.ReturnStatement;
39+
import org.codehaus.groovy.ast.tools.GeneralUtils;
3940
import org.codehaus.groovy.ast.tools.GenericsUtils;
4041
import org.codehaus.groovy.ast.tools.ParameterUtils;
4142
import org.codehaus.groovy.ast.tools.WideningCategories;
@@ -691,9 +692,26 @@ public static boolean checkCompatibleAssignmentTypes(ClassNode left, ClassNode r
691692
return checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), rightRedirect.getComponentType(), rightExpression, false);
692693
}
693694

695+
/* GRECLIPSE edit -- GROOVY-8983
694696
if (rightRedirect == VOID_TYPE || rightRedirect == void_WRAPPER_TYPE) {
695697
return leftRedirect == VOID_TYPE || leftRedirect == void_WRAPPER_TYPE;
696698
}
699+
*/
700+
if (rightRedirect == void_WRAPPER_TYPE) return leftRedirect == VOID_TYPE;
701+
if (rightRedirect == VOID_TYPE) return leftRedirect == void_WRAPPER_TYPE;
702+
703+
if (left.isArray()) {
704+
if (right.isArray()) {
705+
return checkCompatibleAssignmentTypes(left.getComponentType(), right.getComponentType(), rightExpression, false);
706+
}
707+
if (GeneralUtils.isOrImplements(right, Collection_TYPE) && !(rightExpression instanceof ListExpression)) {
708+
GenericsType elementType = GenericsUtils.parameterizeType(right, Collection_TYPE).getGenericsTypes()[0];
709+
return OBJECT_TYPE.equals(left.getComponentType()) // Object[] can accept any collection element type(s)
710+
|| (elementType.getLowerBound() == null && isCovariant(extractType(elementType), left.getComponentType()));
711+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GROOVY-8984: "? super T" is only compatible with an Object[] target
712+
}
713+
}
714+
// GRECLIPSE end
697715

698716
if (isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect)) {
699717
if (leftRedirect.equals(BigDecimal_TYPE) || leftRedirect.equals(Number_TYPE)) { // GRECLIPSE add -- GROOVY-9935

base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode t
251251
}
252252
return target;
253253
}
254+
if (hint.isGenericsPlaceHolder()) {
255+
ClassNode bound = hint.redirect();
256+
return parameterizeType(bound, target);
257+
}
258+
if (target.redirect().getGenericsTypes() == null) {
259+
return target;
260+
}
254261
if (!target.equals(hint) && implementsInterfaceOrIsSubclassOf(target, hint)) {
255262
ClassNode nextSuperClass = ClassHelper.getNextSuperClass(target, hint);
256263
if (!hint.equals(nextSuperClass)) {
@@ -421,9 +428,9 @@ public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpe
421428
String name = type.getName();
422429
ret = genericsSpec.get(name);
423430
}
424-
// GRECLIPSE add -- GROOVY-9891
431+
// GRECLIPSE add -- GROOVY-8984, GROOVY-9891
425432
else if (type.isWildcard()) {
426-
ret = type.getLowerBound(); // use lower or upper
433+
//ret = type.getLowerBound(); // use lower or upper
427434
if (ret == null && type.getUpperBounds() != null) {
428435
ret = type.getUpperBounds()[0]; // ? supports 1
429436
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+18
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.codehaus.groovy.ast.expr.MapExpression;
3838
import org.codehaus.groovy.ast.expr.VariableExpression;
3939
import org.codehaus.groovy.ast.stmt.ReturnStatement;
40+
import org.codehaus.groovy.ast.tools.GeneralUtils;
4041
import org.codehaus.groovy.ast.tools.GenericsUtils;
4142
import org.codehaus.groovy.ast.tools.ParameterUtils;
4243
import org.codehaus.groovy.ast.tools.WideningCategories;
@@ -654,13 +655,30 @@ public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final
654655
ClassNode rightRedirect = right.redirect();
655656
if (leftRedirect == rightRedirect) return true;
656657

658+
/* GRECLIPSE edit -- GROOVY-8983
657659
if (leftRedirect.isArray() && rightRedirect.isArray()) {
658660
return checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), rightRedirect.getComponentType(), rightExpression, false);
659661
}
660662
661663
if (rightRedirect == VOID_TYPE || rightRedirect == void_WRAPPER_TYPE) {
662664
return leftRedirect == VOID_TYPE || leftRedirect == void_WRAPPER_TYPE;
663665
}
666+
*/
667+
if (rightRedirect == void_WRAPPER_TYPE) return leftRedirect == VOID_TYPE;
668+
if (rightRedirect == VOID_TYPE) return leftRedirect == void_WRAPPER_TYPE;
669+
670+
if (left.isArray()) {
671+
if (right.isArray()) {
672+
return checkCompatibleAssignmentTypes(left.getComponentType(), right.getComponentType(), rightExpression, false);
673+
}
674+
if (GeneralUtils.isOrImplements(right, Collection_TYPE) && !(rightExpression instanceof ListExpression)) {
675+
GenericsType elementType = GenericsUtils.parameterizeType(right, Collection_TYPE).getGenericsTypes()[0];
676+
return OBJECT_TYPE.equals(left.getComponentType()) // Object[] can accept any collection element type(s)
677+
|| (elementType.getLowerBound() == null && isCovariant(extractType(elementType), left.getComponentType()));
678+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GROOVY-8984: "? super T" is only compatible with an Object[] target
679+
}
680+
}
681+
// GRECLIPSE end
664682

665683
if (isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect)) {
666684
if (leftRedirect.equals(BigDecimal_TYPE) || leftRedirect.equals(Number_TYPE)) { // GRECLIPSE add -- GROOVY-9935

base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode t
251251
}
252252
return target;
253253
}
254+
if (hint.isGenericsPlaceHolder()) {
255+
ClassNode bound = hint.redirect();
256+
return parameterizeType(bound, target);
257+
}
258+
if (target.redirect().getGenericsTypes() == null) {
259+
return target;
260+
}
254261
if (!target.equals(hint) && implementsInterfaceOrIsSubclassOf(target, hint)) {
255262
ClassNode nextSuperClass = ClassHelper.getNextSuperClass(target, hint);
256263
if (!hint.equals(nextSuperClass)) {
@@ -421,9 +428,9 @@ public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpe
421428
String name = type.getName();
422429
ret = genericsSpec.get(name);
423430
}
424-
// GRECLIPSE add -- GROOVY-9891
431+
// GRECLIPSE add -- GROOVY-8984, GROOVY-9891
425432
else if (type.isWildcard()) {
426-
ret = type.getLowerBound(); // use lower or upper
433+
//ret = type.getLowerBound(); // use lower or upper
427434
if (ret == null && type.getUpperBounds() != null) {
428435
ret = type.getUpperBounds()[0]; // ? supports 1
429436
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+18
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.codehaus.groovy.ast.expr.MapExpression;
3838
import org.codehaus.groovy.ast.expr.VariableExpression;
3939
import org.codehaus.groovy.ast.stmt.ReturnStatement;
40+
import org.codehaus.groovy.ast.tools.GeneralUtils;
4041
import org.codehaus.groovy.ast.tools.GenericsUtils;
4142
import org.codehaus.groovy.ast.tools.ParameterUtils;
4243
import org.codehaus.groovy.ast.tools.WideningCategories;
@@ -653,13 +654,30 @@ public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final
653654
ClassNode rightRedirect = right.redirect();
654655
if (leftRedirect == rightRedirect) return true;
655656

657+
/* GRECLIPSE edit -- GROOVY-8983
656658
if (leftRedirect.isArray() && rightRedirect.isArray()) {
657659
return checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), rightRedirect.getComponentType(), rightExpression, false);
658660
}
659661
660662
if (rightRedirect == VOID_TYPE || rightRedirect == void_WRAPPER_TYPE) {
661663
return leftRedirect == VOID_TYPE || leftRedirect == void_WRAPPER_TYPE;
662664
}
665+
*/
666+
if (rightRedirect == void_WRAPPER_TYPE) return leftRedirect == VOID_TYPE;
667+
if (rightRedirect == VOID_TYPE) return leftRedirect == void_WRAPPER_TYPE;
668+
669+
if (left.isArray()) {
670+
if (right.isArray()) {
671+
return checkCompatibleAssignmentTypes(left.getComponentType(), right.getComponentType(), rightExpression, false);
672+
}
673+
if (GeneralUtils.isOrImplements(right, Collection_TYPE) && !(rightExpression instanceof ListExpression)) {
674+
GenericsType elementType = GenericsUtils.parameterizeType(right, Collection_TYPE).getGenericsTypes()[0];
675+
return OBJECT_TYPE.equals(left.getComponentType()) // Object[] can accept any collection element type(s)
676+
|| (elementType.getLowerBound() == null && isCovariant(extractType(elementType), left.getComponentType()));
677+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GROOVY-8984: "? super T" is only compatible with an Object[] target
678+
}
679+
}
680+
// GRECLIPSE end
663681

664682
if (isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect)) {
665683
if (leftRedirect.equals(BigDecimal_TYPE) || leftRedirect.equals(Number_TYPE)) { // GRECLIPSE add -- GROOVY-9935

0 commit comments

Comments
 (0)