Search code examples
zig

Error to append a converted u8 (from i8) to an ArrayList, only in a specific program


I have to convert an i8 number to u8 (@intCast()), so that it is added to a ArrayList (I don't care how this conversion will be done if the number is negative).

Running this program with zig test intcast.zig it returns All 1 tests passed.:

const std = @import("std");

const SIZE = 30_000;

test "Convert i8 to u8" {
    var memory :[SIZE]i8 = [_]i8{65} ** SIZE;
    var memory_index: u32 = 10;
    var output = std.ArrayList(u8).init(std.heap.page_allocator);
    defer output.deinit();

    try output.append(@intCast(u8, memory[memory_index]));

    std.testing.expectEqualSlices(u8, "A", output.items);
}

But when I try to use the same procedure in another program, it doesn't work, the compiler returns me the following error:

≻ zig test bf.zig
./bf.zig:15:22: error: expected type '[30000]i8', found '@TypeOf(std.array_list.ArrayListAligned(u8,null).append).ReturnType.ErrorSet'
            '.' => { try output.append(@intCast(u8, memory[memory_index])); },

Here is the the program, and this is where I append the converted number:

for (program) |command| {
    switch (command) {
        '+' => { memory[memory_index] += 1; },
        '-' => { memory[memory_index] -= 1; },
        '.' => { try output.append(@intCast(u8, memory[memory_index])); },

Please, can anyone tell me what I'm doing wrong?

My zig is 0.6.0+8b82c4010.


Solution

  • This has nothing to do with the intCast, the issue is that the function's return type does not allow for a possible error

    fn execute(program: []const u8) [MEMORY_SIZE]i8 {
        for (program) |command| {
            switch (command) {
                '+' => { memory[memory_index] += 1; },
                '-' => { memory[memory_index] -= 1; },
                '.' => { try output.append(@intCast(u8, memory[memory_index])); },
    //                   ^^^ try wants to return an error, but
    //                       the function's return type is [30000]i8
    //                       which cannot be an error
        ...
    }
    

    Simple fix: allow the function to return an error

    fn execute(program: []const u8) ![MEMORY_SIZE]i8 {
    

    The error isn't very good for this right now, but if you look closely at the "found" type, something is trying to convert from @TypeOf(...).ReturnType.ErrorSet to [30000]i8 and that cannot be done. It is, however, possible to convert from @TypeOf(...).ReturnType.ErrorSet to ![30000]i8

    try something() is equivalent to something() catch |err| return err; which is where the type error is coming from.