Hi, I've written a precise 62 LOC of Zig in my lifetime and thus this is probably just me being a doof (in which case, this is an extremely unhelpful error).
I've written this code:
const std = @import("std");
fn parseDecimal(comptime T: type, text: []const u8) !T {
var x: T = 0;
for (text) |char| {
const digit = try charToDigit(char);
if (@mulWithOverflow(T, x, 10, &x)) {
return error.Overflow;
}
if (@addWithOverflow(T, x, digit, &x)) {
return error.Overflow;
}
}
return x;
}
fn charToDigit(char: u8) !u4 {
return switch (char) {
'0'...'9' => @intCast(u4, char - '0'),
else => error.InvalidChar,
};
}
test "parse numbers" {
const lol = parseDecimal(u64, "6969696969") catch unreachable;
std.debug.assert(lol == 6969696969);
if (parseDecimal(i192, "test")) |n| {
std.debug.panic("somehow got {}, expected error.Overflow", n);
} else |e| switch (e) {
error.Overflow => {},
else => unreachable,
}
}
Upon running it with zig test I get:
0 ~/W/a/a/z/day1 zig test src/main.zig
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
fish: “zig test src/main.zig” terminated by signal SIGABRT (Abort)
134 # the numbers before paths are exit codes of last cmd
Reduction:
test "parse numbers" {
{var v: u128 = 1; v *= 10;} // works
{var v: u192 = 1; v *= 10;} // works
{var v: u256 = 1; v *= 10;} // works
{var v: u257 = 1; v *= 10;} // works
{var v: i127 = 1; v *= 10;} // works
{var v: i128 = 1; v *= 10;} // works
{var v: i129 = 1; v *= 10;} // crashes
}
Further reduction:
source_filename = "test"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
; Function Attrs: nounwind readnone speculatable
declare { i129, i1 } @llvm.smul.with.overflow.i129(i129, i129) #3
; Function Attrs: nobuiltin nounwind
define internal fastcc i1 @"foo"() unnamed_addr #1 {
Entry:
%v = alloca i129, align 16
store i129 1, i129* %v, align 16
%0 = load i129, i129* %v, align 16
%1 = call { i129, i1 } @llvm.smul.with.overflow.i129(i129 %0, i129 10)
%2 = extractvalue { i129, i1 } %1, 1
ret i1 %2;
}
@andrewrk, looks like we've got another bug for our LLVM friends :)
Next step is to report an LLVM bug, which is a contributor friendly task.
@andrewrk In the mean time, is there a possibility of having a work-around to this, or potentially detect it in use and warn about it?
Most helpful comment
Reduction: