Skip to content

Commit ca78e44

Browse files
committed
Fix Painless def [char] to String casts (#39759)
* Start to fix def char casts. * Fix def char to String casts
1 parent 31e6f6c commit ca78e44

File tree

4 files changed

+107
-29
lines changed

4 files changed

+107
-29
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java

Lines changed: 88 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -625,8 +625,9 @@ public static boolean defToboolean(final Object value) {
625625
if (value instanceof Boolean) {
626626
return (boolean)value;
627627
} else {
628-
throw new ClassCastException(
629-
"cannot cast def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to boolean");
628+
throw new ClassCastException("cannot cast " +
629+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
630+
boolean.class.getCanonicalName());
630631
}
631632
}
632633

@@ -635,7 +636,8 @@ public static byte defTobyteImplicit(final Object value) {
635636
return (byte)value;
636637
} else {
637638
throw new ClassCastException("cannot implicitly cast " +
638-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to byte");
639+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
640+
byte.class.getCanonicalName());
639641
}
640642
}
641643

@@ -646,7 +648,8 @@ public static short defToshortImplicit(final Object value) {
646648
return (short)value;
647649
} else {
648650
throw new ClassCastException("cannot implicitly cast " +
649-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to short");
651+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
652+
short.class.getCanonicalName());
650653
}
651654
}
652655

@@ -655,7 +658,8 @@ public static char defTocharImplicit(final Object value) {
655658
return (char)value;
656659
} else {
657660
throw new ClassCastException("cannot implicitly cast " +
658-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to char");
661+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
662+
char.class.getCanonicalName());
659663
}
660664
}
661665

@@ -670,7 +674,8 @@ public static int defTointImplicit(final Object value) {
670674
return (int)value;
671675
} else {
672676
throw new ClassCastException("cannot implicitly cast " +
673-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to int");
677+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
678+
int.class.getCanonicalName());
674679
}
675680
}
676681

@@ -686,9 +691,9 @@ public static long defTolongImplicit(final Object value) {
686691
} else if (value instanceof Long) {
687692
return (long)value;
688693
} else {
689-
throw new ClassCastException(
690-
"cannot implicitly cast " +
691-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to long");
694+
throw new ClassCastException("cannot implicitly cast " +
695+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
696+
long.class.getCanonicalName());
692697
}
693698
}
694699

@@ -706,9 +711,9 @@ public static float defTofloatImplicit(final Object value) {
706711
} else if (value instanceof Float) {
707712
return (float)value;
708713
} else {
709-
throw new ClassCastException(
710-
"cannot implicitly cast " +
711-
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to float");
714+
throw new ClassCastException("cannot implicitly cast " +
715+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
716+
float.class.getCanonicalName());
712717
}
713718
}
714719

@@ -728,7 +733,9 @@ public static double defTodoubleImplicit(final Object value) {
728733
} else if (value instanceof Double) {
729734
return (double)value;
730735
} else {
731-
throw new ClassCastException("cannot implicitly cast def [" + value.getClass().getCanonicalName() + "] to double");
736+
throw new ClassCastException("cannot implicitly cast " +
737+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
738+
double.class.getCanonicalName());
732739
}
733740
}
734741

@@ -745,7 +752,9 @@ public static byte defTobyteExplicit(final Object value) {
745752
) {
746753
return ((Number)value).byteValue();
747754
} else {
748-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to byte");
755+
throw new ClassCastException("cannot explicitly cast " +
756+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
757+
byte.class.getCanonicalName());
749758
}
750759
}
751760

@@ -762,12 +771,16 @@ public static short defToshortExplicit(final Object value) {
762771
) {
763772
return ((Number)value).shortValue();
764773
} else {
765-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to short");
774+
throw new ClassCastException("cannot explicitly cast " +
775+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
776+
short.class.getCanonicalName());
766777
}
767778
}
768779

