Commit f88bb56ee5

daurnimator <quae@daurnimator.com>
2021-01-31 14:22:00
std.json union handling should bubble up AllocationRequired
1 parent 33c0a01
Changed files (1)
lib
lib/std/json.zig
@@ -1454,6 +1454,8 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
                         // Parsing some types won't have OutOfMemory in their
                         // error-sets, for the condition to be valid, merge it in.
                         if (@as(@TypeOf(err) || error{OutOfMemory}, err) == error.OutOfMemory) return err;
+                        // Bubble up AllocatorRequired, as it indicates missing option
+                        if (@as(@TypeOf(err) || error{AllocatorRequired}, err) == error.AllocatorRequired) return err;
                         // otherwise continue through the `inline for`
                     }
                 }
@@ -1741,18 +1743,6 @@ test "parse into tagged union" {
         testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{}));
     }
 
-    { // if union matches string member, fails with NoUnionMembersMatched rather than AllocatorRequired
-        // Note that this behaviour wasn't necessarily by design, but was
-        // what fell out of the implementation and may result in interesting
-        // API breakage if changed
-        const T = union(enum) {
-            int: i32,
-            float: f64,
-            string: []const u8,
-        };
-        testing.expectError(error.NoUnionMembersMatched, parse(T, &TokenStream.init("\"foo\""), ParseOptions{}));
-    }
-
     { // failing allocations should be bubbled up instantly without trying next member
         var fail_alloc = testing.FailingAllocator.init(testing.allocator, 0);
         const options = ParseOptions{ .allocator = &fail_alloc.allocator };
@@ -1782,6 +1772,25 @@ test "parse into tagged union" {
     }
 }
 
+test "parse union bubbles up AllocatorRequired" {
+    { // string member first in union (and not matching)
+        const T = union(enum) {
+            string: []const u8,
+            int: i32,
+        };
+        testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("42"), ParseOptions{}));
+    }
+
+    { // string member not first in union (and matching)
+        const T = union(enum) {
+            int: i32,
+            float: f64,
+            string: []const u8,
+        };
+        testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("\"foo\""), ParseOptions{}));
+    }
+}
+
 test "parseFree descends into tagged union" {
     var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1);
     const options = ParseOptions{ .allocator = &fail_alloc.allocator };