From f0176eec4a744c17fc49cbd63c67179887005935 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 20 Aug 2021 17:44:03 -0700 Subject: [PATCH] stage2: support comptime fn call returning type ...when the field type expressions reference locals as well as comptime function parameters. --- src/Sema.zig | 13 ++++++++++++- test/behavior/generics.zig | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Sema.zig b/src/Sema.zig index 78f0948623..8ffc828fba 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2623,7 +2623,18 @@ fn analyzeCall( defer sema.fn_ret_ty = parent_fn_ret_ty; _ = try sema.analyzeBody(&child_block, fn_info.body); - break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges); + const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges); + + // Much like in `Module.semaDecl`, if the result is a struct or union type, + // we need to resolve the field type expressions right here, right now, while + // the child `Sema` is still available, with the AIR instruction map intact, + // because the field type expressions may reference into it. + if (sema.typeOf(result).zigTypeTag() == .Type) { + const ty = try sema.analyzeAsType(&child_block, call_src, result); + try sema.resolveDeclFields(&child_block, call_src, ty); + } + + break :res result; } else if (func_ty_info.is_generic) res: { const func_val = try sema.resolveConstValue(block, func_src, func); const module_fn = func_val.castTag(.function).?.data; diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index 67fb1def8b..2d487a6f16 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -78,3 +78,21 @@ fn max_i32(a: i32, b: i32) i32 { fn max_f64(a: f64, b: f64) f64 { return max_anytype(a, b); } + +test "type constructed by comptime function call" { + var l: List(10) = undefined; + l.array[0] = 10; + l.array[1] = 11; + l.array[2] = 12; + const ptr = @ptrCast([*]u8, &l.array); + try expect(ptr[0] == 10); + try expect(ptr[1] == 11); + try expect(ptr[2] == 12); +} + +fn List(comptime L: usize) type { + var T = u8; + return struct { + array: [L]T, + }; +}