zig icon indicating copy to clipboard operation
zig copied to clipboard

type coercion malfunction: false "expected type x, found y"

Open ssmid opened this issue 1 year ago • 2 comments

Edit: Please see comment # 2 for a shorter code version.

Zig Version

0.11.0-dev.3395+1e7dcaa3a

Steps to Reproduce and Observed Behavior

I'm currently trying to port an interpreter from C to Zig, this is part of the lexer. It's pretty much the shortest reproducer I could make. If I can provide any more information, I'll happily do so.

Please note the two comments in the middle, which mark ways to successfully compile it.

Code

const std = @import("std");

var _gpallocator = std.heap.GeneralPurposeAllocator(.{}){};
pub const allocator = _gpallocator.allocator();

pub const Value = union {
    i: i64,
    f: f64,
};

pub fn get_first_value(source: []const u8) !Value {
    var value = Value{ .i = 0 };
    var start: usize = 0;
    var next: usize = 1;
    var c = source[start];
    var n = source[next];

    // parse number
    if (is_num(c)) {
        while (is_num(n)) {
            next += 1;
            n = source[next];
        }
        const ivalue: u64 = parse_positive_int(source[start..next]);
        //const ivalue: u64 = 0;  // with this line it compiles...
        if (n == '.') {
            next += 1;
            n = source[next];
            // assumed: is_num(n) == true
            const frac_start: usize = next;
            while (is_num(n)) {
                next += 1;
                n = source[next];
            }
            const frac_str: []const u8 = source[frac_start..next];
            value = .{ .f = try parse_float_frac(ivalue, frac_str) };
        } else {
            // when this branch is removed it also compiles
            value = .{ .i = @as(i64, ivalue) };
        }
    }
    return value;
}

pub fn is_num(c: u8) bool {
    return '0' <= c and c <= '9';
}

pub fn parse_positive_int(str: []const u8) u64 {
    var value: u64 = 0;
    var exponent: u64 = 1;
    var i = str.len;
    while (i > 0) {
        i -= 1;
        value += (str[i] - '0') * exponent;
        exponent *= 10;
    }
    return value;
}

pub fn parse_float_frac(intpart: u64, start: []const u8) !f64 {
    const frac_int = @intToFloat(f64, parse_positive_int(start));
    const frac_value = frac_int / @intToFloat(f64, try std.math.powi(u64, 10, start.len));
    return @intToFloat(f64, intpart) + frac_value;
}

pub fn main() !void {
    const value = try get_first_value("0.123 + 0.321\n");
    std.debug.print("{d}\n", .{value.f});
}

Output:

$ ./zig run src/lex_test.zig
src/lex_test.zig:35:48: error: expected type 'i64', found 'u64'
            const frac_str: []const u8 = source[frac_start..next];
                                         ~~~~~~^~~~~~~~~~~~~~~~~~
src/lex_test.zig:35:48: note: signed 64-bit int cannot represent all possible unsigned 64-bit values
referenced by:
    main: src/lex_test.zig:68:23
    callMain: zig-fresh/lib/zig/std/start.zig:609:32
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Debug output:

compile error during Sema:
src/lex_test.zig:35:48: error: expected type 'i64', found 'u64'
            const frac_str: []const u8 = source[frac_start..next];
                                         ~~~~~~^~~~~~~~~~~~~~~~~~
