From 38215ccc3e7bd4c79e70731c6d50556356c76c39 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 15:04:31 +0300 Subject: [PATCH 1/6] stage2: handle `int_u64` in `elemValueAdvanced` Closes #12599 --- src/value.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/value.zig b/src/value.zig index 9909cab5ce..4e9ea882e9 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2689,6 +2689,12 @@ pub const Value = extern union { // to have only one possible value itself. .the_only_possible_value => return val, + // pointer to integer casted to pointer of array + .int_u64, .int_i64 => { + assert(index == 0); + return val; + }, + else => unreachable, } } From d515d37934476365929401a0ba7e5639b09a648a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 15:26:49 +0300 Subject: [PATCH 2/6] AstGen: make root decls relative to beginning of file Closes #12610 --- src/AstGen.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 2001e6950a..db0ed47a04 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -4265,10 +4265,13 @@ fn structDeclInner( // are in scope, so that field types, alignments, and default value expressions // can refer to decls within the struct itself. astgen.advanceSourceCursorToNode(node); + // If `node == 0` then this is the root struct and all the declarations should + // be relative to the beginning of the file. + const decl_line = if (node == 0) 0 else astgen.source_line; var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, - .decl_line = astgen.source_line, + .decl_line = decl_line, .astgen = astgen, .force_comptime = true, .in_defer = false, @@ -11764,7 +11767,6 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. } } - // const index_name = try astgen.identAsString(index_token); var s = namespace.parent; while (true) switch (s.tag) { .local_val => { From cd1833044ab7505bc101c85f59889bd3ea3fac80 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 19:52:52 +0300 Subject: [PATCH 3/6] Sema: do not construct nested partial function types Closes #12616 --- src/Sema.zig | 16 +++++++--------- test/behavior/generics.zig | 15 +++++++++++++++ .../comptime_parameter_not_declared_as_such.zig | 7 ++++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 4f558ccae4..846b6af3bd 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -78,6 +78,9 @@ post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, err: ?*Module.ErrorMsg = null, /// True when analyzing a generic instantiation. Used to suppress some errors. is_generic_instantiation: bool = false, +/// Set to true when analyzing a func type instruction so that nested generic +/// function types will emit generic poison instead of a partial type. +no_partial_func_ty: bool = false, const std = @import("std"); const math = std.math; @@ -7917,6 +7920,7 @@ fn funcCommon( if (cc_workaround == .Inline and is_noinline) { return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); } + if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; break :fn_ty try Type.Tag.function.create(sema.arena, .{ .param_types = param_types, @@ -8097,25 +8101,19 @@ fn zirParam( // Make sure any nested param instructions don't clobber our work. const prev_params = block.params; const prev_preallocated_new_func = sema.preallocated_new_func; + const prev_no_partial_func_type = sema.no_partial_func_ty; block.params = .{}; sema.preallocated_new_func = null; + sema.no_partial_func_ty = true; defer { block.params.deinit(sema.gpa); block.params = prev_params; sema.preallocated_new_func = prev_preallocated_new_func; + sema.no_partial_func_ty = prev_no_partial_func_type; } if (sema.resolveBody(block, body, inst)) |param_ty_inst| { if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| { - if (param_ty.zigTypeTag() == .Fn and param_ty.fnInfo().is_generic) { - // zirFunc will not emit error.GenericPoison to build a - // partial type for generic functions but we still need to - // detect if a function parameter is a generic function - // to force the parent function to also be generic. - if (!sema.inst_map.contains(inst)) { - break :err error.GenericPoison; - } - } break :param_ty param_ty; } else |err| break :err err; } else |err| break :err err; diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index d930fb7d27..ba4bca0c1a 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -342,3 +342,18 @@ test "generic instantiation of tagged union with only one field" { try expect(S.foo(.{ .s = "a" }) == 1); try expect(S.foo(.{ .s = "ab" }) == 2); } + +test "nested generic function" { + const S = struct { + fn foo(comptime T: type, callback: *const fn (user_data: T) anyerror!void, data: T) anyerror!void { + try callback(data); + } + fn bar(a: u32) anyerror!void { + try expect(a == 123); + } + + fn g(_: *const fn (anytype) void) void {} + }; + try expect(@typeInfo(@TypeOf(S.g)).Fn.is_generic); + try S.foo(u32, S.bar, 123); +} diff --git a/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig b/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig index e4d9eed079..008d14f2fc 100644 --- a/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig +++ b/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig @@ -1,5 +1,6 @@ fn f(_: anytype) void {} -fn g(h: *const fn (anytype) void) void { +const T = *const fn (anytype) void; +fn g(h: T) void { h({}); } pub export fn entry() void { @@ -19,5 +20,5 @@ pub export fn entry1() void { // backend=stage2 // target=native // -// :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime -// :9:34: error: parameter of type 'comptime_int' must be declared comptime +// :3:6: error: parameter of type '*const fn(anytype) void' must be declared comptime +// :10:34: error: parameter of type 'comptime_int' must be declared comptime From 1d0b729f28dd5f9341c4f4fe8ab4b25592e6834a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 20:29:13 +0300 Subject: [PATCH 4/6] Sema: fix crash on slice of non-array type Closes #12621 --- src/Sema.zig | 3 ++- test/cases/compile_errors/slice_of_non_array_type.zig | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/slice_of_non_array_type.zig diff --git a/src/Sema.zig b/src/Sema.zig index 846b6af3bd..4e1b885486 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -26139,11 +26139,12 @@ fn analyzeSlice( var array_ty = ptr_ptr_child_ty; var slice_ty = ptr_ptr_ty; var ptr_or_slice = ptr_ptr; - var elem_ty = ptr_ptr_child_ty.childType(); + var elem_ty: Type = undefined; var ptr_sentinel: ?Value = null; switch (ptr_ptr_child_ty.zigTypeTag()) { .Array => { ptr_sentinel = ptr_ptr_child_ty.sentinel(); + elem_ty = ptr_ptr_child_ty.childType(); }, .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { .One => { diff --git a/test/cases/compile_errors/slice_of_non_array_type.zig b/test/cases/compile_errors/slice_of_non_array_type.zig new file mode 100644 index 0000000000..734b026038 --- /dev/null +++ b/test/cases/compile_errors/slice_of_non_array_type.zig @@ -0,0 +1,9 @@ +comptime { + _ = 1[0..]; +} + +// error +// backend=stage2 +// target=native +// +// :2:10: error: slice of non-array type 'comptime_int' From f49dff64c64baf8be48cc987b4ed61712afabc3d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 20:50:43 +0300 Subject: [PATCH 5/6] Sema: check one possible value earlier in `zirValidateArrayInit` Closes #12566 --- src/Sema.zig | 26 +++++++++++++------------- test/behavior/tuple.zig | 11 +++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 4e1b885486..22aa26f737 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4071,6 +4071,19 @@ fn zirValidateArrayInit( // Determine whether the value stored to this pointer is comptime-known. + if (array_ty.isTuple()) { + if (array_ty.structFieldValueComptime(i)) |opv| { + element_vals[i] = opv; + continue; + } + } else { + // Array has one possible value, so value is always comptime-known + if (opt_opv) |opv| { + element_vals[i] = opv; + continue; + } + } + const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?; // Find the block index of the elem_ptr so that we can look at the next @@ -4087,19 +4100,6 @@ fn zirValidateArrayInit( } first_block_index = @minimum(first_block_index, block_index); - if (array_ty.isTuple()) { - if (array_ty.structFieldValueComptime(i)) |opv| { - element_vals[i] = opv; - continue; - } - } else { - // Array has one possible value, so value is always comptime-known - if (opt_opv) |opv| { - element_vals[i] = opv; - continue; - } - } - // If the next instructon is a store with a comptime operand, this element // is comptime. const next_air_inst = block.instructions.items[block_index + 1]; diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 14297bd61c..971e52a0b5 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -290,3 +290,14 @@ test "coerce tuple to tuple" { }; try S.foo(.{123}); } + +test "tuple type with void field" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const T = std.meta.Tuple(&[_]type{void}); + const x = T{{}}; + try expect(@TypeOf(x[0]) == void); +} From 69a3c4e279238874cc74cf6acd5eb0426d5b65ee Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 24 Aug 2022 21:12:13 +0300 Subject: [PATCH 6/6] Sema: correctly reset inst_map for analyzeInlineCallArg Closes #12622 --- src/Sema.zig | 3 +-- .../cases/compile_errors/error_in_typeof_param.zig | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/cases/compile_errors/error_in_typeof_param.zig diff --git a/src/Sema.zig b/src/Sema.zig index 22aa26f737..4af9c80e02 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5941,10 +5941,9 @@ fn analyzeCall( undefined, ) catch |err| switch (err) { error.NeededSourceLocation => { - sema.inst_map.clearRetainingCapacity(); + _ = sema.inst_map.remove(inst); const decl = sema.mod.declPtr(block.src_decl); child_block.src_decl = block.src_decl; - arg_i = 0; try sema.analyzeInlineCallArg( block, &child_block, diff --git a/test/cases/compile_errors/error_in_typeof_param.zig b/test/cases/compile_errors/error_in_typeof_param.zig new file mode 100644 index 0000000000..747cdf3df6 --- /dev/null +++ b/test/cases/compile_errors/error_in_typeof_param.zig @@ -0,0 +1,14 @@ +fn getSize() usize { + return 2; +} +pub fn expectEqual(expected: anytype, _: @TypeOf(expected)) !void {} +pub export fn entry() void { + try expectEqual(2, getSize()); +} + +// error +// backend=stage2 +// target=native +// +// :6:31: error: unable to resolve comptime value +// :6:31: note: argument to parameter with comptime only type must be comptime known