authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-22 14:32:31+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-22 14:32:31+03:00
log8667d6d61e8217159377c0e22bc35075848d1202
tree4dd89f89f346d2a1f435efff54cd27d33485f2c5
parentf1999712b0a8560bd84726c8a5e8fd37dbdf5375
parent5404dcdfd844e4b9f47dc49a1f43f0e1075a563f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12563 from Vexu/stage2-fixes

Stage2 fixes

20 files changed, 179 insertions(+), 37 deletions(-)

doc/langref.html.in+2-2
......@@ -5024,8 +5024,8 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 {
50245024// Another file can use @import and call sub2
50255025pub fn sub2(a: i8, b: i8) i8 { return a - b; }
50265026
5027// Functions can be used as values and are equivalent to pointers.
5028const call2_op = fn (a: i8, b: i8) i8;
5027// Function pointers are prefixed with `*const `.
5028const call2_op = *const fn (a: i8, b: i8) i8;
50295029fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 {
50305030 return fn_call(op1, op2);
50315031}
lib/std/fs/path.zig+1-1
......@@ -42,7 +42,7 @@ pub fn isSep(byte: u8) bool {
4242
4343/// This is different from mem.join in that the separator will not be repeated if
4444/// it is found at the end or beginning of a pair of consecutive paths.
45fn joinSepMaybeZ(allocator: Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
45fn joinSepMaybeZ(allocator: Allocator, separator: u8, comptime sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
4646 if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
4747
4848 // Find first non-empty path index.
lib/std/math.zig+1-1
......@@ -1548,7 +1548,7 @@ test "boolMask" {
15481548}
15491549
15501550/// Return the mod of `num` with the smallest integer type
1551pub fn comptimeMod(num: anytype, denom: comptime_int) IntFittingRange(0, denom - 1) {
1551pub fn comptimeMod(num: anytype, comptime denom: comptime_int) IntFittingRange(0, denom - 1) {
15521552 return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom));
15531553}
15541554
lib/std/math/float.zig+1-1
......@@ -8,7 +8,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {
88}
99
1010/// Creates floating point type T from an unbiased exponent and raw mantissa.
11inline fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T {
11inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T {
1212 const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
1313 const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
1414 return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa));
lib/std/zig/c_translation.zig+1-1
......@@ -349,7 +349,7 @@ test "shuffleVectorIndex" {
349349
350350/// Constructs a [*c] pointer with the const and volatile annotations
351351/// from SelfType for pointing to a C flexible array of ElementType.
352pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type {
352pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type {
353353 switch (@typeInfo(SelfType)) {
354354 .Pointer => |ptr| {
355355 return @Type(.{ .Pointer = .{
lib/std/zig/parse.zig+1-1
......@@ -3670,7 +3670,7 @@ const Parser = struct {
36703670 }
36713671
36723672 /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
3673 fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
3673 fn parseIf(p: *Parser, comptime bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
36743674 const if_token = p.eatToken(.keyword_if) orelse return null_node;
36753675 _ = try p.expectToken(.l_paren);
36763676 const condition = try p.expectExpr();
src/Module.zig+4-4
......@@ -6072,17 +6072,17 @@ pub fn paramSrc(
60726072 else => unreachable,
60736073 };
60746074 var it = full.iterate(tree);
6075 while (true) {
6076 if (it.param_i == param_i) {
6077 const param = it.next().?;
6075 var i: usize = 0;
6076 while (it.next()) |param| : (i += 1) {
6077 if (i == param_i) {
60786078 if (param.anytype_ellipsis3) |some| {
60796079 const main_token = tree.nodes.items(.main_token)[decl.src_node];
60806080 return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
60816081 }
60826082 return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
60836083 }
6084 _ = it.next();
60856084 }
6085 unreachable;
60866086}
60876087
60886088pub fn argSrc(
src/Sema.zig+46-17
......@@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
7676post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
7777/// Populated with the last compile error created.
7878err: ?*Module.ErrorMsg = null,
79/// True when analyzing a generic instantiation. Used to suppress some errors.
80is_generic_instantiation: bool = false,
7981
8082const std = @import("std");
8183const math = std.math;
......@@ -1696,7 +1698,10 @@ fn resolveMaybeUndefValIntable(
16961698 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
16971699 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
16981700 .generic_poison => return error.GenericPoison,
1699 else => return val,
1701 else => {
1702 try sema.resolveLazyValue(block, src, val);
1703 return val;
1704 },
17001705 };
17011706}
17021707
......@@ -6495,6 +6500,7 @@ fn instantiateGenericCall(
64956500 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
64966501 .comptime_args_fn_inst = module_fn.zir_body_inst,
64976502 .preallocated_new_func = new_module_func,
6503 .is_generic_instantiation = true,
64986504 };
64996505 defer child_sema.deinit();
65006506
......@@ -7255,6 +7261,8 @@ fn zirOptionalPayload(
72557261 if (operand_ty.ptrSize() != .C) {
72567262 return sema.failWithExpectedOptionalType(block, src, operand_ty);
72577263 }
7264 // TODO https://github.com/ziglang/zig/issues/6597
7265 if (true) break :t operand_ty;
72587266 const ptr_info = operand_ty.ptrInfo().data;
72597267 break :t try Type.ptr(sema.arena, sema.mod, .{
72607268 .pointee_type = try ptr_info.pointee_type.copy(sema.arena),
......@@ -7789,6 +7797,7 @@ fn funcCommon(
77897797 &is_generic,
77907798 is_extern,
77917799 cc_workaround,
7800 has_body,
77927801 ) catch |err| switch (err) {
77937802 error.NeededSourceLocation => {
77947803 const decl = sema.mod.declPtr(block.src_decl);
......@@ -7802,6 +7811,7 @@ fn funcCommon(
78027811 &is_generic,
78037812 is_extern,
78047813 cc_workaround,
7814 has_body,
78057815 );
78067816 return error.AnalysisFail;
78077817 },
......@@ -8005,6 +8015,7 @@ fn analyzeParameter(
80058015 is_generic: *bool,
80068016 is_extern: bool,
80078017 cc: std.builtin.CallingConvention,
8018 has_body: bool,
80088019) !void {
80098020 const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
80108021 comptime_params[i] = param.is_comptime or requires_comptime;
......@@ -8053,9 +8064,9 @@ fn analyzeParameter(
80538064 };
80548065 return sema.failWithOwnedErrorMsg(msg);
80558066 }
8056 if (requires_comptime and !param.is_comptime) {
8067 if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
80578068 const msg = msg: {
8058 const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{
8069 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
80598070 param.ty.fmt(sema.mod),
80608071 });
80618072 errdefer msg.destroy(sema.gpa);
......@@ -8153,7 +8164,7 @@ fn zirParam(
81538164
81548165 try block.params.append(sema.gpa, .{
81558166 .ty = param_ty,
8156 .is_comptime = is_comptime,
8167 .is_comptime = comptime_syntax,
81578168 .name = param_name,
81588169 });
81598170 const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
......@@ -16318,7 +16329,7 @@ fn zirUnaryMath(
1631816329 block: *Block,
1631916330 inst: Zir.Inst.Index,
1632016331 air_tag: Air.Inst.Tag,
16321 eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
16332 comptime eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
1632216333) CompileError!Air.Inst.Ref {
1632316334 const tracy = trace(@src());
1632416335 defer tracy.end();
......@@ -17777,7 +17788,7 @@ fn zirBitCount(
1777717788 block: *Block,
1777817789 inst: Zir.Inst.Index,
1777917790 air_tag: Air.Inst.Tag,
17780 comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
17791 comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
1778117792) CompileError!Air.Inst.Ref {
1778217793 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1778317794 const src = inst_data.src();
......@@ -20554,8 +20565,8 @@ fn validatePackedType(ty: Type) bool {
2055420565 .AnyFrame,
2055520566 .Fn,
2055620567 .Array,
20557 .Optional,
2055820568 => return false,
20569 .Optional => return ty.isPtrLikeOptional(),
2055920570 .Void,
2056020571 .Bool,
2056120572 .Float,
......@@ -21383,14 +21394,30 @@ fn fieldCallBind(
2138321394 switch (concrete_ty.zigTypeTag()) {
2138421395 .Struct => {
2138521396 const struct_ty = try sema.resolveTypeFields(block, src, concrete_ty);
21386 const struct_obj = struct_ty.castTag(.@"struct").?.data;
21387
21388 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
21389 break :find_field;
21390 const field_index = @intCast(u32, field_index_usize);
21391 const field = struct_obj.fields.values()[field_index];
21397 if (struct_ty.castTag(.@"struct")) |struct_obj| {
21398 const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse
21399 break :find_field;
21400 const field_index = @intCast(u32, field_index_usize);
21401 const field = struct_obj.data.fields.values()[field_index];
2139221402
21393 return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
21403 return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
21404 } else if (struct_ty.isTuple()) {
21405 if (mem.eql(u8, field_name, "len")) {
21406 return sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount());
21407 }
21408 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
21409 if (field_index >= struct_ty.structFieldCount()) break :find_field;
21410 return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr);
21411 } else |_| {}
21412 } else {
21413 const max = struct_ty.structFieldCount();
21414 var i: u32 = 0;
21415 while (i < max) : (i += 1) {
21416 if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {
21417 return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);
21418 }
21419 }
21420 }
2139421421 },
2139521422 .Union => {
2139621423 const union_ty = try sema.resolveTypeFields(block, src, concrete_ty);
......@@ -22553,7 +22580,7 @@ fn coerceExtra(
2255322580 // Function body to function pointer.
2255422581 if (inst_ty.zigTypeTag() == .Fn) {
2255522582 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
22556 const fn_decl = fn_val.castTag(.function).?.data.owner_decl;
22583 const fn_decl = fn_val.pointerDecl().?;
2255722584 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
2255822585 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
2255922586 }
......@@ -27909,7 +27936,9 @@ fn resolveInferredErrorSetTy(
2790927936fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void {
2791027937 const gpa = mod.gpa;
2791127938 const decl_index = struct_obj.owner_decl;
27912 const zir = struct_obj.namespace.file_scope.zir;
27939 const file_scope = struct_obj.namespace.file_scope;
27940 if (file_scope.status != .success_zir) return error.AnalysisFail;
27941 const zir = file_scope.zir;
2791327942 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
2791427943 assert(extended.opcode == .struct_decl);
2791527944 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -29489,7 +29518,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
2948929518 => {
2949029519 const child_ty = ty.childType();
2949129520 if (child_ty.zigTypeTag() == .Fn) {
29492 return false;
29521 return child_ty.fnInfo().is_generic;
2949329522 } else {
2949429523 return sema.typeRequiresComptime(block, src, child_ty);
2949529524 }
src/codegen/llvm.zig+6-3
......@@ -3417,7 +3417,10 @@ pub const DeclGen = struct {
34173417 });
34183418 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
34193419 const small_int_ty = dg.context.intType(ty_bit_size);
3420 const small_int_val = non_int_val.constBitCast(small_int_ty);
3420 const small_int_val = if (field.ty.isPtrAtRuntime())
3421 non_int_val.constPtrToInt(small_int_ty)
3422 else
3423 non_int_val.constBitCast(small_int_ty);
34213424 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
34223425 // If the field is as large as the entire packed struct, this
34233426 // zext would go from, e.g. i16 to i16. This is legal with
......@@ -5343,7 +5346,7 @@ pub const FuncGen = struct {
53435346 const same_size_int = self.context.intType(elem_bits);
53445347 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
53455348 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
5346 } else if (field_ty.zigTypeTag() == .Pointer) {
5349 } else if (field_ty.isPtrAtRuntime()) {
53475350 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
53485351 const same_size_int = self.context.intType(elem_bits);
53495352 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
......@@ -8408,7 +8411,7 @@ pub const FuncGen = struct {
84088411 const non_int_val = try self.resolveInst(elem);
84098412 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
84108413 const small_int_ty = self.dg.context.intType(ty_bit_size);
8411 const small_int_val = if (field.ty.zigTypeTag() == .Pointer)
8414 const small_int_val = if (field.ty.isPtrAtRuntime())
84128415 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
84138416 else
84148417 self.builder.buildBitCast(non_int_val, small_int_ty, "");
src/type.zig+1-1
......@@ -2394,7 +2394,7 @@ pub const Type = extern union {
23942394 if (ignore_comptime_only) {
23952395 return true;
23962396 } else if (ty.childType().zigTypeTag() == .Fn) {
2397 return true;
2397 return !ty.childType().fnInfo().is_generic;
23982398 } else if (sema_kit) |sk| {
23992399 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
24002400 } else {
test/behavior/cast.zig+1-1
......@@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" {
12811281test "cast between [*c]T and ?[*:0]T on fn parameter" {
12821282 const S = struct {
12831283 const Handler = ?fn ([*c]const u8) callconv(.C) void;
1284 fn addCallback(handler: Handler) void {
1284 fn addCallback(comptime handler: Handler) void {
12851285 _ = handler;
12861286 }
12871287
test/behavior/error.zig+1-1
......@@ -168,7 +168,7 @@ fn entryPtr() void {
168168 fooPtr(ptr);
169169}
170170
171fn foo2(f: fn () anyerror!void) void {
171fn foo2(comptime f: fn () anyerror!void) void {
172172 const x = f();
173173 x catch {
174174 @panic("fail");
test/behavior/eval.zig+22
......@@ -1325,3 +1325,25 @@ test "value in if block is comptime known" {
13251325 };
13261326 comptime try expect(std.mem.eql(u8, first, second));
13271327}
1328
1329test "lazy sizeof is resolved in division" {
1330 const A = struct {
1331 a: u32,
1332 };
1333 const a = 2;
1334 try expect(@sizeOf(A) / a == 2);
1335 try expect(@sizeOf(A) - a == 2);
1336}
1337
1338test "lazy value is resolved as slice operand" {
1339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1340 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1341
1342 const A = struct { a: u32 };
1343 var a: [512]u64 = undefined;
1344
1345 const ptr1 = a[0..@sizeOf(A)];
1346 const ptr2 = @ptrCast([*]u8, &a)[0..@sizeOf(A)];
1347 try expect(@ptrToInt(ptr1) == @ptrToInt(ptr2));
1348 try expect(ptr1.len == ptr2.len);
1349}
test/behavior/fn.zig+22-1
......@@ -137,7 +137,7 @@ test "implicit cast function unreachable return" {
137137 wantsFnWithVoid(fnWithUnreachable);
138138}
139139
140fn wantsFnWithVoid(f: fn () void) void {
140fn wantsFnWithVoid(comptime f: fn () void) void {
141141 _ = f;
142142}
143143
......@@ -422,3 +422,24 @@ test "import passed byref to function in return type" {
422422 var list = S.get();
423423 try expect(list.items.len == 0);
424424}
425
426test "implicit cast function to function ptr" {
427 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
431 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
432
433 const S1 = struct {
434 export fn someFunctionThatReturnsAValue() c_int {
435 return 123;
436 }
437 };
438 var fnPtr1: *const fn () callconv(.C) c_int = S1.someFunctionThatReturnsAValue;
439 try expect(fnPtr1() == 123);
440 const S2 = struct {
441 extern fn someFunctionThatReturnsAValue() c_int;
442 };
443 var fnPtr2: *const fn () callconv(.C) c_int = S2.someFunctionThatReturnsAValue;
444 try expect(fnPtr2() == 123);
445}
test/behavior/optional.zig+7
......@@ -405,3 +405,10 @@ test "optional of noreturn used with orelse" {
405405 const val = NoReturn.testOrelse();
406406 try expect(val == 123);
407407}
408
409test "orelse on C pointer" {
410 // TODO https://github.com/ziglang/zig/issues/6597
411 const foo: [*c]const u8 = "hey";
412 const d = foo orelse @compileError("bad");
413 try expectEqual([*c]const u8, @TypeOf(d));
414}
test/behavior/packed-struct.zig+12
......@@ -434,3 +434,15 @@ test "@ptrToInt on a packed struct field" {
434434 };
435435 try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2);
436436}
437
438test "optional pointer in packed struct" {
439 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
442 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
443
444 const T = packed struct { ptr: ?*const u8 };
445 var n: u8 = 0;
446 const x = T{ .ptr = &n };
447 try expect(x.ptr.? == &n);
448}
test/behavior/struct.zig+1-1
......@@ -147,7 +147,7 @@ test "fn call of struct field" {
147147 return 13;
148148 }
149149
150 fn callStructField(foo: Foo) i32 {
150 fn callStructField(comptime foo: Foo) i32 {
151151 return foo.ptr();
152152 }
153153 };
test/cases/compile_errors/bogus_method_call_on_slice.zig+8
......@@ -3,9 +3,17 @@ fn f(m: []const u8) void {
33 m.copy(u8, self[0..], m);
44}
55export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
6pub export fn entry1() void {
7 .{}.bar();
8}
9pub export fn entry2() void {
10 .{ .foo = 1 }.bar();
11}
612
713// error
814// backend=stage2
915// target=native
1016//
17// :7:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
18// :10:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}'
1119// :3:6: error: no field or member function named 'copy' in '[]const u8'
test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig created+23
......@@ -0,0 +1,23 @@
1fn f(_: anytype) void {}
2fn g(h: *const fn (anytype) void) void {
3 h({});
4}
5pub export fn entry() void {
6 g(f);
7}
8
9pub fn comptimeMod(num: anytype, denom: comptime_int) void {
10 _ = num;
11 _ = denom;
12}
13
14pub export fn entry1() void {
15 _ = comptimeMod(1, 2);
16}
17
18// error
19// backend=stage2
20// target=native
21//
22// :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime
23// :9:34: error: parameter of type 'comptime_int' must be declared comptime
test/compile_errors.zig+18-1
......@@ -184,7 +184,7 @@ pub fn addCases(ctx: *TestContext) !void {
184184 }
185185
186186 {
187 const case = ctx.obj("argument causes error ", .{});
187 const case = ctx.obj("argument causes error", .{});
188188 case.backend = .stage2;
189189
190190 case.addSourceFile("b.zig",
......@@ -208,6 +208,23 @@ pub fn addCases(ctx: *TestContext) !void {
208208 });
209209 }
210210
211 {
212 const case = ctx.obj("astgen failure in file struct", .{});
213 case.backend = .stage2;
214
215 case.addSourceFile("b.zig",
216 \\bad
217 );
218
219 case.addError(
220 \\pub export fn entry() void {
221 \\ _ = (@sizeOf(@import("b.zig")));
222 \\}
223 , &[_][]const u8{
224 ":1:1: error: struct field missing type",
225 });
226 }
227
211228 // TODO test this in stage2, but we won't even try in stage1
212229 //ctx.objErrStage1("inline fn calls itself indirectly",
213230 // \\export fn foo() void {