src/lex_test.zig:35:48: note: signed 64-bit int cannot represent all possible unsigned 64-bit values
thread 375981 panic: unexpected compile error occurred
Analyzing src/lex_test.zig: lex_test.zig:get_first_value
      %223 = dbg_block_begin()
      %224 = dbg_stmt(29, 13)
      %225 = field_base_ptr(%30) node_offset:39:21 to :39:47
      %226 = field_ptr_init(%225, "i") node_offset:39:29 to :39:45
    > %229 = as(@Zir.Inst.Ref.i64_type, %128)
      %230 = store_node(%226, %229) node_offset:39:38 to :39:44
      %231 = validate_struct_init({
        %226 = field_ptr_init(%225, "i") node_offset:39:29 to :39:45
      }) node_offset:39:21 to :39:47
      %232 = dbg_block_end()
      %233 = restore_err_ret_index(%222, @Zir.Inst.Ref.none)
      %234 = break(%222, @Zir.Inst.Ref.void_value)
    For full context, use the command
      zig ast-check -t src/lex_test.zig

  in src/lex_test.zig: lex_test.zig:get_first_value
    > %222 = block({%223..%234}) node_offset:37:16 to :37:17
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %135 = condbr(%134, {%137..%236}, {%221..%237}) node_offset:26:9 to :26:11
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %136 = block({%131..%135}) node_offset:26:9 to :26:11
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %77 = block({%78..%241}) node_offset:19:20 to :19:21
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %74 = condbr(%73, {%76..%243}, {%244}) node_offset:19:5 to :19:7
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %75 = block({%68..%74}) node_offset:19:5 to :19:7
  in src/lex_test.zig: lex_test.zig:get_first_value
    > %27 = block({%28..%255}) node_offset:11:51 to :11:52
  in src/lex_test.zig: lex_test.zig:main
    > %437 = try(%434, {%438..%440}) node_offset:68:19 to :68:57
  in src/lex_test.zig: lex_test.zig:main
    > %427 = block({%428..%459}) node_offset:67:21 to :67:22
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMain
    > %3049 = is_non_err(%3048) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMain
    > %3051 = block({%3045..%3050}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMain
    > %3042 = block({%3043..%3192}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMain
    > %2947 = switch_block(%2944,
        else => {%3195..%3201},
        %2949 => {%2950..%2962},
        %2964 => {%2965..%2983},
        %2986 => {%2984..%3038},
        %3040 => {%3041..%3194}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMain
    > %2929 = block({%2930..%3205}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:initEventLoopAndCallMain
    > %2650 = builtin_call(%2648, %2649, @Zir.Inst.Ref.empty_struct) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:initEventLoopAndCallMain
    > %2497 = block({%2498..%2658}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMainWithArgs
    > %2273 = call(.auto, %2271, []) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:callMainWithArgs
    > %2236 = block({%2237..%2281}) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:posixCallMainAndExit
    > %2100 = builtin_call(%2097, %2098, %2099) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:posixCallMainAndExit
    > %2096 = field_call(nodiscard .auto, %2093, exit, [
        {%2097..%2101},
      ]) 
  in zig-fresh/lib/zig/std/start.zig: start.zig:posixCallMainAndExit
    > %1689 = block({%1690..%2104}) 

/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:2224:35: 0x5c6f8e8 in failWithOwnedErrorMsg (zig)
        crash_report.compilerPanic("unexpected compile error occurred", null, null);
                                  ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:26151:38: 0x5e861fd in coerceExtra (zig)
    return sema.failWithOwnedErrorMsg(msg);
                                     ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:9488:28: 0x663991d in analyzeAs (zig)
    return sema.coerceExtra(block, dest_ty, operand, src, .{ .is_ret = is_ret, .no_cast_to_comptime_int = no_cast_to_comptime_int }) catch |err| switch (err) {
                           ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:9443:26: 0x60fe083 in zirAs (zig)
    return sema.analyzeAs(block, sema.src, bin_inst.lhs, bin_inst.rhs, false);
                         ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:911:60: 0x5e51a8a in analyzeBodyInner (zig)
            .as                           => try sema.zirAs(block, inst),
                                                           ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:784:30: 0x667a734 in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:17063:41: 0x61ceb1f in zirCondbr (zig)
        try sema.analyzeBodyRuntimeBreak(&sub_block, else_body);
                                        ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1570:61: 0x5e62e9e in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:784:30: 0x667a734 in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:17044:37: 0x61ce491 in zirCondbr (zig)
    try sema.analyzeBodyRuntimeBreak(&sub_block, then_body);
                                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1570:61: 0x5e62e9e in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:5753:21: 0x5e392ca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:4342:40: 0x5c6166e in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:29000:36: 0x6710757 in ensureFuncBodyAnalyzed (zig)
    sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
                                   ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:31720:40: 0x620fa96 in resolveInferredErrorSet (zig)
        try sema.ensureFuncBodyAnalyzed(ies.func);
                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:29313:49: 0x61d049e in analyzeIsNonErrComptimeOnly (zig)
                try sema.resolveInferredErrorSet(block, src, ies);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:17095:60: 0x61cf46d in zirTry (zig)
    const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
                                                           ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1616:67: 0x5e6416a in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
                                                                  ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:5753:21: 0x5e392ca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:4342:40: 0x5c6166e in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:29000:36: 0x6710757 in ensureFuncBodyAnalyzed (zig)
    sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
                                   ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:31720:40: 0x620fa96 in resolveInferredErrorSet (zig)
        try sema.ensureFuncBodyAnalyzed(ies.func);
                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:29313:49: 0x61d049e in analyzeIsNonErrComptimeOnly (zig)
                try sema.resolveInferredErrorSet(block, src, ies);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:29340:56: 0x6663d5c in analyzeIsNonErr (zig)
    const result = try sema.analyzeIsNonErrComptimeOnly(block, src, operand);
                                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:16982:32: 0x6117e06 in zirIsNonErr (zig)
    return sema.analyzeIsNonErr(block, src, operand);
                               ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:966:66: 0x5e54ae0 in analyzeBodyInner (zig)
            .is_non_err                   => try sema.zirIsNonErr(block, inst),
                                                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:11013:49: 0x6128920 in zirSwitchBlock (zig)
                    return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:989:69: 0x5e55ee8 in analyzeBodyInner (zig)
            .switch_block                 => try sema.zirSwitchBlock(block, inst),
                                                                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:6967:33: 0x664b753 in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:21748:28: 0x6167cc3 in zirBuiltinCall (zig)
    return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null);
                           ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1045:69: 0x5e58fdb in analyzeBodyInner (zig)
            .builtin_call                 => try sema.zirBuiltinCall(block, inst),
                                                                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:6967:33: 0x664b753 in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:6407:32: 0x6106434 in zirCall__anon_131151 (zig)
        return sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node);
                               ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:923:62: 0x5e52507 in analyzeBodyInner (zig)
            .call                         => try sema.zirCall(block, inst, .direct),
                                                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:6967:33: 0x664b753 in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:21748:28: 0x6167cc3 in zirBuiltinCall (zig)
    return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null);
                           ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1045:69: 0x5e58fdb in analyzeBodyInner (zig)
            .builtin_call                 => try sema.zirBuiltinCall(block, inst),
                                                                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:821:45: 0x5c82771 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:770:50: 0x663fe53 in resolveBody (zig)
    const break_data = (try sema.analyzeBodyBreak(block, body)) orelse
                                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:6353:46: 0x6107ce9 in zirCall__anon_131153 (zig)
        const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
                                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:924:62: 0x5e525e5 in analyzeBodyInner (zig)
            .field_call                   => try sema.zirCall(block, inst, .field),
                                                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5503:34: 0x667f349 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:5486:33: 0x61d39a7 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:1461:49: 0x5e66167 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/andre/stuff/dev/languages/zig/zig/src/Sema.zig:804:30: 0x60adea8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:5753:21: 0x5e392ca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                    ^
/home/andre/stuff/dev/languages/zig/zig/src/Module.zig:4342:40: 0x5c6166e in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/home/andre/stuff/dev/languages/zig/zig/src/Compilation.zig:3134:42: 0x5c5f663 in processOneJob (zig)
            module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                         ^
/home/andre/stuff/dev/languages/zig/zig/src/Compilation.zig:3071:30: 0x5b0a93e in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
                             ^
/home/andre/stuff/dev/languages/zig/zig/src/Compilation.zig:2026:31: 0x5b07058 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/home/andre/stuff/dev/languages/zig/zig/src/main.zig:3835:24: 0x5b3450a in updateModule (zig)
        try comp.update(main_progress_node);
                       ^
/home/andre/stuff/dev/languages/zig/zig/src/main.zig:3270:17: 0x59cb785 in buildOutputType (zig)
    updateModule(comp) catch |err| switch (err) {
                ^
/home/andre/stuff/dev/languages/zig/zig/src/main.zig:277:31: 0x597e825 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .run);
                              ^
/home/andre/stuff/dev/languages/zig/zig/src/main.zig:213:20: 0x597b9c5 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/home/andre/stuff/dev/languages/zig/zig/lib/std/start.zig:609:37: 0x597b448 in main (zig)
            const result = root.main() catch |err| {
                                    ^

Expected Behavior

$ ./zig run src/lex_test.zig
0.123

Thanks for all your work guys!

ssmid avatar Jun 12 '23 23:06 ssmid

And it is as it always is... You spent countless hours debugging, simplifying, writing a bug report etc etc. 5 minutes after posting you find the issue.

It looks like the else branch uses the wrong cast ("@as" which actually should be "@intCast"). However, this probably should be detected by the compiler, considering the type annotations.

ssmid avatar Jun 12 '23 23:06 ssmid

Here is a much shorter reproducer:

const std = @import("std");

// conditions:
//  value2 must be u64, not u8 and not comptime_int
//  @as(i64, value2) must not be returned directly
// then: compile error points at a completely unrelated code line

pub fn parse(value1: u8, value2: u64) i64 {
    var ret_value: i64 = 0;
    if (value1 == '.') {
        // wrong cast used here; should be @intCast() instead
        ret_value = @as(i64, value2);
    }
    return ret_value;
}

pub fn main() !void {
    std.debug.print("{d}\n", .{parse(0, 1)});
}

Output:

src/lex_test.zig:10:16: error: expected type 'i64', found 'u64'
    if (value1 == '.') {
        ~~~~~~~^~~~~~
src/lex_test.zig:10:16: note: signed 64-bit int cannot represent all possible unsigned 64-bit values
referenced by:
    main: src/lex_test.zig:18:32
    callMain: zig-fresh/lib/zig/std/start.zig:609:32
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

The output is different, but just as before it points at an unrelated code line.

ssmid avatar Jun 15 '23 08:06 ssmid

@ssmid I tried with 0.12.0-dev.2341+92211135 and it seems it work correctly:

test.zig:12:30: error: expected type 'i64', found 'u64'
        ret_value = @as(i64, value2);
                             ^~~~~~
test.zig:12:30: note: signed 64-bit int cannot represent all possible unsigned 64-bit values
referenced by:
    main: test.zig:18:32
    callMain: /home/manlio/.local/share/sdk/zig/master/lib/std/start.zig:585:32
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Can you confirm it?

perillo avatar Jan 29 '24 20:01 perillo

Likely fixed by the cast builtin result location type change.

Vexu avatar Jan 30 '24 20:01 Vexu

Can confirm as of zig-0.12.0.1871+e426ae43a

ssmid avatar Feb 09 '24 15:02 ssmid