From 8a859afd580f438f549ee69a3e3487eb5d119fad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 7 Feb 2017 17:19:51 -0500 Subject: [PATCH] std.io supports printing integers as hex values remove "unnecessary if statement" error this "depends on compile variable" code is too hard to validate, and has false negatives. not worth it right now. std.str removed, instead use std.mem. std.mem.eql and std.mem.sliceEql merged and do not require explicit type argument. --- CMakeLists.txt | 1 - src/ir.cpp | 12 +---- std/elf.zig | 3 +- std/index.zig | 1 - std/io.zig | 93 +++++++++++++++++++++++--------- std/math.zig | 37 +++++++++++++ std/mem.zig | 20 +++++++ std/sort.zig | 7 ++- std/str.zig | 21 -------- test/cases/array.zig | 12 ++--- test/cases/enum_with_members.zig | 10 ++-- test/cases/error.zig | 6 +-- test/cases/eval.zig | 1 - test/cases/for.zig | 4 +- test/cases/misc.zig | 36 ++++++------- test/cases/void.zig | 20 +++++++ test/run_tests.cpp | 38 ++----------- test/self_hosted.zig | 1 + 18 files changed, 191 insertions(+), 132 deletions(-) delete mode 100644 std/str.zig create mode 100644 test/cases/void.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fce41d4cf..a05f8f5fda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,7 +225,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/panic.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}") -install(FILES "${CMAKE_SOURCE_DIR}/std/str.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}") diff --git a/src/ir.cpp b/src/ir.cpp index a6add73124..e89f89f89c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8536,14 +8536,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct if (!ir_resolve_bool(ira, condition, &cond_is_true)) return ir_unreach_error(ira); - if (!cond_br_instruction->base.is_gen && !condition->value.depends_on_compile_var && - !ir_should_inline(ira->new_irb.exec, cond_br_instruction->base.scope)) - { - const char *true_or_false = cond_is_true ? "true" : "false"; - ir_add_error(ira, &cond_br_instruction->base, - buf_sprintf("condition is always %s; unnecessary if statement", true_or_false)); - } - IrBasicBlock *old_dest_block = cond_is_true ? cond_br_instruction->then_block : cond_br_instruction->else_block; @@ -9060,7 +9052,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, - usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); + usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); } else { ir_add_error_node(ira, source_node, buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), @@ -9084,7 +9076,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, - usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); + usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); } else { ir_add_error_node(ira, source_node, buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), diff --git a/std/elf.zig b/std/elf.zig index 704f1e1870..1ad41bf245 100644 --- a/std/elf.zig +++ b/std/elf.zig @@ -1,5 +1,4 @@ const io = @import("io.zig"); -const str = @import("str.zig"); const math = @import("math.zig"); const mem = @import("mem.zig"); const debug = @import("debug.zig"); @@ -95,7 +94,7 @@ pub const Elf = struct { var magic: [4]u8 = undefined; %return elf.in_stream.readNoEof(magic); - if (!str.eql(magic, "\x7fELF")) return error.InvalidFormat; + if (!mem.eql(magic, "\x7fELF")) return error.InvalidFormat; elf.is_64 = switch (%return elf.in_stream.readByte()) { 1 => false, diff --git a/std/index.zig b/std/index.zig index c4a18cbbe8..b4aeb410b2 100644 --- a/std/index.zig +++ b/std/index.zig @@ -2,7 +2,6 @@ pub const rand = @import("rand.zig"); pub const io = @import("io.zig"); pub const os = @import("os.zig"); pub const math = @import("math.zig"); -pub const str = @import("str.zig"); pub const cstr = @import("cstr.zig"); pub const sort = @import("sort.zig"); pub const net = @import("net.zig"); diff --git a/std/io.zig b/std/io.zig index d0c7f407bd..f726c30cbc 100644 --- a/std/io.zig +++ b/std/io.zig @@ -61,8 +61,8 @@ error Unseekable; error Eof; const buffer_size = 4 * 1024; -const max_u64_base10_digits = 20; const max_f64_digits = 65; +const max_int_digits = 65; pub const OpenRead = 0b0001; pub const OpenWrite = 0b0010; @@ -100,6 +100,7 @@ pub const OutStream = struct { Start, OpenBrace, CloseBrace, + Hex: bool, }; /// Calls print and then flushes the buffer. @@ -131,6 +132,12 @@ pub const OutStream = struct { state = State.Start; start_index = i + 1; }, + 'x' => { + state = State.Hex { false }; + }, + 'X' => { + state = State.Hex { true }; + }, else => @compileError("Unknown format character: " ++ c), }, State.CloseBrace => switch (c) { @@ -140,14 +147,25 @@ pub const OutStream = struct { }, else => @compileError("Single '}' encountered in format string"), }, + State.Hex => |uppercase| switch (c) { + '}' => { + self.printInt(args[next_arg], 16, uppercase); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + else => @compileError("Expected '}' after 'x'/'X' in format string"), + }, } } comptime { if (args.len != next_arg) { @compileError("Unused arguments"); } - if (state != State.Start) { - @compileError("Incomplete format string: " ++ format); + // TODO https://github.com/andrewrk/zig/issues/253 + switch (state) { + State.Start => {}, + else => @compileError("Incomplete format string: " ++ format), } } if (start_index < format.len) { @@ -159,7 +177,7 @@ pub const OutStream = struct { pub fn printValue(self: &OutStream, value: var) -> %void { const T = @typeOf(value); if (@isInteger(T)) { - return self.printInt(T, value); + return self.printInt(value, 10, false); } else if (@isFloat(T)) { return self.printFloat(T, value); } else if (@canImplicitCast([]const u8, value)) { @@ -172,12 +190,11 @@ pub const OutStream = struct { } } - pub fn printInt(self: &OutStream, comptime T: type, x: T) -> %void { - // TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T))) - if (self.index + max_u64_base10_digits >= self.buffer.len) { + pub fn printInt(self: &OutStream, x: var, base: u8, uppercase: bool) -> %void { + if (self.index + max_int_digits >= self.buffer.len) { %return self.flush(); } - const amt_printed = bufPrintInt(T, self.buffer[self.index...], x); + const amt_printed = bufPrintInt(self.buffer[self.index...], x, base, uppercase); self.index += amt_printed; } @@ -448,39 +465,51 @@ fn charToDigit(c: u8, radix: u8) -> %u8 { return value; } -pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize { - if (T.is_signed) bufPrintSigned(T, out_buf, x) else bufPrintUnsigned(T, out_buf, x) +fn digitToChar(digit: u8, uppercase: bool) -> u8 { + return switch (digit) { + 0 ... 9 => digit + '0', + 10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10), + else => @unreachable(), + }; } -fn bufPrintSigned(comptime T: type, out_buf: []u8, x: T) -> usize { - const uint = @intType(false, T.bit_count); +/// Guaranteed to not use more than max_int_digits +pub fn bufPrintInt(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize { + if (@typeOf(x).is_signed) + bufPrintSigned(out_buf, x, base, uppercase) + else + bufPrintUnsigned(out_buf, x, base, uppercase) +} + +fn bufPrintSigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize { + const uint = @intType(false, @typeOf(x).bit_count); if (x < 0) { out_buf[0] = '-'; - return 1 + bufPrintUnsigned(uint, out_buf[1...], uint(-(x + 1)) + 1); + return 1 + bufPrintUnsigned(out_buf[1...], uint(-(x + 1)) + 1, base, uppercase); } else { - return bufPrintUnsigned(uint, out_buf, uint(x)); + return bufPrintUnsigned(out_buf, uint(x), base, uppercase); } } -fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize { - var buf: [max_u64_base10_digits]u8 = undefined; +fn bufPrintUnsigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize { + // max_int_digits accounts for the minus sign. when printing an unsigned + // number we don't need to do that. + var buf: [max_int_digits - 1]u8 = undefined; var a = x; var index: usize = buf.len; while (true) { - const digit = a % 10; + const digit = a % base; index -= 1; - buf[index] = '0' + u8(digit); - a /= 10; + buf[index] = digitToChar(u8(digit), uppercase); + a /= base; if (a == 0) break; } - const len = buf.len - index; - - @memcpy(&out_buf[0], &buf[index], len); - - return len; + const src_buf = buf[index...]; + mem.copy(u8, out_buf, src_buf); + return src_buf.len; } fn parseU64DigitTooBig() { @@ -505,3 +534,19 @@ pub fn openSelfExe(stream: &InStream) -> %void { else => @compileError("unsupported os"), } } + +fn bufPrintIntToSlice(buf: []u8, x: var, base: u8, uppercase: bool) -> []u8 { + return buf[0...bufPrintInt(buf, x, base, uppercase)]; +} + +fn testBufPrintInt() { + @setFnTest(this); + + var buf: [max_int_digits]u8 = undefined; + assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 2, false), "-101111000110000101001110")); + assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 10, false), "-12345678")); + assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, false), "-bc614e")); + assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, true), "-BC614E")); + + assert(mem.eql(bufPrintIntToSlice(buf, u32(12345678), 10, true), "12345678")); +} diff --git a/std/math.zig b/std/math.zig index 3dbc029a02..d8e4951fa9 100644 --- a/std/math.zig +++ b/std/math.zig @@ -29,3 +29,40 @@ pub fn shlOverflow(comptime T: type, a: T, b: T) -> %T { var answer: T = undefined; if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer } + +pub fn log(comptime base: usize, value: var) -> @typeOf(value) { + const T = @typeOf(value); + if (@isInteger(T)) { + if (base == 2) { + return T.bit_count - 1 - @clz(value); + } else { + @compileError("TODO implement log for non base 2 integers"); + } + } else if (@isFloat(T)) { + @compileError("TODO implement log for floats"); + } else { + @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'"); + } +} + +/// x must be an integer or a float +/// Note that this causes undefined behavior if +/// @typeOf(x).is_signed && x == @minValue(@typeOf(x)). +pub fn abs(x: var) -> @typeOf(x) { + const T = @typeOf(x); + if (@isInteger(T)) { + return if (x < 0) -x else x; + } else if (@isFloat(T)) { + @compileError("TODO implement abs for floats"); + } else { + @unreachable(); + } +} +fn getReturnTypeForAbs(comptime T: type) -> type { + if (@isInteger(T)) { + return @intType(false, T.bit_count); + } else { + return T; + } +} + diff --git a/std/mem.zig b/std/mem.zig index 8aa18348b2..45734ce869 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -43,6 +43,9 @@ pub const Allocator = struct { /// Copy all of source into dest at position 0. /// dest.len must be >= source.len. pub fn copy(comptime T: type, dest: []T, source: []const T) { + // TODO instead of manually doing this check for the whole array + // and turning off debug safety, the compiler should detect loops like + // this and automatically omit safety checks for loops @setDebugSafety(this, false); assert(dest.len >= source.len); for (source) |s, i| dest[i] = s; @@ -82,6 +85,23 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T { return result; } +/// Compares two slices and returns whether they are equal. +pub fn eql(a: var, b: var) -> bool { + if (a.len != b.len) return false; + for (a) |item, index| { + if (b[index] != item) return false; + } + return true; +} + +fn testStringEquality() { + @setFnTest(this); + + assert(eql("abcd", "abcd")); + assert(!eql("abcdef", "abZdef")); + assert(!eql("abcdefg", "abcdef")); +} + fn testSliceAsInt() { @setFnTest(this); { diff --git a/std/sort.zig b/std/sort.zig index 9699773b4f..8c41d87034 100644 --- a/std/sort.zig +++ b/std/sort.zig @@ -1,5 +1,4 @@ const assert = @import("debug.zig").assert; -const str = @import("str.zig"); const mem = @import("mem.zig"); const math = @import("math.zig"); @@ -76,7 +75,7 @@ fn testSort() { const slice = buf[0...case[0].len]; mem.copy(u8, slice, case[0]); sort(u8, slice, u8asc); - assert(str.eql(slice, case[1])); + assert(mem.eql(slice, case[1])); } const i32cases = [][][]i32 { @@ -93,7 +92,7 @@ fn testSort() { const slice = buf[0...case[0].len]; mem.copy(i32, slice, case[0]); sort(i32, slice, i32asc); - assert(str.sliceEql(i32, slice, case[1])); + assert(mem.eql(slice, case[1])); } } @@ -114,6 +113,6 @@ fn testSortDesc() { const slice = buf[0...case[0].len]; mem.copy(i32, slice, case[0]); sort(i32, slice, i32desc); - assert(str.sliceEql(i32, slice, case[1])); + assert(mem.eql(slice, case[1])); } } diff --git a/std/str.zig b/std/str.zig deleted file mode 100644 index bb891b37ef..0000000000 --- a/std/str.zig +++ /dev/null @@ -1,21 +0,0 @@ -const assert = @import("debug.zig").assert; - -pub fn eql(a: []const u8, b: []const u8) -> bool { - sliceEql(u8, a, b) -} - -pub fn sliceEql(comptime T: type, a: []const T, b: []const T) -> bool { - if (a.len != b.len) return false; - for (a) |item, index| { - if (b[index] != item) return false; - } - return true; -} - -fn testStringEquality() { - @setFnTest(this); - - assert(eql("abcd", "abcd")); - assert(!eql("abcdef", "abZdef")); - assert(!eql("abcdefg", "abcdef")); -} diff --git a/test/cases/array.zig b/test/cases/array.zig index 79dcf21407..1dc1242d37 100644 --- a/test/cases/array.zig +++ b/test/cases/array.zig @@ -1,5 +1,5 @@ const assert = @import("std").debug.assert; -const str = @import("std").str; +const mem = @import("std").mem; fn arrays() { @setFnTest(this); @@ -63,10 +63,10 @@ fn nestedArrays() { const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"}; for (array_of_strings) |s, i| { - if (i == 0) assert(str.eql(s, "hello")); - if (i == 1) assert(str.eql(s, "this")); - if (i == 2) assert(str.eql(s, "is")); - if (i == 3) assert(str.eql(s, "my")); - if (i == 4) assert(str.eql(s, "thing")); + if (i == 0) assert(mem.eql(s, "hello")); + if (i == 1) assert(mem.eql(s, "this")); + if (i == 2) assert(mem.eql(s, "is")); + if (i == 3) assert(mem.eql(s, "my")); + if (i == 4) assert(mem.eql(s, "thing")); } } diff --git a/test/cases/enum_with_members.zig b/test/cases/enum_with_members.zig index 7bcc2ac01f..b338b9b014 100644 --- a/test/cases/enum_with_members.zig +++ b/test/cases/enum_with_members.zig @@ -1,5 +1,5 @@ const assert = @import("std").debug.assert; -const str = @import("std").str; +const mem = @import("std").mem; const io = @import("std").io; const ET = enum { @@ -8,8 +8,8 @@ const ET = enum { pub fn print(a: &const ET, buf: []u8) -> %usize { return switch (*a) { - ET.SINT => |x| { io.bufPrintInt(i32, buf, x) }, - ET.UINT => |x| { io.bufPrintInt(u32, buf, x) }, + ET.SINT => |x| { io.bufPrintInt(buf, x, 10, false) }, + ET.UINT => |x| { io.bufPrintInt(buf, x, 10, false) }, } } }; @@ -22,8 +22,8 @@ fn enumWithMembers() { var buf: [20]u8 = undefined; assert(%%a.print(buf) == 3); - assert(str.eql(buf[0...3], "-42")); + assert(mem.eql(buf[0...3], "-42")); assert(%%b.print(buf) == 2); - assert(str.eql(buf[0...2], "42")); + assert(mem.eql(buf[0...2], "42")); } diff --git a/test/cases/error.zig b/test/cases/error.zig index 14c4011445..20fba13f90 100644 --- a/test/cases/error.zig +++ b/test/cases/error.zig @@ -1,5 +1,5 @@ const assert = @import("std").debug.assert; -const str = @import("std").str; +const mem = @import("std").mem; pub fn foo() -> %i32 { const x = %return bar(); @@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 { fn errorName() { @setFnTest(this); - assert(str.eql(@errorName(error.AnError), "AnError")); - assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName")); + assert(mem.eql(@errorName(error.AnError), "AnError")); + assert(mem.eql(@errorName(error.ALongerErrorName), "ALongerErrorName")); } error AnError; error ALongerErrorName; diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 629fb6366b..9f3b1d2fcd 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -1,5 +1,4 @@ const assert = @import("std").debug.assert; -const str = @import("std").str; fn compileTimeRecursion() { @setFnTest(this); diff --git a/test/cases/for.zig b/test/cases/for.zig index 27ace9e063..dd1987d6b9 100644 --- a/test/cases/for.zig +++ b/test/cases/for.zig @@ -1,6 +1,6 @@ const std = @import("std"); const assert = std.debug.assert; -const str = std.str; +const mem = std.mem; fn continueInForLoop() { @setFnTest(this); @@ -24,7 +24,7 @@ fn forLoopWithPointerElemVar() { var target: [source.len]u8 = undefined; @memcpy(&target[0], &source[0], source.len); mangleString(target); - assert(str.eql(target, "bcdefgh")); + assert(mem.eql(target, "bcdefgh")); } fn mangleString(s: []u8) { for (s) |*c| { diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 39de3d1e4f..0984abcae9 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -1,5 +1,5 @@ const assert = @import("std").debug.assert; -const str = @import("std").str; +const mem = @import("std").mem; const cstr = @import("std").cstr; // normal comment @@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 { fn ReturnStringFromFunction() { @setFnTest(this); - assert(str.eql(first4KeysOfHomeRow(), "aoeu")); + assert(mem.eql(first4KeysOfHomeRow(), "aoeu")); } const g1 : i32 = 1233 + 1; @@ -210,31 +210,31 @@ fn emptyFn() {} fn hexEscape() { @setFnTest(this); - assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello")); + assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello")); } fn stringConcatenation() { @setFnTest(this); - assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); + assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); } fn arrayMultOperator() { @setFnTest(this); - assert(str.eql("ab" ** 5, "ababababab")); + assert(mem.eql("ab" ** 5, "ababababab")); } fn stringEscapes() { @setFnTest(this); - assert(str.eql("\"", "\x22")); - assert(str.eql("\'", "\x27")); - assert(str.eql("\n", "\x0a")); - assert(str.eql("\r", "\x0d")); - assert(str.eql("\t", "\x09")); - assert(str.eql("\\", "\x5c")); - assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69")); + assert(mem.eql("\"", "\x22")); + assert(mem.eql("\'", "\x27")); + assert(mem.eql("\n", "\x0a")); + assert(mem.eql("\r", "\x0d")); + assert(mem.eql("\t", "\x09")); + assert(mem.eql("\\", "\x5c")); + assert(mem.eql("\u1234\u0069", "\xe1\x88\xb4\x69")); } fn multilineString() { @@ -246,7 +246,7 @@ fn multilineString() { \\three ; const s2 = "one\ntwo)\nthree"; - assert(str.eql(s1, s2)); + assert(mem.eql(s1, s2)); } fn multilineCString() { @@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined; fn memAlloc(comptime T: type, n: usize) -> %[]T { return (&T)(&some_mem[0])[0...n]; } -fn memFree(comptime T: type, mem: []T) { } +fn memFree(comptime T: type, memory: []T) { } fn castUndefined() { @@ -344,8 +344,8 @@ fn pointerDereferencing() { fn callResultOfIfElseExpression() { @setFnTest(this); - assert(str.eql(f2(true), "a")); - assert(str.eql(f2(false), "b")); + assert(mem.eql(f2(true), "a")); + assert(mem.eql(f2(false), "b")); } fn f2(x: bool) -> []u8 { return (if (x) fA else fB)(); @@ -562,8 +562,8 @@ fn typeName() { @setFnTest(this); comptime { - assert(str.eql(@typeName(i64), "i64")); - assert(str.eql(@typeName(&usize), "&usize")); + assert(mem.eql(@typeName(i64), "i64")); + assert(mem.eql(@typeName(&usize), "&usize")); } } diff --git a/test/cases/void.zig b/test/cases/void.zig new file mode 100644 index 0000000000..15b8276b0b --- /dev/null +++ b/test/cases/void.zig @@ -0,0 +1,20 @@ +const assert = @import("std").debug.assert; + +const Foo = struct { + a: void, + b: i32, + c: void, +}; + +fn compareVoidWithVoidCompileTimeKnown() { + @setFnTest(this); + + comptime { + const foo = Foo { + .a = {}, + .b = 1, + .c = {}, + }; + assert(foo.a == {}); + } +} diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 944d687d12..01d16a2543 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -471,21 +471,17 @@ const io = @import("std").io; pub fn main(args: [][]u8) -> %void { const array = []u8 {9, 8, 7, 6}; for (array) |item| { - %%io.stdout.printInt(@typeOf(item), item); - %%io.stdout.printf("\n"); + %%io.stdout.printf("{}\n", item); } for (array) |item, index| { - %%io.stdout.printInt(@typeOf(index), index); - %%io.stdout.printf("\n"); + %%io.stdout.printf("{}\n", index); } const unknown_size: []u8 = array; for (unknown_size) |item| { - %%io.stdout.printInt(@typeOf(item), item); - %%io.stdout.printf("\n"); + %%io.stdout.printf("{}\n", item); } for (unknown_size) |item, index| { - %%io.stdout.printInt(@typeOf(index), index); - %%io.stdout.printf("\n"); + %%io.stdout.printf("{}\n", index); } } )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n"); @@ -1124,13 +1120,6 @@ fn get() -> usize { global_var } ".tmp_source.zig:3:8: note: called from here"); - add_compile_fail_case("unnecessary if statement", R"SOURCE( -fn f() { - if (true) { } -} - )SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement"); - - add_compile_fail_case("addition with non numbers", R"SOURCE( const Foo = struct { field: i32, @@ -1588,25 +1577,6 @@ fn derp() { } )SOURCE", 1, ".tmp_source.zig:7:13: error: cannot assign to constant"); - add_compile_fail_case("compare void with void is compile time known", R"SOURCE( -const Foo = struct { - a: void, - b: i32, - c: void, -}; - -fn f() { - const foo = Foo { - .a = {}, - .b = 1, - .c = {}, - }; - if (foo.a != {}) { - @unreachable(); - } -} - )SOURCE", 1, ".tmp_source.zig:14:15: error: condition is always false; unnecessary if statement"); - add_compile_fail_case("return from defer expression", R"SOURCE( pub fn testTrickyDefer() -> %void { defer canFail() %% {}; diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 5d8356fe18..7830e67ea4 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -32,4 +32,5 @@ const test_try = @import("cases/try.zig"); const test_typedef = @import("cases/typedef.zig"); const test_undefined = @import("cases/undefined.zig"); const test_var_args = @import("cases/var_args.zig"); +const test_void = @import("cases/void.zig"); const test_while = @import("cases/while.zig");