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 @@
77//! TODO(tiehuis): Benchmark these against other reference implementations.
88
99const std = @import("std.zig");
10const builtin = @import("builtin");
1011const assert = std.debug.assert;
1112const expect = std.testing.expect;
1213const expectEqual = std.testing.expectEqual;
......@@ -30,7 +31,10 @@ pub const Sfc64 = @import("rand/Sfc64.zig");
3031
3132pub const Random = struct {
3233 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
3539 pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random {
3640 const Ptr = @TypeOf(pointer);
src/Sema.zig+13
......@@ -5923,6 +5923,10 @@ fn funcCommon(
59235923 break :ret_ty ret_ty;
59245924 } else |err| break :err err;
59255925 } 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 }
59265930 };
59275931 switch (err) {
59285932 error.GenericPoison => {
......@@ -6111,6 +6115,13 @@ fn zirParam(
61116115
61126116 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
61136117 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 }
61146125 break :param_ty param_ty;
61156126 } else |err| break :err err;
61166127 } else |err| break :err err;
......@@ -10965,6 +10976,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1096510976
1096610977 const operand = try sema.resolveBody(&child_block, body, inst);
1096710978 const operand_ty = sema.typeOf(operand);
10979 if (operand_ty.tag() == .generic_poison) return error.GenericPoison;
1096810980 return sema.addType(operand_ty);
1096910981}
1097010982
......@@ -11044,6 +11056,7 @@ fn zirTypeofPeer(
1104411056
1104511057 for (args) |arg_ref, i| {
1104611058 inst_list[i] = sema.resolveInst(arg_ref);
11059 if (sema.typeOf(inst_list[i]).tag() == .generic_poison) return error.GenericPoison;
1104711060 }
1104811061
1104911062 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 {
230230 }
231231 };
232232}
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}