Commit 9821a0c6f0
Changed files (3)
test
behavior
src/Sema.zig
@@ -4764,12 +4764,20 @@ fn analyzeCall(
const gpa = sema.gpa;
- var is_comptime_call = block.is_comptime or modifier == .compile_time or
- try sema.typeRequiresComptime(block, func_src, func_ty_info.return_type);
+ var is_generic_call = func_ty_info.is_generic;
+ var is_comptime_call = block.is_comptime or modifier == .compile_time;
+ if (!is_comptime_call) {
+ if (sema.typeRequiresComptime(block, func_src, func_ty_info.return_type)) |ct| {
+ is_comptime_call = ct;
+ } else |err| switch (err) {
+ error.GenericPoison => is_generic_call = true,
+ else => |e| return e,
+ }
+ }
var is_inline_call = is_comptime_call or modifier == .always_inline or
func_ty_info.cc == .Inline;
- if (!is_inline_call and func_ty_info.is_generic) {
+ if (!is_inline_call and is_generic_call) {
if (sema.instantiateGenericCall(
block,
func,
@@ -6410,10 +6418,20 @@ fn funcCommon(
}
}
- is_generic = is_generic or
- try sema.typeRequiresComptime(block, ret_ty_src, bare_return_type);
+ const ret_poison = if (!is_generic) rp: {
+ if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| {
+ is_generic = ret_comptime;
+ break :rp bare_return_type.tag() == .generic_poison;
+ } else |err| switch (err) {
+ error.GenericPoison => {
+ is_generic = true;
+ break :rp true;
+ },
+ else => |e| return e,
+ }
+ } else bare_return_type.tag() == .generic_poison;
- const return_type = if (!inferred_error_set or bare_return_type.tag() == .generic_poison)
+ const return_type = if (!inferred_error_set or ret_poison)
bare_return_type
else blk: {
const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode);
@@ -13570,7 +13588,7 @@ fn reifyStruct(
.zir_index = inst,
.layout = layout_val.toEnum(std.builtin.Type.ContainerLayout),
.status = .have_field_types,
- .known_non_opv = undefined,
+ .known_non_opv = false,
.namespace = .{
.parent = block.namespace,
.ty = struct_ty,
@@ -21666,6 +21684,10 @@ fn semaStructFields(
// TODO emit compile errors for invalid field types
// such as arrays and pointers inside packed structs.
+ if (field_ty.tag() == .generic_poison) {
+ return error.GenericPoison;
+ }
+
const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
assert(!gop.found_existing);
gop.value_ptr.* = .{
@@ -21913,6 +21935,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
// But only resolve the source location if we need to emit a compile error.
try sema.resolveType(&block_scope, src, field_type_ref);
+ if (field_ty.tag() == .generic_poison) {
+ return error.GenericPoison;
+ }
+
const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
assert(!gop.found_existing);
gop.value_ptr.* = .{
src/Zir.zig
@@ -63,7 +63,7 @@ pub const ExtraIndex = enum(u32) {
/// Returns the requested data, as well as the new index which is at the start of the
/// trailers for the object.
pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } {
- const fields = std.meta.fields(T);
+ const fields = @typeInfo(T).Struct.fields;
var i: usize = index;
var result: T = undefined;
inline for (fields) |field| {
@@ -94,7 +94,8 @@ pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
const raw_slice = code.extra[start..][0..len];
- return @bitCast([]Inst.Ref, raw_slice);
+ // TODO we should be able to directly `@ptrCast` the slice to the other slice type.
+ return @ptrCast([*]Inst.Ref, raw_slice.ptr)[0..len];
}
pub fn hasCompileErrors(code: Zir) bool {
test/behavior/generics.zig
@@ -290,3 +290,19 @@ test "generic function with void and comptime parameter" {
var s: S = .{ .x = 1234 };
try namespace.foo({}, &s, u8);
}
+
+test "anonymous struct return type referencing comptime parameter" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ pub fn extraData(comptime T: type, index: usize) struct { data: T, end: usize } {
+ return .{
+ .data = 1234,
+ .end = index,
+ };
+ }
+ };
+ const s = S.extraData(i32, 5678);
+ try expect(s.data == 1234);
+ try expect(s.end == 5678);
+}