authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-22 15:30:07-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-22 15:30:07-08:00
log4e380b89b889912865f4de3cb0ee6b50f35d9605
treea60af3ec665382b95aed985b2222dd80739d2aa6
parenta3342cea188e1c006b20dd2e4712398f9e8c7fdd

std.mem: adjust semantics

* some kinds of types require comptime calls to eql * don't rely on compare equal for undefined

1 files changed, 25 insertions(+), 39 deletions(-)

lib/std/mem.zig+25-39
...@@ -654,21 +654,14 @@ const eqlBytes_allowed = switch (builtin.zig_backend) {...@@ -654,21 +654,14 @@ const eqlBytes_allowed = switch (builtin.zig_backend) {
654 else => !builtin.fuzz,654 else => !builtin.fuzz,
655};655};
656656
657/// Compares two slices and returns whether they are equal.657/// Returns true if and only if the slices have the same length and all elements
658/// compare true using equality operator.
658pub fn eql(comptime T: type, a: []const T, b: []const T) bool {659pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
659 switch (@typeInfo(T)) {660 if (!@inComptime() and @sizeOf(T) != 0 and std.meta.hasUniqueRepresentation(T) and
660 .Type, .ComptimeInt, .ComptimeFloat => {661 eqlBytes_allowed)
661 if (a.len != b.len) return false;662 {
662 inline for (a, b) |a_elem, b_elem| {663 return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
663 if (a_elem != b_elem) return false;
664 }
665 return true;
666 },
667 .Null, .Undefined => return a.len == b.len,
668 else => {},
669 }664 }
670 if (@sizeOf(T) == 0) return a.len == b.len;
671 if (!@inComptime() and std.meta.hasUniqueRepresentation(T) and eqlBytes_allowed) return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
672665
673 if (a.len != b.len) return false;666 if (a.len != b.len) return false;
674 if (a.len == 0 or a.ptr == b.ptr) return true;667 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 {...@@ -679,6 +672,25 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
679 return true;672 return true;
680}673}
681674
675test eql {
676 try testing.expect(eql(u8, "abcd", "abcd"));
677 try testing.expect(!eql(u8, "abcdef", "abZdef"));
678 try testing.expect(!eql(u8, "abcdefg", "abcdef"));
679
680 comptime {
681 try testing.expect(eql(type, &.{ bool, f32 }, &.{ bool, f32 }));
682 try testing.expect(!eql(type, &.{ bool, f32 }, &.{ f32, bool }));
683 try testing.expect(!eql(type, &.{ bool, f32 }, &.{bool}));
684
685 try testing.expect(eql(comptime_int, &.{ 1, 2, 3 }, &.{ 1, 2, 3 }));
686 try testing.expect(!eql(comptime_int, &.{ 1, 2, 3 }, &.{ 3, 2, 1 }));
687 try testing.expect(!eql(comptime_int, &.{1}, &.{ 1, 2 }));
688 }
689
690 try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
691 try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
692}
693
682/// std.mem.eql heavily optimized for slices of bytes.694/// std.mem.eql heavily optimized for slices of bytes.
683fn eqlBytes(a: []const u8, b: []const u8) bool {695fn eqlBytes(a: []const u8, b: []const u8) bool {
684 comptime assert(eqlBytes_allowed);696 comptime assert(eqlBytes_allowed);
...@@ -3303,32 +3315,6 @@ test concat {...@@ -3303,32 +3315,6 @@ test concat {
3303 }3315 }
3304}3316}
33053317
3306test eql {
3307 try testing.expect(eql(u8, "abcd", "abcd"));
3308 try testing.expect(!eql(u8, "abcdef", "abZdef"));
3309 try testing.expect(!eql(u8, "abcdefg", "abcdef"));
3310
3311 try testing.expect(eql(type, &.{ bool, f32 }, &.{ bool, f32 }));
3312 try testing.expect(!eql(type, &.{ bool, f32 }, &.{ f32, bool }));
3313 try testing.expect(!eql(type, &.{ bool, f32 }, &.{bool}));
3314
3315 try testing.expect(eql(comptime_int, &.{ 1, 2, 3 }, &.{ 1, 2, 3 }));
3316 try testing.expect(!eql(comptime_int, &.{ 1, 2, 3 }, &.{ 3, 2, 1 }));
3317 try testing.expect(!eql(comptime_int, &.{1}, &.{ 1, 2 }));
3318
3319 try testing.expect(eql(@TypeOf(undefined), &.{ undefined, undefined }, &.{ undefined, undefined }));
3320 try testing.expect(!eql(@TypeOf(undefined), &.{undefined}, &.{ undefined, undefined }));
3321
3322 try testing.expect(eql(enum {}, &.{ undefined, undefined }, &.{ undefined, undefined }));
3323 try testing.expect(!eql(enum {}, &.{undefined}, &.{ undefined, undefined }));
3324
3325 try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
3326 try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
3327
3328 try testing.expect(eql(@TypeOf(null), &.{ null, null }, &.{ null, null }));
3329 try testing.expect(!eql(@TypeOf(null), &.{null}, &.{ null, null }));
3330}
3331
3332fn moreReadIntTests() !void {3318fn moreReadIntTests() !void {
3333 {3319 {
3334 const bytes = [_]u8{3320 const bytes = [_]u8{