769780
public static char defTocharExplicit(final Object value) {
770-
if (value instanceof Character) {
781+
if (value instanceof String) {
782+
return Utility.StringTochar((String)value);
783+
} else if (value instanceof Character) {
771784
return (char)value;
772785
} else if (
773786
value instanceof Byte ||
@@ -779,7 +792,9 @@ public static char defTocharExplicit(final Object value) {
779792
) {
780793
return (char)((Number)value).intValue();
781794
} else {
782-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to char");
795+
throw new ClassCastException("cannot explicitly cast " +
796+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
797+
char.class.getCanonicalName());
783798
}
784799
}
785800

@@ -796,7 +811,9 @@ public static int defTointExplicit(final Object value) {
796811
) {
797812
return ((Number)value).intValue();
798813
} else {
799-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to int");
814+
throw new ClassCastException("cannot explicitly cast " +
815+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
816+
int.class.getCanonicalName());
800817
}
801818
}
802819

@@ -813,7 +830,9 @@ public static long defTolongExplicit(final Object value) {
813830
) {
814831
return ((Number)value).longValue();
815832
} else {
816-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to long");
833+
throw new ClassCastException("cannot explicitly cast " +
834+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
835+
long.class.getCanonicalName());
817836
}
818837
}
819838

@@ -830,7 +849,9 @@ public static float defTofloatExplicit(final Object value) {
830849
) {
831850
return ((Number)value).floatValue();
832851
} else {
833-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to float");
852+
throw new ClassCastException("cannot explicitly cast " +
853+
"float [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
854+
byte.class.getCanonicalName());
834855
}
835856
}
836857

@@ -847,7 +868,9 @@ public static double defTodoubleExplicit(final Object value) {
847868
) {
848869
return ((Number)value).doubleValue();
849870
} else {
850-
throw new ClassCastException("cannot explicitly cast def [" + value.getClass().getCanonicalName() + "] to double");
871+
throw new ClassCastException("cannot explicitly cast " +
872+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
873+
byte.class.getCanonicalName());
851874
}
852875
}
853876

@@ -982,7 +1005,8 @@ public static Double defToDoubleImplicit(final Object value) {
9821005
return (Double)value;
9831006
} else {
9841007
throw new ClassCastException("cannot implicitly cast " +
985-
"def [" + value.getClass().getCanonicalName() + "] to " + Double.class.getCanonicalName());
1008+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1009+
Double.class.getCanonicalName());
9861010
}
9871011
}
9881012

@@ -1002,7 +1026,8 @@ public static Byte defToByteExplicit(final Object value) {
10021026
return ((Number)value).byteValue();
10031027
} else {
10041028
throw new ClassCastException("cannot explicitly cast " +
1005-
"def [" + value.getClass().getCanonicalName() + "] to " + Byte.class.getCanonicalName());
1029+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1030+
Byte.class.getCanonicalName());
10061031
}
10071032
}
10081033

@@ -1022,13 +1047,16 @@ public static Short defToShortExplicit(final Object value) {
10221047
return ((Number)value).shortValue();
10231048
} else {
10241049
throw new ClassCastException("cannot explicitly cast " +
1025-
"def [" + value.getClass().getCanonicalName() + "] to " + Short.class.getCanonicalName());
1050+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1051+
Short.class.getCanonicalName());
10261052
}
10271053
}
10281054

10291055
public static Character defToCharacterExplicit(final Object value) {
10301056
if (value == null) {
10311057
return null;
1058+
} else if (value instanceof String) {
1059+
return Utility.StringTochar((String)value);
10321060
} else if (value instanceof Character) {
10331061
return (Character)value;
10341062
} else if (
@@ -1042,7 +1070,8 @@ public static Character defToCharacterExplicit(final Object value) {
10421070
return (char)((Number)value).intValue();
10431071
} else {
10441072
throw new ClassCastException("cannot explicitly cast " +
1045-
"def [" + value.getClass().getCanonicalName() + "] to " + Character.class.getCanonicalName());
1073+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1074+
Character.class.getCanonicalName());
10461075
}
10471076
}
10481077

@@ -1062,7 +1091,8 @@ public static Integer defToIntegerExplicit(final Object value) {
10621091
return ((Number)value).intValue();
10631092
} else {
10641093
throw new ClassCastException("cannot explicitly cast " +
1065-
"def [" + value.getClass().getCanonicalName() + "] to " + Integer.class.getCanonicalName());
1094+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1095+
Integer.class.getCanonicalName());
10661096
}
10671097
}
10681098

@@ -1082,7 +1112,8 @@ public static Long defToLongExplicit(final Object value) {
10821112
return ((Number)value).longValue();
10831113
} else {
10841114
throw new ClassCastException("cannot explicitly cast " +
1085-
"def [" + value.getClass().getCanonicalName() + "] to " + Long.class.getCanonicalName());
1115+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1116+
Long.class.getCanonicalName());
10861117
}
10871118
}
10881119

@@ -1102,7 +1133,8 @@ public static Float defToFloatExplicit(final Object value) {
11021133
return ((Number)value).floatValue();
11031134
} else {
11041135
throw new ClassCastException("cannot explicitly cast " +
1105-
"def [" + value.getClass().getCanonicalName() + "] to " + Float.class.getCanonicalName());
1136+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1137+
Float.class.getCanonicalName());
11061138
}
11071139
}
11081140

@@ -1122,7 +1154,34 @@ public static Double defToDoubleExplicit(final Object value) {
11221154
return ((Number)value).doubleValue();
11231155
} else {
11241156
throw new ClassCastException("cannot explicitly cast " +
1125-
"def [" + value.getClass().getCanonicalName() + "] to " + Double.class.getCanonicalName());
1157+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1158+
Double.class.getCanonicalName());
1159+
}
1160+
}
1161+
1162+
public static String defToStringImplicit(final Object value) {
1163+
if (value == null) {
1164+
return null;
1165+
} else if (value instanceof String) {
1166+
return (String)value;
1167+
} else {
1168+
throw new ClassCastException("cannot implicitly cast " +
1169+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1170+
String.class.getCanonicalName());
1171+
}
1172+
}
1173+
1174+
public static String defToStringExplicit(final Object value) {
1175+
if (value == null) {
1176+
return null;
1177+
} else if (value instanceof Character) {
1178+
return Utility.charToString((char)value);
1179+
} else if (value instanceof String) {
1180+
return (String)value;
1181+
} else {
1182+
throw new ClassCastException("cannot explicitly cast " +
1183+
"def [" + PainlessLookupUtility.typeToUnboxedType(value.getClass()).getCanonicalName() + "] to " +
1184+
String.class.getCanonicalName());
11261185
}
11271186
}
11281187

modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
import static org.elasticsearch.painless.WriterConstants.DEF_TO_P_LONG_IMPLICIT;
7070
import static org.elasticsearch.painless.WriterConstants.DEF_TO_P_SHORT_EXPLICIT;
7171
import static org.elasticsearch.painless.WriterConstants.DEF_TO_P_SHORT_IMPLICIT;
72+
import static org.elasticsearch.painless.WriterConstants.DEF_TO_STRING_EXPLICIT;
73+
import static org.elasticsearch.painless.WriterConstants.DEF_TO_STRING_IMPLICIT;
7274
import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE;
7375
import static org.elasticsearch.painless.WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE;
7476
import static org.elasticsearch.painless.WriterConstants.LAMBDA_BOOTSTRAP_HANDLE;
@@ -188,6 +190,7 @@ public void writeCast(PainlessCast cast) {
188190
else if (cast.targetType == Long.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_LONG_EXPLICIT);
189191
else if (cast.targetType == Float.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_FLOAT_EXPLICIT);
190192
else if (cast.targetType == Double.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_DOUBLE_EXPLICIT);
193+
else if (cast.targetType == String.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_STRING_EXPLICIT);
191194
else {
192195
writeCast(cast.originalType, cast.targetType);
193196
}
@@ -208,6 +211,7 @@ public void writeCast(PainlessCast cast) {
208211
else if (cast.targetType == Long.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_LONG_IMPLICIT);
209212
else if (cast.targetType == Float.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_FLOAT_IMPLICIT);
210213
else if (cast.targetType == Double.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_B_DOUBLE_IMPLICIT);
214+
else if (cast.targetType == String.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_STRING_IMPLICIT);
211215
else {
212216
writeCast(cast.originalType, cast.targetType);
213217
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ public final class WriterConstants {
158158
public static final Method DEF_TO_B_FLOAT_EXPLICIT = getAsmMethod(Float.class , "defToFloatExplicit" , Object.class);
159159
public static final Method DEF_TO_B_DOUBLE_EXPLICIT = getAsmMethod(Double.class , "defToDoubleExplicit" , Object.class);
160160

161+
public static final Method DEF_TO_STRING_IMPLICIT = getAsmMethod(String.class, "defToStringImplicit", Object.class);
162+
public static final Method DEF_TO_STRING_EXPLICIT = getAsmMethod(String.class, "defToStringExplicit", Object.class);
163+
161164
public static final Type DEF_ARRAY_LENGTH_METHOD_TYPE = Type.getMethodType(Type.INT_TYPE, Type.getType(Object.class));
162165

163166
/** invokedynamic bootstrap for lambda expression/method references */

modules/lang-painless/src/test/java/org/elasticsearch/painless/DefCastTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public void testdefToshortImplicit() {
8585
}
8686

8787
public void testdefTocharImplicit() {
88+
expectScriptThrows(ClassCastException.class, () -> exec("def d = 's'; char b = d;"));
8889
expectScriptThrows(ClassCastException.class, () -> exec("def d = 'string'; char b = d;"));
8990
expectScriptThrows(ClassCastException.class, () -> exec("def d = true; char b = d;"));
9091
expectScriptThrows(ClassCastException.class, () -> exec("def d = (byte)0; char b = d;"));
@@ -232,6 +233,7 @@ public void testdefToshortExplicit() {
232233
}
233234

234235
public void testdefTocharExplicit() {
236+
assertEquals('s', exec("def d = 's'; char b = (char)d; b"));
235237
expectScriptThrows(ClassCastException.class, () -> exec("def d = 'string'; char b = (char)d;"));
236238
expectScriptThrows(ClassCastException.class, () -> exec("def d = true; char b = (char)d;"));
237239
assertEquals((char)0, exec("def d = (byte)0; char b = (char)d; b"));
@@ -400,6 +402,7 @@ public void testdefToShortImplicit() {
400402
}
401403

402404
public void testdefToCharacterImplicit() {
405+
expectScriptThrows(ClassCastException.class, () -> exec("def d = 's'; Character b = d;"));
403406
expectScriptThrows(ClassCastException.class, () -> exec("def d = 'string'; Character b = d;"));
404407
expectScriptThrows(ClassCastException.class, () -> exec("def d = true; Character b = d;"));
405408
expectScriptThrows(ClassCastException.class, () -> exec("def d = (byte)0; Character b = d;"));
@@ -568,6 +571,7 @@ public void testdefToShortExplicit() {
568571
}
569572

570573
public void testdefToCharacterExplicit() {
574+
assertEquals('s', exec("def d = 's'; Character b = (Character)d; b"));
571575
expectScriptThrows(ClassCastException.class, () -> exec("def d = 'string'; Character b = (Character)d;"));
572576
expectScriptThrows(ClassCastException.class, () -> exec("def d = true; Character b = (Character)d;"));
573577
assertEquals((char)0, exec("def d = (byte)0; Character b = (Character)d; b"));
@@ -671,4 +675,12 @@ public void testdefToDoubleExplicit() {
671675
assertEquals((double)0, exec("def d = Double.valueOf(0); Double b = (Double)d; b"));
672676
expectScriptThrows(ClassCastException.class, () -> exec("def d = new ArrayList(); Double b = (Double)d;"));
673677
}
678+
679+
public void testdefToStringImplicit() {
680+
expectScriptThrows(ClassCastException.class, () -> exec("def d = (char)'s'; String b = d;"));
681+
}
682+
683+
public void testdefToStringExplicit() {
684+
assertEquals("s", exec("def d = (char)'s'; String b = (String)d; b"));
685+
}
674686
}

0 commit comments

Comments
 (0)