[m-rev.] for review: fix a bug in the C# implementation of array.shrink/3
Julien Fischer
jfischer at opturion.com
Thu Sep 5 16:28:33 AEST 2019
For review by Peter.
-------------------
Fix a bug in the C# implementation of array.shrink/3.
library/array.m:
Workaround the fact that C#'s 'is' operator has some fairly surprising
behaviour with arrays of integer types.
tests/hard_coded/array_primitives.{m,exp}:
tests/hard_coded/array_shrinks.{m,exp}:
Improve the coverage of these tests.
Julien.
diff --git a/library/array.m b/library/array.m
index 809f836..2bb3ff6 100644
--- a/library/array.m
+++ b/library/array.m
@@ -1184,47 +1184,55 @@ ML_shrink_array(System.Array arr, int Size)
{
if (arr == null) {
return null;
- } else if (arr is int[]) {
+ }
+
+ // We need to use Item here to determine the type instead of arr itself
+ // since both 'arr is int[]' and 'arr is uint[]' evaluate to true;
+ // similarly for the other integer types. (That behaviour is due to an
+ // inconsistency between the covariance of value-typed arrays in C# and
+ // the CLR.)
+ object Item = arr.GetValue(0);
+ if (Item is int) {
int[] tmp = (int[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is uint[]) {
+ } else if (Item is uint) {
uint[] tmp = (uint[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is sbyte[]) {
+ } else if (Item is sbyte) {
sbyte[] tmp = (sbyte[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is byte[]) {
+ } else if (Item is byte) {
byte[] tmp = (byte[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is short[]) {
+ } else if (Item is short) {
short[] tmp = (short[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is ushort[]) {
+ } else if (Item is ushort) {
ushort[] tmp = (ushort[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is long[]) {
+ } else if (Item is long) {
long[] tmp = (long[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is ulong[]) {
+ } else if (Item is ulong) {
ulong[] tmp = (ulong[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is double[]) {
+ } else if (Item is double) {
double[] tmp = (double[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is char[]) {
+ } else if (Item is char) {
char[] tmp = (char[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
- } else if (arr is bool[]) {
+ } else if (Item is bool) {
bool[] tmp = (bool[]) arr;
System.Array.Resize(ref tmp, Size);
return tmp;
diff --git a/tests/hard_coded/array_primitives.exp b/tests/hard_coded/array_primitives.exp
index a49b169..ec52536 100644
--- a/tests/hard_coded/array_primitives.exp
+++ b/tests/hard_coded/array_primitives.exp
@@ -70,3 +70,9 @@ generate = array(["foo", "foo", "foo", "foo", "foo"])
resize = array(["foo", "foo", "foo", "foo", "foo", "bar", "bar"])
shrink = array(["foo", "foo"])
+*** Testing with element type: list.list(int) ****
+init = array([[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]])
+generate = array([[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]])
+resize = array([[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [4], [4]])
+shrink = array([[1, 2, 3], [1, 2, 3]])
+
diff --git a/tests/hard_coded/array_primitives.m b/tests/hard_coded/array_primitives.m
index 8df63ea..c70300b 100644
--- a/tests/hard_coded/array_primitives.m
+++ b/tests/hard_coded/array_primitives.m
@@ -45,7 +45,8 @@ main(!IO) :-
do_test(2u, 3u, !IO),
do_test(2.0, 3.0, !IO),
- do_test("foo", "bar", !IO).
+ do_test("foo", "bar", !IO),
+ do_test([1, 2, 3], [4], !IO).
:- pred do_test(T::in, T::in, io::di, io::uo) is det.
diff --git a/tests/hard_coded/array_shrink.exp b/tests/hard_coded/array_shrink.exp
index f51004b..f31796f 100644
--- a/tests/hard_coded/array_shrink.exp
+++ b/tests/hard_coded/array_shrink.exp
@@ -19,6 +19,10 @@ Array0 = array([1, 2, 3, 4])
Size = 5
EXCEPTION: "predicate `array.shrink\'/3: Unexpected: cannot shrink to a larger size"
================
+Array0 = array([])
+Size = 0
+Array = array([])
+================
Array0 = array([1i8, 2i8, 3i8, 4i8])
Size = 3
Array = array([1i8, 2i8, 3i8])
diff --git a/tests/hard_coded/array_shrink.m b/tests/hard_coded/array_shrink.m
index 11a5956..5c5b4e6 100644
--- a/tests/hard_coded/array_shrink.m
+++ b/tests/hard_coded/array_shrink.m
@@ -37,6 +37,7 @@ main(!IO) :-
test_shrink([1, 2, 3, 4], 3, !IO),
test_shrink([1, 2, 3, 4], 4, !IO),
test_shrink([1, 2, 3, 4], 5, !IO), % Should raise exception.
+ test_shrink([] : list(int), 0, !IO),
test_shrink([1i8, 2i8, 3i8, 4i8], 3, !IO),
test_shrink([1u8, 2u8, 3u8, 4u8], 3, !IO),
test_shrink([1i16, 2i16, 3i16, 4i16], 3, !IO),
More information about the reviews
mailing list