Commit 84549b4267

LemonBoy <thatlemon@gmail.com>
2020-12-19 22:27:24
stage1: Fix for generic fn monomorphization
Don't use the instantiation argument types to build the function parameter array. f416535768fc30195cad6cd481f73fd1e80082aa worked around the problem, this commit solves it.
1 parent dd7b816
Changed files (3)
lib
std
src
stage1
test
stage1
behavior
lib/std/crypto/tlcsprng.zig
@@ -117,9 +117,7 @@ fn setupPthreadAtforkAndFill(buffer: []u8) void {
 }
 
 fn childAtForkHandler() callconv(.C) void {
-    // TODO this is a workaround for https://github.com/ziglang/zig/issues/7495
-    var wipe_slice: []u8 = undefined;
-    wipe_slice = @ptrCast([*]u8, &wipe_me)[0..@sizeOf(@TypeOf(wipe_me))];
+    const wipe_slice = @ptrCast([*]u8, &wipe_me)[0..@sizeOf(@TypeOf(wipe_me))];
     std.crypto.utils.secureZero(u8, wipe_slice);
 }
 
src/stage1/ir.cpp
@@ -20226,9 +20226,12 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
     bool is_var_args = param_decl_node->data.param_decl.is_var_args;
     bool arg_part_of_generic_id = false;
     IrInstGen *casted_arg;
+
+    ZigType *param_info_type = nullptr;
     if (is_var_args) {
         arg_part_of_generic_id = true;
         casted_arg = arg;
+        param_info_type = arg->value->type;
     } else {
         if (param_decl_node->data.param_decl.anytype_token == nullptr) {
             AstNode *param_type_node = param_decl_node->data.param_decl.type;
@@ -20239,9 +20242,12 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
             casted_arg = ir_implicit_cast2(ira, arg_src, arg, param_type);
             if (type_is_invalid(casted_arg->value->type))
                 return false;
+
+            param_info_type = param_type;
         } else {
             arg_part_of_generic_id = true;
             casted_arg = arg;
+            param_info_type = arg->value->type;
         }
     }
 
@@ -20298,7 +20304,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
     if (!comptime_arg) {
         casted_args[fn_type_id->param_count] = casted_arg;
         FnTypeParamInfo *param_info = &fn_type_id->param_info[fn_type_id->param_count];
-        param_info->type = casted_arg->value->type;
+        param_info->type = param_info_type;
         param_info->is_noalias = param_decl_node->data.param_decl.is_noalias;
         impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node;
         fn_type_id->param_count += 1;
test/stage1/behavior/generics.zig
@@ -1,4 +1,7 @@
-const expect = @import("std").testing.expect;
+const std = @import("std");
+const testing = std.testing;
+const expect = testing.expect;
+const expectEqual = testing.expectEqual;
 
 test "simple generic fn" {
     expect(max(i32, 3, -1) == 3);
@@ -149,3 +152,18 @@ test "array of generic fns" {
     expect(foos[0](true));
     expect(!foos[1](true));
 }
+
+test "generic fn keeps non-generic parameter types" {
+    const A = 128;
+
+    const S = struct {
+        fn f(comptime T: type, s: []T) void {
+            expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
+        }
+    };
+
+    // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
+    // `x` type not affect `s` parameter type.
+    var x: [16]u8 align(A) = undefined;
+    S.f(u8, &x);
+}