authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-11 11:24:01+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-11 11:25:45+02:00
log98a5998d831fd0fa7b897aafacf4c2af18e64ed1
tree04846185bf4314afe9c942a7e72e13ae76ae51cd
parent078037ab9b410fa13a86eabdfc30918fc83cdcf3

Sema: improve detection of generic parameters


3 files changed, 31 insertions(+), 1 deletions(-)

lib/std/rand.zig+5-1
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7//! TODO(tiehuis): Benchmark these against other reference implementations.7//! TODO(tiehuis): Benchmark these against other reference implementations.
88
9const std = @import("std.zig");9const std = @import("std.zig");
10const builtin = @import("builtin");
10const assert = std.debug.assert;11const assert = std.debug.assert;
11const expect = std.testing.expect;12const expect = std.testing.expect;
12const expectEqual = std.testing.expectEqual;13const expectEqual = std.testing.expectEqual;
...@@ -30,7 +31,10 @@ pub const Sfc64 = @import("rand/Sfc64.zig");...@@ -30,7 +31,10 @@ pub const Sfc64 = @import("rand/Sfc64.zig");
3031
31pub const Random = struct {32pub const Random = struct {
32 ptr: *anyopaque,33 ptr: *anyopaque,
33 fillFn: fn (ptr: *anyopaque, buf: []u8) void,34 fillFn: if (builtin.zig_backend == .stage1)
35 fn (ptr: *anyopaque, buf: []u8) void
36 else
37 *const fn (ptr: *anyopaque, buf: []u8) void,
3438
35 pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random {39 pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random {
36 const Ptr = @TypeOf(pointer);40 const Ptr = @TypeOf(pointer);
src/Sema.zig+13
...@@ -5923,6 +5923,10 @@ fn funcCommon(...@@ -5923,6 +5923,10 @@ fn funcCommon(
5923 break :ret_ty ret_ty;5923 break :ret_ty ret_ty;
5924 } else |err| break :err err;5924 } else |err| break :err err;
5925 } else |err| break :err err;5925 } else |err| break :err err;
5926 // Check for generic params.
5927 for (block.params.items) |param| {
5928 if (param.ty.tag() == .generic_poison) is_generic = true;
5929 }
5926 };5930 };
5927 switch (err) {5931 switch (err) {
5928 error.GenericPoison => {5932 error.GenericPoison => {
...@@ -6111,6 +6115,13 @@ fn zirParam(...@@ -6111,6 +6115,13 @@ fn zirParam(
61116115
6112 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {6116 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
6113 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {6117 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
6118 if (param_ty.zigTypeTag() == .Fn and param_ty.fnInfo().is_generic) {
6119 // zirFunc will not emit error.GenericPoison to build a
6120 // partial type for generic functions but we still need to
6121 // detect if a function parameter is a generic function
6122 // to force the parent function to also be generic.
6123 break :err error.GenericPoison;
6124 }
6114 break :param_ty param_ty;6125 break :param_ty param_ty;
6115 } else |err| break :err err;6126 } else |err| break :err err;
6116 } else |err| break :err err;6127 } else |err| break :err err;
...@@ -10965,6 +10976,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -10965,6 +10976,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1096510976
10966 const operand = try sema.resolveBody(&child_block, body, inst);10977 const operand = try sema.resolveBody(&child_block, body, inst);
10967 const operand_ty = sema.typeOf(operand);10978 const operand_ty = sema.typeOf(operand);
10979 if (operand_ty.tag() == .generic_poison) return error.GenericPoison;
10968 return sema.addType(operand_ty);10980 return sema.addType(operand_ty);
10969}10981}
1097010982
...@@ -11044,6 +11056,7 @@ fn zirTypeofPeer(...@@ -11044,6 +11056,7 @@ fn zirTypeofPeer(
1104411056
11045 for (args) |arg_ref, i| {11057 for (args) |arg_ref, i| {
11046 inst_list[i] = sema.resolveInst(arg_ref);11058 inst_list[i] = sema.resolveInst(arg_ref);
11059 if (sema.typeOf(inst_list[i]).tag() == .generic_poison) return error.GenericPoison;
11047 }11060 }
1104811061
11049 const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node });11062 const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node });
test/behavior/generics.zig+13
...@@ -230,3 +230,16 @@ fn GenNode(comptime T: type) type {...@@ -230,3 +230,16 @@ fn GenNode(comptime T: type) type {
230 }230 }
231 };231 };
232}232}
233
234test "function parameter is generic" {
235 const S = struct {
236 pub fn init(pointer: anytype, comptime fillFn: fn (ptr: *@TypeOf(pointer)) void) void {
237 _ = fillFn;
238 }
239 pub fn fill(self: *u32) void {
240 _ = self;
241 }
242 };
243 var rng: u32 = 2;
244 S.init(rng, S.fill);
245}