authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-10 14:17:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-10 14:21:37-07:00
log9f163310f2bfa4f5289c1db6231089f3be0c9b93
treea3e6012d38c15d34c847773c27189c8a4f1edadb
parent569870ca41e73c64d8dc9f1eccfef3529caf2266

stage2: improve Type.eql and Type.hash for error sets

* Reduce branching in Type.eql and Type.hash for error sets. * `Type.eql` uses element-wise bytes comparison since it can rely on the error sets being pre-sorted. * Avoid unnecessarily skipping tests that are passing.

3 files changed, 43 insertions(+), 60 deletions(-)

src/type.zig+22-23
...@@ -556,37 +556,36 @@ pub const Type = extern union {...@@ -556,37 +556,36 @@ pub const Type = extern union {
556 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;556 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
557 },557 },
558558
559 .error_set_inferred => {
560 // Inferred error sets are only equal if both are inferred
561 // and they originate from the exact same function.
562 const a_set = a.castTag(.error_set_inferred).?.data;
563 const b_set = (b.castTag(.error_set_inferred) orelse return false).data;
564 return a_set.func == b_set.func;
565 },
566
567 .anyerror => {
568 return b.tag() == .anyerror;
569 },
570
559 .error_set,571 .error_set,
560 .error_set_single,572 .error_set_single,
561 .anyerror,
562 .error_set_inferred,
563 .error_set_merged,573 .error_set_merged,
564 => {574 => {
565 if (b.zigTypeTag() != .ErrorSet) return false;575 switch (b.tag()) {
566576 .error_set, .error_set_single, .error_set_merged => {},
567 // inferred error sets are only equal if both are inferred577 else => return false,
568 // and they originate from the exact same function.
569 if (a.castTag(.error_set_inferred)) |a_pl| {
570 if (b.castTag(.error_set_inferred)) |b_pl| {
571 return a_pl.data.func == b_pl.data.func;
572 }
573 return false;
574 }578 }
575 if (b.tag() == .error_set_inferred) return false;
576
577 // anyerror matches exactly.
578 const a_is_any = a.isAnyError();
579 const b_is_any = b.isAnyError();
580 if (a_is_any or b_is_any) return a_is_any and b_is_any;
581579
582 // two resolved sets match if their error set names match.580 // Two resolved sets match if their error set names match.
581 // Since they are pre-sorted we compare them element-wise.
583 const a_set = a.errorSetNames();582 const a_set = a.errorSetNames();
584 const b_set = b.errorSetNames();583 const b_set = b.errorSetNames();
585 if (a_set.len != b_set.len) return false;584 if (a_set.len != b_set.len) return false;
586 for (b_set) |b_val| {585 for (a_set) |a_item, i| {
587 if (!a.errorSetHasField(b_val)) return false;586 const b_item = b_set[i];
587 if (!std.mem.eql(u8, a_item, b_item)) return false;
588 }588 }
589
590 return true;589 return true;
591 },590 },
592591
...@@ -984,10 +983,10 @@ pub const Type = extern union {...@@ -984,10 +983,10 @@ pub const Type = extern union {
984983
985 .error_set_inferred => {984 .error_set_inferred => {
986 // inferred error sets are compared using their data pointer985 // inferred error sets are compared using their data pointer
987 const data = ty.castTag(.error_set_inferred).?.data.func;986 const set = ty.castTag(.error_set_inferred).?.data;
988 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorSet);987 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorSet);
989 std.hash.autoHash(hasher, Tag.error_set_inferred);988 std.hash.autoHash(hasher, Tag.error_set_inferred);
990 std.hash.autoHash(hasher, data);989 std.hash.autoHash(hasher, set.func);
991 },990 },
992991
993 .@"opaque" => {992 .@"opaque" => {
test/behavior/error.zig+21-35
...@@ -330,11 +330,11 @@ fn intLiteral(str: []const u8) !?i64 {...@@ -330,11 +330,11 @@ fn intLiteral(str: []const u8) !?i64 {
330}330}
331331
332test "nested error union function call in optional unwrap" {332test "nested error union function call in optional unwrap" {
333 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
334 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO333 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;334 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
338338
339 const S = struct {339 const S = struct {
340 const Foo = struct {340 const Foo = struct {
...@@ -381,9 +381,9 @@ test "nested error union function call in optional unwrap" {...@@ -381,9 +381,9 @@ test "nested error union function call in optional unwrap" {
381test "return function call to error set from error union function" {381test "return function call to error set from error union function" {
382 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
383 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO383 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;384 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
387387
388 const S = struct {388 const S = struct {
389 fn errorable() anyerror!i32 {389 fn errorable() anyerror!i32 {
...@@ -414,9 +414,9 @@ test "optional error set is the same size as error set" {...@@ -414,9 +414,9 @@ test "optional error set is the same size as error set" {
414test "nested catch" {414test "nested catch" {
415 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO415 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
416 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO416 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
417 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;417 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
420420
421 const S = struct {421 const S = struct {
422 fn entry() !void {422 fn entry() !void {
...@@ -440,14 +440,16 @@ test "nested catch" {...@@ -440,14 +440,16 @@ test "nested catch" {
440}440}
441441
442test "function pointer with return type that is error union with payload which is pointer of parent struct" {442test "function pointer with return type that is error union with payload which is pointer of parent struct" {
443 // This test uses the stage2 const fn pointer443 if (builtin.zig_backend == .stage1) {
444 if (builtin.zig_backend == .stage1) return error.SkipZigTest;444 // stage1 has wrong function pointer semantics
445 return error.SkipZigTest;
446 }
445447
446 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO448 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO449 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;450 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;452 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
451453
452 const S = struct {454 const S = struct {
453 const Foo = struct {455 const Foo = struct {
...@@ -501,9 +503,9 @@ test "return result loc as peer result loc in inferred error set function" {...@@ -501,9 +503,9 @@ test "return result loc as peer result loc in inferred error set function" {
501test "error payload type is correctly resolved" {503test "error payload type is correctly resolved" {
502 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO504 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO505 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;506 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
505 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;507 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
507509
508 const MyIntWrapper = struct {510 const MyIntWrapper = struct {
509 const Self = @This();511 const Self = @This();
...@@ -519,12 +521,6 @@ test "error payload type is correctly resolved" {...@@ -519,12 +521,6 @@ test "error payload type is correctly resolved" {
519}521}
520522
521test "error union comptime caching" {523test "error union comptime caching" {
522 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
523 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
525 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
527
528 const S = struct {524 const S = struct {
529 fn quux(comptime arg: anytype) void {525 fn quux(comptime arg: anytype) void {
530 arg catch {};526 arg catch {};
...@@ -571,12 +567,6 @@ test "error set equality" {...@@ -571,12 +567,6 @@ test "error set equality" {
571 // This tests using stage2 logic (#11022)567 // This tests using stage2 logic (#11022)
572 if (builtin.zig_backend == .stage1) return error.SkipZigTest;568 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
573569
574 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
577 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
579
580 const a = error{One};570 const a = error{One};
581 const b = error{One};571 const b = error{One};
582572
...@@ -592,11 +582,7 @@ test "error set equality" {...@@ -592,11 +582,7 @@ test "error set equality" {
592}582}
593583
594test "inferred error set equality" {584test "inferred error set equality" {
595 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
599 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
600586
601 const S = struct {587 const S = struct {
602 fn foo() !void {588 fn foo() !void {
test/behavior/type_info.zig-2
...@@ -209,10 +209,8 @@ test "type info: error set merged" {...@@ -209,10 +209,8 @@ test "type info: error set merged" {
209 if (builtin.zig_backend == .stage1) return error.SkipZigTest;209 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
210210
211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO212 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
214 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO213 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
215 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
216214
217 const TestSet = error{ One, Two } || error{Three};215 const TestSet = error{ One, Two } || error{Three};
218216