Commit 4e380b89b8

Andrew Kelley <andrew@ziglang.org>
2024-11-23 00:30:07
std.mem: adjust semantics
* some kinds of types require comptime calls to eql * don't rely on compare equal for undefined
1 parent a3342ce
Changed files (1)
lib
lib/std/mem.zig
@@ -654,21 +654,14 @@ const eqlBytes_allowed = switch (builtin.zig_backend) {
     else => !builtin.fuzz,
 };
 
-/// Compares two slices and returns whether they are equal.
+/// Returns true if and only if the slices have the same length and all elements
+/// compare true using equality operator.
 pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
-    switch (@typeInfo(T)) {
-        .Type, .ComptimeInt, .ComptimeFloat => {
-            if (a.len != b.len) return false;
-            inline for (a, b) |a_elem, b_elem| {
-                if (a_elem != b_elem) return false;
-            }
-            return true;
-        },
-        .Null, .Undefined => return a.len == b.len,
-        else => {},
+    if (!@inComptime() and @sizeOf(T) != 0 and std.meta.hasUniqueRepresentation(T) and
+        eqlBytes_allowed)
+    {
+        return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
     }
-    if (@sizeOf(T) == 0) return a.len == b.len;
-    if (!@inComptime() and std.meta.hasUniqueRepresentation(T) and eqlBytes_allowed) return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
 
     if (a.len != b.len) return false;
     if (a.len == 0 or a.ptr == b.ptr) return true;
@@ -679,6 +672,25 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
     return true;
 }
 
+test eql {
+    try testing.expect(eql(u8, "abcd", "abcd"));
+    try testing.expect(!eql(u8, "abcdef", "abZdef"));
+    try testing.expect(!eql(u8, "abcdefg", "abcdef"));
+
+    comptime {
+        try testing.expect(eql(type, &.{ bool, f32 }, &.{ bool, f32 }));
+        try testing.expect(!eql(type, &.{ bool, f32 }, &.{ f32, bool }));
+        try testing.expect(!eql(type, &.{ bool, f32 }, &.{bool}));
+
+        try testing.expect(eql(comptime_int, &.{ 1, 2, 3 }, &.{ 1, 2, 3 }));
+        try testing.expect(!eql(comptime_int, &.{ 1, 2, 3 }, &.{ 3, 2, 1 }));
+        try testing.expect(!eql(comptime_int, &.{1}, &.{ 1, 2 }));
+    }
+
+    try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
+    try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
+}
+
 /// std.mem.eql heavily optimized for slices of bytes.
 fn eqlBytes(a: []const u8, b: []const u8) bool {
     comptime assert(eqlBytes_allowed);
@@ -3303,32 +3315,6 @@ test concat {
     }
 }
 
-test eql {
-    try testing.expect(eql(u8, "abcd", "abcd"));
-    try testing.expect(!eql(u8, "abcdef", "abZdef"));
-    try testing.expect(!eql(u8, "abcdefg", "abcdef"));
-
-    try testing.expect(eql(type, &.{ bool, f32 }, &.{ bool, f32 }));
-    try testing.expect(!eql(type, &.{ bool, f32 }, &.{ f32, bool }));
-    try testing.expect(!eql(type, &.{ bool, f32 }, &.{bool}));
-
-    try testing.expect(eql(comptime_int, &.{ 1, 2, 3 }, &.{ 1, 2, 3 }));
-    try testing.expect(!eql(comptime_int, &.{ 1, 2, 3 }, &.{ 3, 2, 1 }));
-    try testing.expect(!eql(comptime_int, &.{1}, &.{ 1, 2 }));
-
-    try testing.expect(eql(@TypeOf(undefined), &.{ undefined, undefined }, &.{ undefined, undefined }));
-    try testing.expect(!eql(@TypeOf(undefined), &.{undefined}, &.{ undefined, undefined }));
-
-    try testing.expect(eql(enum {}, &.{ undefined, undefined }, &.{ undefined, undefined }));
-    try testing.expect(!eql(enum {}, &.{undefined}, &.{ undefined, undefined }));
-
-    try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
-    try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
-
-    try testing.expect(eql(@TypeOf(null), &.{ null, null }, &.{ null, null }));
-    try testing.expect(!eql(@TypeOf(null), &.{null}, &.{ null, null }));
-}
-
 fn moreReadIntTests() !void {
     {
         const bytes = [_]u8{