Commit 3525b8778e

Veikka Tuominen <git@vexu.eu>
2022-09-23 15:55:46
Sema: properly handle generic struct as parameter type
Closes #12907
1 parent ede3798
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -8277,8 +8277,21 @@ fn zirParam(
             else => |e| return e,
         }
     };
-    const is_comptime = comptime_syntax or
-        try sema.typeRequiresComptime(param_ty);
+    const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
+        error.GenericPoison => {
+            // The type is not available until the generic instantiation.
+            // We result the param instruction with a poison value and
+            // insert an anytype parameter.
+            try block.params.append(sema.gpa, .{
+                .ty = Type.initTag(.generic_poison),
+                .is_comptime = comptime_syntax,
+                .name = param_name,
+            });
+            try sema.inst_map.putNoClobber(sema.gpa, inst, .generic_poison);
+            return;
+        },
+        else => |e| return e,
+    } or comptime_syntax;
     if (sema.inst_map.get(inst)) |arg| {
         if (is_comptime) {
             // We have a comptime value for this parameter so it should be elided from the
test/behavior/generics.zig
@@ -369,3 +369,16 @@ test "extern function used as generic parameter" {
     };
     try expect(S.baz(S.foo) != S.baz(S.bar));
 }
+
+test "generic struct as parameter type" {
+    const S = struct {
+        fn doTheTest(comptime Int: type, thing: struct { int: Int }) !void {
+            try expect(thing.int == 123);
+        }
+        fn doTheTest2(comptime Int: type, comptime thing: struct { int: Int }) !void {
+            try expect(thing.int == 456);
+        }
+    };
+    try S.doTheTest(u32, .{ .int = 123 });
+    try S.doTheTest2(i32, .{ .int = 456 });
+}