Browse Source

Check for zero-length slices in `slice.equal`

Feoramund 1 year ago
parent
commit
806c87d71d
2 changed files with 42 additions and 1 deletions
  1. 11 0
      core/slice/slice.odin
  2. 31 1
      tests/core/slice/test_core_slice.odin

+ 11 - 0
core/slice/slice.odin

@@ -200,6 +200,17 @@ equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) #no_
 		return false
 	}
 	when intrinsics.type_is_simple_compare(E) {
+		if len(a) == 0 {
+			// Empty slices are always equivalent to each other.
+			//
+			// This check is here in the event that a slice with a `data` of
+			// nil is compared against a slice with a non-nil `data` but a
+			// length of zero.
+			//
+			// In that case, `memory_compare` would return -1 or +1 because one
+			// of the pointers is nil.
+			return true
+		}
 		return runtime.memory_compare(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
 	} else {
 		for i in 0..<len(a) {

+ 31 - 1
tests/core/slice/test_core_slice.odin

@@ -275,4 +275,34 @@ test_unique :: proc(t: ^testing.T) {
 		delete(original)
 		delete(expected)
 	}
-}
+}
+
+@test
+test_compare_empty :: proc(t: ^testing.T) {
+	a := []int{}
+	b := []int{}
+	c: [dynamic]int = { 0 }
+	d: [dynamic]int = { 1 }
+	clear(&c)
+	clear(&d)
+	defer {
+		delete(c)
+		delete(d)
+	}
+
+	testing.expectf(t, len(a) == 0,
+		"Expected length of slice `a` to be zero")
+	testing.expectf(t, len(c) == 0,
+		"Expected length of dynamic array `c` to be zero")
+	testing.expectf(t, len(d) == 0,
+		"Expected length of dynamic array `d` to be zero")
+
+	testing.expectf(t, slice.equal(a, a),
+		"Expected empty slice to be equal to itself")
+	testing.expectf(t, slice.equal(a, b),
+		"Expected two different but empty stack-based slices to be equivalent")
+	testing.expectf(t, slice.equal(a, c[:]),
+		"Expected empty slice to be equal to slice of empty dynamic array")
+	testing.expectf(t, slice.equal(c[:], d[:]),
+		"Expected two separate empty slices of two dynamic arrays to be equal")
+}