Commit bd801dc489

Borja Clemente <clebs@users.noreply.github.com>
2023-04-22 13:09:44
std: GPA deinit return an enum instead of a bool
1 parent 3f259d3
Changed files (4)
lib
test
standalone
windows_spawn
lib/std/heap/general_purpose_allocator.zig
@@ -155,6 +155,8 @@ pub const Config = struct {
     verbose_log: bool = false,
 };
 
+pub const Check = enum { ok, leak };
+
 pub fn GeneralPurposeAllocator(comptime config: Config) type {
     return struct {
         backing_allocator: Allocator = std.heap.page_allocator,
@@ -431,7 +433,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
         } else struct {};
 
         /// Returns true if there were leaks; false otherwise.
-        pub fn deinit(self: *Self) bool {
+        pub fn deinit(self: *Self) Check {
             const leaks = if (config.safety) self.detectLeaks() else false;
             if (config.retain_metadata) {
                 self.freeRetainedMetadata();
@@ -441,7 +443,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
                 self.small_allocations.deinit(self.backing_allocator);
             }
             self.* = undefined;
-            return leaks;
+            return @intToEnum(Check, @boolToInt(leaks));
         }
 
         fn collectStackTrace(first_trace_addr: usize, addresses: *[stack_n]usize) void {
@@ -1024,7 +1026,7 @@ const test_config = Config{};
 
 test "small allocations - free in same order" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var list = std.ArrayList(*u64).init(std.testing.allocator);
@@ -1043,7 +1045,7 @@ test "small allocations - free in same order" {
 
 test "small allocations - free in reverse order" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var list = std.ArrayList(*u64).init(std.testing.allocator);
@@ -1062,7 +1064,7 @@ test "small allocations - free in reverse order" {
 
 test "large allocations" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     const ptr1 = try allocator.alloc(u64, 42768);
@@ -1075,7 +1077,7 @@ test "large allocations" {
 
 test "very large allocation" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     try std.testing.expectError(error.OutOfMemory, allocator.alloc(u8, math.maxInt(usize)));
@@ -1083,7 +1085,7 @@ test "very large allocation" {
 
 test "realloc" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alignedAlloc(u8, @alignOf(u32), 1);
@@ -1105,7 +1107,7 @@ test "realloc" {
 
 test "shrink" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alloc(u8, 20);
@@ -1130,7 +1132,7 @@ test "shrink" {
 
 test "large object - grow" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice1 = try allocator.alloc(u8, page_size * 2 - 20);
@@ -1148,7 +1150,7 @@ test "large object - grow" {
 
 test "realloc small object to large object" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alloc(u8, 70);
@@ -1165,7 +1167,7 @@ test "realloc small object to large object" {
 
 test "shrink large object to large object" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alloc(u8, page_size * 2 + 50);
@@ -1190,7 +1192,7 @@ test "shrink large object to large object" {
 
 test "shrink large object to large object with larger alignment" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var debug_buffer: [1000]u8 = undefined;
@@ -1226,7 +1228,7 @@ test "shrink large object to large object with larger alignment" {
 
 test "realloc large object to small object" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alloc(u8, page_size * 2 + 50);
@@ -1244,7 +1246,7 @@ test "overrideable mutexes" {
         .backing_allocator = std.testing.allocator,
         .mutex = std.Thread.Mutex{},
     };
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     const ptr = try allocator.create(i32);
@@ -1253,7 +1255,7 @@ test "overrideable mutexes" {
 
 test "non-page-allocator backing allocator" {
     var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator };
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     const ptr = try allocator.create(i32);
@@ -1262,7 +1264,7 @@ test "non-page-allocator backing allocator" {
 
 test "realloc large object to larger alignment" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var debug_buffer: [1000]u8 = undefined;
@@ -1304,7 +1306,7 @@ test "realloc large object to larger alignment" {
 test "large object shrinks to small but allocation fails during shrink" {
     var failing_allocator = std.testing.FailingAllocator.init(std.heap.page_allocator, 3);
     var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = failing_allocator.allocator() };
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     var slice = try allocator.alloc(u8, page_size * 2 + 50);
@@ -1322,7 +1324,7 @@ test "large object shrinks to small but allocation fails during shrink" {
 
 test "objects of size 1024 and 2048" {
     var gpa = GeneralPurposeAllocator(test_config){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     const slice = try allocator.alloc(u8, 1025);
@@ -1334,7 +1336,7 @@ test "objects of size 1024 and 2048" {
 
 test "setting a memory cap" {
     var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){};
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     gpa.setRequestedMemoryLimit(1010);
@@ -1361,11 +1363,11 @@ test "setting a memory cap" {
 test "double frees" {
     // use a GPA to back a GPA to check for leaks of the latter's metadata
     var backing_gpa = GeneralPurposeAllocator(.{ .safety = true }){};
-    defer std.testing.expect(!backing_gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(backing_gpa.deinit() == .ok) catch @panic("leak");
 
     const GPA = GeneralPurposeAllocator(.{ .safety = true, .never_unmap = true, .retain_metadata = true });
     var gpa = GPA{ .backing_allocator = backing_gpa.allocator() };
-    defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
+    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
     const allocator = gpa.allocator();
 
     // detect a small allocation double free, even though bucket is emptied
lib/std/heap.zig
@@ -16,6 +16,7 @@ pub const LogToWriterAllocator = @import("heap/log_to_writer_allocator.zig").Log
 pub const logToWriterAllocator = @import("heap/log_to_writer_allocator.zig").logToWriterAllocator;
 pub const ArenaAllocator = @import("heap/arena_allocator.zig").ArenaAllocator;
 pub const GeneralPurposeAllocator = @import("heap/general_purpose_allocator.zig").GeneralPurposeAllocator;
+pub const Check = @import("heap/general_purpose_allocator.zig").Check;
 pub const WasmAllocator = @import("heap/WasmAllocator.zig");
 pub const WasmPageAllocator = @import("heap/WasmPageAllocator.zig");
 pub const PageAllocator = @import("heap/PageAllocator.zig");
lib/test_runner.zig
@@ -56,7 +56,7 @@ fn mainServer() !void {
             },
             .query_test_metadata => {
                 std.testing.allocator_instance = .{};
-                defer if (std.testing.allocator_instance.deinit()) {
+                defer if (std.testing.allocator_instance.deinit() == .leak) {
                     @panic("internal test runner memory leak");
                 };
 
@@ -108,7 +108,7 @@ fn mainServer() !void {
                         }
                     },
                 };
-                leak = std.testing.allocator_instance.deinit();
+                leak = std.testing.allocator_instance.deinit() == .leak;
                 try server.serveTestResults(.{
                     .index = index,
                     .flags = .{
@@ -148,7 +148,7 @@ fn mainTerminal() void {
     for (test_fn_list, 0..) |test_fn, i| {
         std.testing.allocator_instance = .{};
         defer {
-            if (std.testing.allocator_instance.deinit()) {
+            if (std.testing.allocator_instance.deinit() == .leak) {
                 leaks += 1;
             }
         }
test/standalone/windows_spawn/main.zig
@@ -4,7 +4,7 @@ const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;
 
 pub fn main() anyerror!void {
     var gpa = std.heap.GeneralPurposeAllocator(.{}){};
-    defer if (gpa.deinit()) @panic("found memory leaks");
+    defer if (gpa.deinit() == .leak) @panic("found memory leaks");
     const allocator = gpa.allocator();
 
     var it = try std.process.argsWithAllocator(allocator);