| ... | ... | @@ -1454,6 +1454,8 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: |
| 1454 | 1454 | // Parsing some types won't have OutOfMemory in their |
| 1455 | 1455 | // error-sets, for the condition to be valid, merge it in. |
| 1456 | 1456 | if (@as(@TypeOf(err) || error{OutOfMemory}, err) == error.OutOfMemory) return err; |
| 1457 | // Bubble up AllocatorRequired, as it indicates missing option |
| 1458 | if (@as(@TypeOf(err) || error{AllocatorRequired}, err) == error.AllocatorRequired) return err; |
| 1457 | 1459 | // otherwise continue through the `inline for` |
| 1458 | 1460 | } |
| 1459 | 1461 | } |
| ... | ... | @@ -1741,18 +1743,6 @@ test "parse into tagged union" { |
| 1741 | 1743 | testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{})); |
| 1742 | 1744 | } |
| 1743 | 1745 | |
| 1744 | | { // if union matches string member, fails with NoUnionMembersMatched rather than AllocatorRequired |
| 1745 | | // Note that this behaviour wasn't necessarily by design, but was |
| 1746 | | // what fell out of the implementation and may result in interesting |
| 1747 | | // API breakage if changed |
| 1748 | | const T = union(enum) { |
| 1749 | | int: i32, |
| 1750 | | float: f64, |
| 1751 | | string: []const u8, |
| 1752 | | }; |
| 1753 | | testing.expectError(error.NoUnionMembersMatched, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); |
| 1754 | | } |
| 1755 | | |
| 1756 | 1746 | { // failing allocations should be bubbled up instantly without trying next member |
| 1757 | 1747 | var fail_alloc = testing.FailingAllocator.init(testing.allocator, 0); |
| 1758 | 1748 | const options = ParseOptions{ .allocator = &fail_alloc.allocator }; |
| ... | ... | @@ -1782,6 +1772,25 @@ test "parse into tagged union" { |
| 1782 | 1772 | } |
| 1783 | 1773 | } |
| 1784 | 1774 | |
| 1775 | test "parse union bubbles up AllocatorRequired" { |
| 1776 | { // string member first in union (and not matching) |
| 1777 | const T = union(enum) { |
| 1778 | string: []const u8, |
| 1779 | int: i32, |
| 1780 | }; |
| 1781 | testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("42"), ParseOptions{})); |
| 1782 | } |
| 1783 | |
| 1784 | { // string member not first in union (and matching) |
| 1785 | const T = union(enum) { |
| 1786 | int: i32, |
| 1787 | float: f64, |
| 1788 | string: []const u8, |
| 1789 | }; |
| 1790 | testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); |
| 1791 | } |
| 1792 | } |
| 1793 | |
| 1785 | 1794 | test "parseFree descends into tagged union" { |
| 1786 | 1795 | var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1); |
| 1787 | 1796 | const options = ParseOptions{ .allocator = &fail_alloc.allocator }; |