authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-19 23:19:59+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-21 02:41:42+00:00
log0ec6b2dd883568900aa28dd5fea6d22258eed792
tree5c731f5f54deb17b0e8bf674be1ba29052f7a3ea
parent216e0f37306d5cded92d547f65f9c2566d7b1523

compiler: simplify generic functions, fix issues with inline calls

The original motivation here was to fix regressions caused by #22414. However, while working on this, I ended up discussing a language simplification with Andrew, which changes things a little from how they worked before #22414. The main user-facing change here is that any reference to a prior function parameter, even if potentially comptime-known at the usage site or even not analyzed, now makes a function generic. This applies even if the parameter being referenced is not a `comptime` parameter, since it could still be populated when performing an inline call. This is a breaking language change. The detection of this is done in AstGen; when evaluating a parameter type or return type, we track whether it referenced any prior parameter, and if so, we mark this type as being "generic" in ZIR. This will cause Sema to not evaluate it until the time of instantiation or inline call. A lovely consequence of this from an implementation perspective is that it eliminates the need for most of the "generic poison" system. In particular, `error.GenericPoison` is now completely unnecessary, because we identify generic expressions earlier in the pipeline; this simplifies the compiler and avoids redundant work. This also entirely eliminates the concept of the "generic poison value". The only remnant of this system is the "generic poison type" (`Type.generic_poison` and `InternPool.Index.generic_poison_type`). This type is used in two places: * During semantic analysis, to represent an unknown result type. * When storing generic function types, to represent a generic parameter/return type. It's possible that these use cases should instead use `.none`, but I leave that investigation to a future adventurer. One last thing. Prior to #22414, inline calls were a little inefficient, because they re-evaluated even non-generic parameter types whenever they were called. Changing this behavior is what ultimately led to #22538. Well, because the new logic will mark a type expression as generic if there is any change its resolved type could differ in an inline call, this redundant work is unnecessary! So, this is another way in which the new design reduces redundant work and complexity. Resolves: #22494 Resolves: #22532 Resolves: #22538

23 files changed, 265 insertions(+), 378 deletions(-)

lib/std/zig/AstGen.zig+30-4
......@@ -107,6 +107,8 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
107107 Zir.Inst.SwitchBlock.Bits,
108108 Zir.Inst.SwitchBlockErrUnion.Bits,
109109 Zir.Inst.FuncFancy.Bits,
110 Zir.Inst.Param.Type,
111 Zir.Inst.Func.RetTy,
110112 => @bitCast(@field(extra, field.name)),
111113
112114 else => @compileError("bad field type"),
......@@ -1384,7 +1386,7 @@ fn fnProtoExprInner(
13841386 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
13851387 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous
13861388 // arguments (we haven't set up scopes here).
1387 const param_inst = try block_scope.addParam(&param_gz, &.{}, tag, name_token, param_name);
1389 const param_inst = try block_scope.addParam(&param_gz, &.{}, false, tag, name_token, param_name);
13881390 assert(param_inst_expected == param_inst);
13891391 }
13901392 }
......@@ -1416,6 +1418,7 @@ fn fnProtoExprInner(
14161418
14171419 .ret_param_refs = &.{},
14181420 .param_insts = &.{},
1421 .ret_ty_is_generic = false,
14191422
14201423 .param_block = block_inst,
14211424 .body_gz = null,
......@@ -4336,6 +4339,9 @@ fn fnDeclInner(
43364339 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
43374340 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
43384341
4342 // We use this as `is_used_or_discarded` to figure out if parameters / return types are generic.
4343 var any_param_used = false;
4344
43394345 var noalias_bits: u32 = 0;
43404346 var params_scope = scope;
43414347 const is_var_args = is_var_args: {
......@@ -4409,16 +4415,18 @@ fn fnDeclInner(
44094415 } else param: {
44104416 const param_type_node = param.type_expr;
44114417 assert(param_type_node != 0);
4418 any_param_used = false; // we will check this later
44124419 var param_gz = decl_gz.makeSubBlock(scope);
44134420 defer param_gz.unstack();
44144421 const param_type = try fullBodyExpr(&param_gz, params_scope, coerced_type_ri, param_type_node, .normal);
44154422 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
44164423 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
4424 const param_type_is_generic = any_param_used;
44174425
44184426 const main_tokens = tree.nodes.items(.main_token);
44194427 const name_token = param.name_token orelse main_tokens[param_type_node];
44204428 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
4421 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, tag, name_token, param_name);
4429 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name);
44224430 assert(param_inst_expected == param_inst);
44234431 break :param param_inst.toRef();
44244432 };
......@@ -4433,6 +4441,7 @@ fn fnDeclInner(
44334441 .inst = param_inst,
44344442 .token_src = param.name_token.?,
44354443 .id_cat = .@"function parameter",
4444 .is_used_or_discarded = &any_param_used,
44364445 };
44374446 params_scope = &sub_scope.base;
44384447 try param_insts.append(astgen.arena, param_inst.toIndex().?);
......@@ -4446,6 +4455,7 @@ fn fnDeclInner(
44464455
44474456 var ret_gz = decl_gz.makeSubBlock(params_scope);
44484457 defer ret_gz.unstack();
4458 any_param_used = false; // we will check this later
44494459 const ret_ref: Zir.Inst.Ref = inst: {
44504460 // Parameters are in scope for the return type, so we use `params_scope` here.
44514461 // The calling convention will not have parameters in scope, so we'll just use `scope`.
......@@ -4459,6 +4469,7 @@ fn fnDeclInner(
44594469 break :inst inst;
44604470 };
44614471 const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items);
4472 const ret_ty_is_generic = any_param_used;
44624473
44634474 // We're jumping back in source, so restore the cursor.
44644475 astgen.restoreSourceCursor(saved_cursor);
......@@ -4556,6 +4567,7 @@ fn fnDeclInner(
45564567 .ret_ref = ret_ref,
45574568 .ret_gz = &ret_gz,
45584569 .ret_param_refs = ret_body_param_refs,
4570 .ret_ty_is_generic = ret_ty_is_generic,
45594571 .lbrace_line = lbrace_line,
45604572 .lbrace_column = lbrace_column,
45614573 .param_block = decl_inst,
......@@ -5028,6 +5040,7 @@ fn testDecl(
50285040
50295041 .ret_param_refs = &.{},
50305042 .param_insts = &.{},
5043 .ret_ty_is_generic = false,
50315044
50325045 .lbrace_line = lbrace_line,
50335046 .lbrace_column = lbrace_column,
......@@ -8546,6 +8559,8 @@ fn localVarRef(
85468559 local_val.used = ident_token;
85478560 }
85488561
8562 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
8563
85498564 const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure(
85508565 gz,
85518566 ident,
......@@ -11876,6 +11891,7 @@ const Scope = struct {
1187611891 /// Track the identifier where it is discarded, like this `_ = foo;`.
1187711892 /// 0 means never discarded.
1187811893 discarded: Ast.TokenIndex = 0,
11894 is_used_or_discarded: ?*bool = null,
1187911895 /// String table index.
1188011896 name: Zir.NullTerminatedString,
1188111897 id_cat: IdCat,
......@@ -12223,6 +12239,7 @@ const GenZir = struct {
1222312239
1222412240 ret_param_refs: []Zir.Inst.Index,
1222512241 param_insts: []Zir.Inst.Index, // refs to params in `body_gz` should still be in `astgen.ref_table`
12242 ret_ty_is_generic: bool,
1222612243
1222712244 cc_ref: Zir.Inst.Ref,
1222812245 ret_ref: Zir.Inst.Ref,
......@@ -12322,6 +12339,8 @@ const GenZir = struct {
1232212339
1232312340 .has_cc_body = cc_body.len != 0,
1232412341 .has_ret_ty_body = ret_body.len != 0,
12342
12343 .ret_ty_is_generic = args.ret_ty_is_generic,
1232512344 },
1232612345 });
1232712346
......@@ -12372,7 +12391,10 @@ const GenZir = struct {
1237212391
1237312392 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
1237412393 .param_block = args.param_block,
12375 .ret_body_len = ret_body_len,
12394 .ret_ty = .{
12395 .body_len = @intCast(ret_body_len),
12396 .is_generic = args.ret_ty_is_generic,
12397 },
1237612398 .body_len = body_len,
1237712399 });
1237812400 const zir_datas = astgen.instructions.items(.data);
......@@ -12535,6 +12557,7 @@ const GenZir = struct {
1253512557 /// Previous parameters, which might be referenced in `param_gz` (the new parameter type).
1253612558 /// `ref`s of these instructions will be put into this param's type body, and removed from `AstGen.ref_table`.
1253712559 prev_param_insts: []const Zir.Inst.Index,
12560 ty_is_generic: bool,
1253812561 tag: Zir.Inst.Tag,
1253912562 /// Absolute token index. This function does the conversion to Decl offset.
1254012563 abs_tok_index: Ast.TokenIndex,
......@@ -12548,7 +12571,10 @@ const GenZir = struct {
1254812571
1254912572 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
1255012573 .name = name,
12551 .body_len = @intCast(body_len),
12574 .type = .{
12575 .body_len = @intCast(body_len),
12576 .is_generic = ty_is_generic,
12577 },
1255212578 });
1255312579 gz.astgen.appendBodyWithFixupsExtraRefsArrayList(&gz.astgen.extra, param_body, prev_param_insts);
1255412580 param_gz.unstack();
lib/std/zig/Zir.zig+38-18
......@@ -89,6 +89,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
8989 Inst.SwitchBlockErrUnion.Bits,
9090 Inst.FuncFancy.Bits,
9191 Inst.Declaration.Flags,
92 Inst.Param.Type,
93 Inst.Func.RetTy,
9294 => @bitCast(code.extra[i]),
9395
9496 else => @compileError("bad field type"),
......@@ -2126,7 +2128,7 @@ pub const Inst = struct {
21262128 ref_start_index = static_len,
21272129 _,
21282130
2129 pub const static_len = 71;
2131 pub const static_len = 70;
21302132
21312133 pub fn toRef(i: Index) Inst.Ref {
21322134 return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i));
......@@ -2229,7 +2231,6 @@ pub const Inst = struct {
22292231 bool_true,
22302232 bool_false,
22312233 empty_tuple,
2232 generic_poison,
22332234
22342235 /// This Ref does not correspond to any ZIR instruction or constant
22352236 /// value and may instead be used as a sentinel to indicate null.
......@@ -2472,24 +2473,31 @@ pub const Inst = struct {
24722473 };
24732474
24742475 /// Trailing:
2475 /// if (ret_body_len == 1) {
2476 /// if (ret_ty.body_len == 1) {
24762477 /// 0. return_type: Ref
24772478 /// }
2478 /// if (ret_body_len > 1) {
2479 /// 1. return_type: Index // for each ret_body_len
2479 /// if (ret_ty.body_len > 1) {
2480 /// 1. return_type: Index // for each ret_ty.body_len
24802481 /// }
24812482 /// 2. body: Index // for each body_len
24822483 /// 3. src_locs: SrcLocs // if body_len != 0
24832484 /// 4. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype
24842485 pub const Func = struct {
2485 /// If this is 0 it means a void return type.
2486 /// If this is 1 it means return_type is a simple Ref
2487 ret_body_len: u32,
2486 ret_ty: RetTy,
24882487 /// Points to the block that contains the param instructions for this function.
24892488 /// If this is a `declaration`, it refers to the declaration's value body.
24902489 param_block: Index,
24912490 body_len: u32,
24922491
2492 pub const RetTy = packed struct(u32) {
2493 /// 0 means `void`.
2494 /// 1 means the type is a simple `Ref`.
2495 /// Otherwise, the length of a trailing body.
2496 body_len: u31,
2497 /// Whether the return type is generic, i.e. refers to one or more previous parameters.
2498 is_generic: bool,
2499 };
2500
24932501 pub const SrcLocs = struct {
24942502 /// Line index in the source file relative to the parent decl.
24952503 lbrace_line: u32,
......@@ -2539,7 +2547,8 @@ pub const Inst = struct {
25392547 has_ret_ty_ref: bool,
25402548 has_ret_ty_body: bool,
25412549 has_any_noalias: bool,
2542 _: u24 = undefined,
2550 ret_ty_is_generic: bool,
2551 _: u23 = undefined,
25432552 };
25442553 };
25452554
......@@ -3708,8 +3717,14 @@ pub const Inst = struct {
37083717 pub const Param = struct {
37093718 /// Null-terminated string index.
37103719 name: NullTerminatedString,
3711 /// The body contains the type of the parameter.
3712 body_len: u32,
3720 type: Type,
3721
3722 pub const Type = packed struct(u32) {
3723 /// The body contains the type of the parameter.
3724 body_len: u31,
3725 /// Whether the type is generic, i.e. refers to one or more previous parameters.
3726 is_generic: bool,
3727 };
37133728 };
37143729
37153730 /// Trailing:
......@@ -4492,7 +4507,7 @@ fn findTrackableInner(
44924507
44934508 if (extra.data.body_len == 0) {
44944509 // This is just a prototype. No need to track.
4495 assert(extra.data.ret_body_len < 2);
4510 assert(extra.data.ret_ty.body_len < 2);
44964511 return;
44974512 }
44984513
......@@ -4500,11 +4515,11 @@ fn findTrackableInner(
45004515 contents.func_decl = inst;
45014516
45024517 var extra_index: usize = extra.end;
4503 switch (extra.data.ret_body_len) {
4518 switch (extra.data.ret_ty.body_len) {
45044519 0 => {},
45054520 1 => extra_index += 1,
45064521 else => {
4507 const body = zir.bodySlice(extra_index, extra.data.ret_body_len);
4522 const body = zir.bodySlice(extra_index, extra.data.ret_ty.body_len);
45084523 extra_index += body.len;
45094524 try zir.findTrackableBody(gpa, contents, defers, body);
45104525 },
......@@ -4595,7 +4610,7 @@ fn findTrackableInner(
45954610 .param, .param_comptime => {
45964611 const inst_data = datas[@intFromEnum(inst)].pl_tok;
45974612 const extra = zir.extraData(Inst.Param, inst_data.payload_index);
4598 const body = zir.bodySlice(extra.end, extra.data.body_len);
4613 const body = zir.bodySlice(extra.end, extra.data.type.body_len);
45994614 try zir.findTrackableBody(gpa, contents, defers, body);
46004615 },
46014616
......@@ -4738,6 +4753,7 @@ pub const FnInfo = struct {
47384753 ret_ty_body: []const Inst.Index,
47394754 body: []const Inst.Index,
47404755 ret_ty_ref: Zir.Inst.Ref,
4756 ret_ty_is_generic: bool,
47414757 total_params_len: u32,
47424758 inferred_error_set: bool,
47434759};
......@@ -4779,6 +4795,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
47794795 body: []const Inst.Index,
47804796 ret_ty_ref: Inst.Ref,
47814797 ret_ty_body: []const Inst.Index,
4798 ret_ty_is_generic: bool,
47824799 ies: bool,
47834800 } = switch (tags[@intFromEnum(fn_inst)]) {
47844801 .func, .func_inferred => |tag| blk: {
......@@ -4789,7 +4806,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
47894806 var ret_ty_ref: Inst.Ref = .none;
47904807 var ret_ty_body: []const Inst.Index = &.{};
47914808
4792 switch (extra.data.ret_body_len) {
4809 switch (extra.data.ret_ty.body_len) {
47934810 0 => {
47944811 ret_ty_ref = .void_type;
47954812 },
......@@ -4798,7 +4815,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
47984815 extra_index += 1;
47994816 },
48004817 else => {
4801 ret_ty_body = zir.bodySlice(extra_index, extra.data.ret_body_len);
4818 ret_ty_body = zir.bodySlice(extra_index, extra.data.ret_ty.body_len);
48024819 extra_index += ret_ty_body.len;
48034820 },
48044821 }
......@@ -4811,6 +4828,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
48114828 .ret_ty_ref = ret_ty_ref,
48124829 .ret_ty_body = ret_ty_body,
48134830 .body = body,
4831 .ret_ty_is_generic = extra.data.ret_ty.is_generic,
48144832 .ies = tag == .func_inferred,
48154833 };
48164834 },
......@@ -4848,6 +4866,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
48484866 .ret_ty_ref = ret_ty_ref,
48494867 .ret_ty_body = ret_ty_body,
48504868 .body = body,
4869 .ret_ty_is_generic = extra.data.bits.ret_ty_is_generic,
48514870 .ies = extra.data.bits.is_inferred_error,
48524871 };
48534872 },
......@@ -4870,6 +4889,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
48704889 .ret_ty_ref = info.ret_ty_ref,
48714890 .body = info.body,
48724891 .total_params_len = total_params_len,
4892 .ret_ty_is_generic = info.ret_ty_is_generic,
48734893 .inferred_error_set = info.ies,
48744894 };
48754895}
......@@ -4967,7 +4987,7 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
49674987 return null;
49684988 }
49694989 const extra_index = extra.end +
4970 extra.data.ret_body_len +
4990 extra.data.ret_ty.body_len +
49714991 extra.data.body_len +
49724992 @typeInfo(Inst.Func.SrcLocs).@"struct".fields.len;
49734993 return @bitCast([4]u32{
src/Air.zig-1
......@@ -1004,7 +1004,6 @@ pub const Inst = struct {
10041004 bool_true = @intFromEnum(InternPool.Index.bool_true),
10051005 bool_false = @intFromEnum(InternPool.Index.bool_false),
10061006 empty_tuple = @intFromEnum(InternPool.Index.empty_tuple),
1007 generic_poison = @intFromEnum(InternPool.Index.generic_poison),
10081007
10091008 /// This Ref does not correspond to any AIR instruction or constant
10101009 /// value and may instead be used as a sentinel to indicate null.
src/Air/types_resolved.zig+2-3
......@@ -455,9 +455,8 @@ pub fn checkVal(val: Value, zcu: *Zcu) bool {
455455
456456pub fn checkType(ty: Type, zcu: *Zcu) bool {
457457 const ip = &zcu.intern_pool;
458 return switch (ty.zigTypeTagOrPoison(zcu) catch |err| switch (err) {
459 error.GenericPoison => return true,
460 }) {
458 if (ty.isGenericPoison()) return true;
459 return switch (ty.zigTypeTag(zcu)) {
461460 .type,
462461 .void,
463462 .bool,
src/InternPool.zig+11-16
......@@ -620,11 +620,11 @@ pub const Nav = struct {
620620 return switch (nav.status) {
621621 .unresolved => unreachable,
622622 .type_resolved => |r| {
623 const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable;
623 const tag = ip.zigTypeTag(r.type);
624624 return tag == .@"fn";
625625 },
626626 .fully_resolved => |r| {
627 const tag = ip.zigTypeTagOrPoison(ip.typeOf(r.val)) catch unreachable;
627 const tag = ip.zigTypeTag(ip.typeOf(r.val));
628628 return tag == .@"fn";
629629 },
630630 };
......@@ -639,13 +639,13 @@ pub const Nav = struct {
639639 .unresolved => unreachable,
640640 .type_resolved => |r| {
641641 if (r.is_extern_decl) return true;
642 const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable;
642 const tag = ip.zigTypeTag(r.type);
643643 if (tag == .@"fn") return true;
644644 return false;
645645 },
646646 .fully_resolved => |r| {
647647 if (ip.indexToKey(r.val) == .@"extern") return true;
648 const tag = ip.zigTypeTagOrPoison(ip.typeOf(r.val)) catch unreachable;
648 const tag = ip.zigTypeTag(ip.typeOf(r.val));
649649 if (tag == .@"fn") return true;
650650 return false;
651651 },
......@@ -3216,7 +3216,6 @@ pub const Key = union(enum) {
32163216 .false, .true => .bool_type,
32173217 .empty_tuple => .empty_tuple_type,
32183218 .@"unreachable" => .noreturn_type,
3219 .generic_poison => .generic_poison_type,
32203219 },
32213220
32223221 .memoized_call => unreachable,
......@@ -4581,6 +4580,10 @@ pub const Index = enum(u32) {
45814580 anyerror_void_error_union_type,
45824581 /// Used for the inferred error set of inline/comptime function calls.
45834582 adhoc_inferred_error_set_type,
4583 /// Represents a type which is unknown.
4584 /// This is used in functions to represent generic parameter/return types, and
4585 /// during semantic analysis to represent unknown result types (i.e. where AstGen
4586 /// thought we would have a result type, but we do not).
45844587 generic_poison_type,
45854588 /// `@TypeOf(.{})`; a tuple with zero elements.
45864589 /// This is not the same as `struct {}`, since that is a struct rather than a tuple.
......@@ -4617,10 +4620,6 @@ pub const Index = enum(u32) {
46174620 /// `.{}`
46184621 empty_tuple,
46194622
4620 /// Used for generic parameters where the type and value
4621 /// is not known until generic function instantiation.
4622 generic_poison,
4623
46244623 /// Used by Air/Sema only.
46254624 none = std.math.maxInt(u32),
46264625
......@@ -5136,7 +5135,6 @@ pub const static_keys = [_]Key{
51365135 .{ .simple_value = .true },
51375136 .{ .simple_value = .false },
51385137 .{ .simple_value = .empty_tuple },
5139 .{ .simple_value = .generic_poison },
51405138};
51415139
51425140/// How many items in the InternPool are statically known.
......@@ -6054,8 +6052,6 @@ pub const SimpleValue = enum(u32) {
60546052 true = @intFromEnum(Index.bool_true),
60556053 false = @intFromEnum(Index.bool_false),
60566054 @"unreachable" = @intFromEnum(Index.unreachable_value),
6057
6058 generic_poison = @intFromEnum(Index.generic_poison),
60596055};
60606056
60616057/// Stored as a power-of-two, with one special value to indicate none.
......@@ -11712,7 +11708,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
1171211708 .null_value => .null_type,
1171311709 .bool_true, .bool_false => .bool_type,
1171411710 .empty_tuple => .empty_tuple_type,
11715 .generic_poison => .generic_poison_type,
1171611711
1171711712 // This optimization on tags is needed so that indexToKey can call
1171811713 // typeOf without being recursive.
......@@ -11954,7 +11949,8 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Ta
1195411949
1195511950/// This is a particularly hot function, so we operate directly on encodings
1195611951/// rather than the more straightforward implementation of calling `indexToKey`.
11957pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
11952/// Asserts `index` is not `.generic_poison_type`.
11953pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
1195811954 return switch (index) {
1195911955 .u0_type,
1196011956 .i0_type,
......@@ -12017,7 +12013,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
1201712013 .anyerror_void_error_union_type => .error_union,
1201812014 .empty_tuple_type => .@"struct",
1201912015
12020 .generic_poison_type => return error.GenericPoison,
12016 .generic_poison_type => unreachable,
1202112017
1202212018 // values, not types
1202312019 .undef => unreachable,
......@@ -12035,7 +12031,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
1203512031 .bool_true => unreachable,
1203612032 .bool_false => unreachable,
1203712033 .empty_tuple => unreachable,
12038 .generic_poison => unreachable,
1203912034
1204012035 _ => switch (index.unwrap(ip).getTag(ip)) {
1204112036 .removed => unreachable,
src/Sema.zig+127-292
......@@ -53,9 +53,6 @@ comptime_break_inst: Zir.Inst.Index = undefined,
5353post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .empty,
5454/// Populated with the last compile error created.
5555err: ?*Zcu.ErrorMsg = null,
56/// Set to true when analyzing a func type instruction so that nested generic
57/// function types will emit generic poison instead of a partial type.
58no_partial_func_ty: bool = false,
5956
6057/// The temporary arena is used for the memory of the `InferredAlloc` values
6158/// here so the values can be dropped without any cleanup.
......@@ -1935,9 +1932,7 @@ pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
19351932pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
19361933 assert(zir_ref != .none);
19371934 if (zir_ref.toIndex()) |i| {
1938 const inst = sema.inst_map.get(i).?;
1939 if (inst == .generic_poison) return error.GenericPoison;
1940 return inst;
1935 return sema.inst_map.get(i).?;
19411936 }
19421937 // First section of indexes correspond to a set number of constant values.
19431938 // We intentionally map the same indexes to the same values between ZIR and AIR.
......@@ -1997,13 +1992,17 @@ pub fn resolveConstStringIntern(
19971992 return sema.sliceToIpString(block, src, val, reason);
19981993}
19991994
2000pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
1995fn resolveTypeOrPoison(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !?Type {
20011996 const air_inst = try sema.resolveInst(zir_ref);
20021997 const ty = try sema.analyzeAsType(block, src, air_inst);
2003 if (ty.isGenericPoison()) return error.GenericPoison;
1998 if (ty.isGenericPoison()) return null;
20041999 return ty;
20052000}
20062001
2002pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
2003 return (try sema.resolveTypeOrPoison(block, src, zir_ref)).?;
2004}
2005
20072006fn resolveDestType(
20082007 sema: *Sema,
20092008 block: *Block,
......@@ -2023,24 +2022,21 @@ fn resolveDestType(
20232022 .remove_eu => false,
20242023 };
20252024
2026 const raw_ty = sema.resolveType(block, src, zir_ref) catch |err| switch (err) {
2027 error.GenericPoison => {
2028 // Cast builtins use their result type as the destination type, but
2029 // it could be an anytype argument, which we can't catch in AstGen.
2030 const msg = msg: {
2031 const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name});
2032 errdefer msg.destroy(sema.gpa);
2033 switch (sema.genericPoisonReason(block, zir_ref)) {
2034 .anytype_param => |call_src| try sema.errNote(call_src, msg, "result type is unknown due to anytype parameter", .{}),
2035 .anyopaque_ptr => |ptr_src| try sema.errNote(ptr_src, msg, "result type is unknown due to opaque pointer type", .{}),
2036 .unknown => {},
2037 }
2038 try sema.errNote(src, msg, "use @as to provide explicit result type", .{});
2039 break :msg msg;
2040 };
2041 return sema.failWithOwnedErrorMsg(block, msg);
2042 },
2043 else => |e| return e,
2025 const raw_ty = try sema.resolveTypeOrPoison(block, src, zir_ref) orelse {
2026 // Cast builtins use their result type as the destination type, but
2027 // it could be an anytype argument, which we can't catch in AstGen.
2028 const msg = msg: {
2029 const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name});
2030 errdefer msg.destroy(sema.gpa);
2031 switch (sema.genericPoisonReason(block, zir_ref)) {
2032 .anytype_param => |call_src| try sema.errNote(call_src, msg, "result type is unknown due to anytype parameter", .{}),
2033 .anyopaque_ptr => |ptr_src| try sema.errNote(ptr_src, msg, "result type is unknown due to opaque pointer type", .{}),
2034 .unknown => {},
2035 }
2036 try sema.errNote(src, msg, "use @as to provide explicit result type", .{});
2037 break :msg msg;
2038 };
2039 return sema.failWithOwnedErrorMsg(block, msg);
20442040 };
20452041
20462042 if (remove_eu and raw_ty.zigTypeTag(zcu) == .error_union) {
......@@ -2086,9 +2082,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
20862082 // Either the input type was itself poison, or it was a slice, which we cannot translate
20872083 // to an overall result type.
20882084 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2089 const operand_ref = sema.resolveInst(un_node.operand) catch |err| switch (err) {
2090 error.GenericPoison => unreachable, // this is a type, not a value
2091 };
2085 const operand_ref = try sema.resolveInst(un_node.operand);
20922086 if (operand_ref == .generic_poison_type) {
20932087 // The input was poison -- keep looking.
20942088 cur = un_node.operand;
......@@ -2107,9 +2101,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
21072101 // There are two cases here: the pointer type may already have been
21082102 // generic poison, or it may have been an anyopaque pointer.
21092103 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2110 const operand_ref = sema.resolveInst(un_node.operand) catch |err| switch (err) {
2111 error.GenericPoison => unreachable, // this is a type, not a value
2112 };
2104 const operand_ref = try sema.resolveInst(un_node.operand);
21132105 const operand_val = operand_ref.toInterned() orelse return .unknown;
21142106 if (operand_val == .generic_poison_type) {
21152107 // The pointer was generic poison - keep looking.
......@@ -2187,7 +2179,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
21872179}
21882180
21892181/// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value.
2190/// Generic poison causes `error.GenericPoison` to be returned.
21912182fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
21922183 const zcu = sema.pt.zcu;
21932184 assert(inst != .none);
......@@ -2201,7 +2192,6 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
22012192
22022193 assert(val.getVariable(zcu) == null);
22032194 if (val.isPtrRuntimeValue(zcu)) return null;
2204 if (val.isGenericPoison()) return error.GenericPoison;
22052195
22062196 return val;
22072197 } else {
......@@ -2761,8 +2751,7 @@ fn zirTupleDecl(
27612751 .elem_index = @intCast(field_index),
27622752 } });
27632753
2764 const uncoerced_field_ty = try sema.resolveInst(zir_field_ty);
2765 const field_type = try sema.analyzeAsType(block, type_src, uncoerced_field_ty);
2754 const field_type = try sema.resolveType(block, type_src, zir_field_ty);
27662755 try sema.validateTupleFieldType(block, field_type, type_src);
27672756
27682757 field_ty.* = field_type.toIntern();
......@@ -4555,10 +4544,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
45554544 const src = block.nodeOffset(pl_node.src_node);
45564545 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;
45574546 const uncoerced_val = try sema.resolveInst(extra.rhs);
4558 const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, extra.lhs) catch |err| switch (err) {
4559 error.GenericPoison => return uncoerced_val,
4560 else => |e| return e,
4561 };
4547 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val;
45624548 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
45634549 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
45644550 const elem_ty = ptr_ty.childType(zcu);
......@@ -4606,10 +4592,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
46064592 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
46074593 const src = block.nodeOffset(un_node.src_node);
46084594
4609 const operand_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {
4610 error.GenericPoison => return .generic_poison_type,
4611 else => |e| return e,
4612 };
4595 const operand_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type;
46134596
46144597 const payload_ty = if (is_ref) ty: {
46154598 if (!operand_ty.isSinglePointer(zcu)) {
......@@ -4656,15 +4639,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
46564639 const src = block.tokenOffset(un_tok.src_tok);
46574640 // In case of GenericPoison, we don't actually have a type, so this will be
46584641 // treated as an untyped address-of operator.
4659 const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) {
4660 error.GenericPoison => return,
4661 else => |e| return e,
4662 };
4663 const ty_operand = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
4664 error.GenericPoison => return,
4665 else => |e| return e,
4666 };
4667 if (ty_operand.isGenericPoison()) return;
4642 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
46684643 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
46694644 return sema.failWithOwnedErrorMsg(block, msg: {
46704645 const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(pt)});
......@@ -4696,10 +4671,7 @@ fn zirValidateArrayInitRefTy(
46964671 const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
46974672 const src = block.nodeOffset(pl_node.src_node);
46984673 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;
4699 const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, extra.ptr_ty) catch |err| switch (err) {
4700 error.GenericPoison => return .generic_poison_type,
4701 else => |e| return e,
4702 };
4674 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.ptr_ty) orelse return .generic_poison_type;
47034675 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
47044676 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
47054677 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) {
......@@ -4740,11 +4712,8 @@ fn zirValidateArrayInitTy(
47404712 const src = block.nodeOffset(inst_data.src_node);
47414713 const ty_src: LazySrcLoc = if (is_result_ty) src else block.src(.{ .node_offset_init_ty = inst_data.src_node });
47424714 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
4743 const ty = sema.resolveType(block, ty_src, extra.ty) catch |err| switch (err) {
4744 // It's okay for the type to be unknown: this will result in an anonymous array init.
4745 error.GenericPoison => return,
4746 else => |e| return e,
4747 };
4715 // It's okay for the type to be poison: this will result in an anonymous array init.
4716 const ty = try sema.resolveTypeOrPoison(block, ty_src, extra.ty) orelse return;
47484717 const arr_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;
47494718 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);
47504719}
......@@ -4803,11 +4772,8 @@ fn zirValidateStructInitTy(
48034772 const zcu = pt.zcu;
48044773 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
48054774 const src = block.nodeOffset(inst_data.src_node);
4806 const ty = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {
4807 // It's okay for the type to be unknown: this will result in an anonymous struct init.
4808 error.GenericPoison => return,
4809 else => |e| return e,
4810 };
4775 // It's okay for the type to be poison: this will result in an anonymous struct init.
4776 const ty = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return;
48114777 const struct_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;
48124778
48134779 switch (struct_ty.zigTypeTag(zcu)) {
......@@ -7043,7 +7009,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
70437009 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
70447010 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
70457011 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
7046 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
7012 error.ComptimeReturn, error.ComptimeBreak => unreachable,
70477013 error.OutOfMemory => |e| return e,
70487014 };
70497015
......@@ -7668,6 +7634,11 @@ fn analyzeCall(
76687634 }
76697635 }
76707636
7637 // This is whether we already know this to be an inline call.
7638 // If so, then comptime-known arguments are propagated when evaluating generic parameter/return types.
7639 // We might still learn that this call is inline *after* evaluating the generic return type.
7640 const early_known_inline = inline_requested or block.isComptime();
7641
76717642 // These values are undefined if `func_val == null`.
76727643 const fn_nav: InternPool.Nav, const fn_zir: Zir, const fn_tracked_inst: InternPool.TrackedInst.Index, const fn_zir_inst: Zir.Inst.Index, const fn_zir_info: Zir.FnInfo = if (func_val) |f| b: {
76737644 const info = ip.indexToKey(f.toIntern()).func;
......@@ -7746,7 +7717,7 @@ fn analyzeCall(
77467717
77477718 const extra = sema.code.extraData(Zir.Inst.Param, param_inst.data.pl_tok.payload_index);
77487719 const param_src = generic_block.tokenOffset(param_inst.data.pl_tok.src_tok);
7749 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
7720 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);
77507721
77517722 generic_block.comptime_reason = .{ .reason = .{
77527723 .r = .{ .simple = .function_parameters },
......@@ -7777,8 +7748,10 @@ fn analyzeCall(
77777748 const param_inst_idx = fn_zir_info.param_body[arg_idx];
77787749 const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false;
77797750 const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt);
7780 if (param_is_comptime) {
7781 if (!try sema.isComptimeKnown(arg.*)) {
7751 // We allow comptime-known arguments to propagate to generic types not only for comptime
7752 // parameters, but if the call is known to be inline.
7753 if (param_is_comptime or early_known_inline) {
7754 if (param_is_comptime and !try sema.isComptimeKnown(arg.*)) {
77827755 assert(!declared_comptime); // `analyzeArg` handles this
77837756 const arg_src = args_info.argSrc(block, arg_idx);
77847757 const param_ty_src: LazySrcLoc = .{
......@@ -8313,14 +8286,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
83138286 const pt = sema.pt;
83148287 const zcu = pt.zcu;
83158288 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
8316 const maybe_wrapped_indexable_ty = sema.resolveType(block, LazySrcLoc.unneeded, bin.lhs) catch |err| switch (err) {
8317 // Since this is a ZIR instruction that returns a type, encountering
8318 // generic poison should not result in a failed compilation, but the
8319 // generic poison type. This prevents unnecessary failures when
8320 // constructing types at compile-time.
8321 error.GenericPoison => return .generic_poison_type,
8322 else => |e| return e,
8323 };
8289 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type;
83248290 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu);
83258291 try indexable_ty.resolveFields(pt);
83268292 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction
......@@ -8337,10 +8303,7 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
83378303 const pt = sema.pt;
83388304 const zcu = pt.zcu;
83398305 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
8340 const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, un_node.operand) catch |err| switch (err) {
8341 error.GenericPoison => return .generic_poison_type,
8342 else => |e| return e,
8343 };
8306 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
83448307 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
83458308 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
83468309 const elem_ty = ptr_ty.childType(zcu);
......@@ -8357,10 +8320,7 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
83578320 const zcu = pt.zcu;
83588321 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
83598322 const src = block.nodeOffset(un_node.src_node);
8360 const ptr_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {
8361 error.GenericPoison => return .generic_poison_type,
8362 else => |e| return e,
8363 };
8323 const ptr_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type;
83648324 try sema.checkMemOperand(block, src, ptr_ty);
83658325 const elem_ty = switch (ptr_ty.ptrSize(zcu)) {
83668326 .slice, .many, .c => ptr_ty.childType(zcu),
......@@ -8373,14 +8333,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
83738333 const pt = sema.pt;
83748334 const zcu = pt.zcu;
83758335 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
8376 const vec_ty = sema.resolveType(block, LazySrcLoc.unneeded, un_node.operand) catch |err| switch (err) {
8377 // Since this is a ZIR instruction that returns a type, encountering
8378 // generic poison should not result in a failed compilation, but the
8379 // generic poison type. This prevents unnecessary failures when
8380 // constructing types at compile-time.
8381 error.GenericPoison => return .generic_poison_type,
8382 else => |e| return e,
8383 };
8336 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
83848337 switch (vec_ty.zigTypeTag(zcu)) {
83858338 .array, .vector => {},
83868339 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{}'", .{vec_ty.fmt(pt)}),
......@@ -8702,10 +8655,7 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b
87028655 .no_embedded_nulls,
87038656 );
87048657
8705 const orig_ty = sema.resolveType(block, src, extra.lhs) catch |err| switch (err) {
8706 error.GenericPoison => Type.generic_poison,
8707 else => |e| return e,
8708 };
8658 const orig_ty: Type = try sema.resolveTypeOrPoison(block, src, extra.lhs) orelse .generic_poison;
87098659
87108660 const uncoerced_result = res: {
87118661 if (orig_ty.toIntern() == .generic_poison_type) {
......@@ -9232,22 +9182,17 @@ fn zirFunc(
92329182
92339183 var extra_index = extra.end;
92349184
9235 const ret_ty: Type = switch (extra.data.ret_body_len) {
9185 const ret_ty: Type = if (extra.data.ret_ty.is_generic)
9186 .generic_poison
9187 else switch (extra.data.ret_ty.body_len) {
92369188 0 => Type.void,
92379189 1 => blk: {
92389190 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
92399191 extra_index += 1;
9240 if (sema.resolveType(block, ret_ty_src, ret_ty_ref)) |ret_ty| {
9241 break :blk ret_ty;
9242 } else |err| switch (err) {
9243 error.GenericPoison => {
9244 break :blk Type.generic_poison;
9245 },
9246 else => |e| return e,
9247 }
9192 break :blk try sema.resolveType(block, ret_ty_src, ret_ty_ref);
92489193 },
92499194 else => blk: {
9250 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_body_len);
9195 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
92519196 extra_index += ret_ty_body.len;
92529197
92539198 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, .{ .simple = .function_ret_ty });
......@@ -9319,32 +9264,16 @@ fn resolveGenericBody(
93199264) !Value {
93209265 assert(body.len != 0);
93219266
9322 const err = err: {
9323 // Make sure any nested param instructions don't clobber our work.
9324 const prev_params = block.params;
9325 const prev_no_partial_func_type = sema.no_partial_func_ty;
9326 block.params = .{};
9327 sema.no_partial_func_ty = true;
9328 defer {
9329 block.params = prev_params;
9330 sema.no_partial_func_ty = prev_no_partial_func_type;
9331 }
9332
9333 const uncasted = sema.resolveInlineBody(block, body, func_inst) catch |err| break :err err;
9334 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
9335 const val = sema.resolveConstDefinedValue(block, src, result, reason) catch |err| break :err err;
9336 return val;
9337 };
9338 switch (err) {
9339 error.GenericPoison => {
9340 if (dest_ty.toIntern() == .type_type) {
9341 return Value.generic_poison_type;
9342 } else {
9343 return Value.generic_poison;
9344 }
9345 },
9346 else => |e| return e,
9267 // Make sure any nested param instructions don't clobber our work.
9268 const prev_params = block.params;
9269 block.params = .{};
9270 defer {
9271 block.params = prev_params;
93479272 }
9273
9274 const uncasted = try sema.resolveInlineBody(block, body, func_inst);
9275 const result = try sema.coerce(block, dest_ty, uncasted, src);
9276 return sema.resolveConstDefinedValue(block, src, result, reason);
93489277}
93499278
93509279/// Given a library name, examines if the library name should end up in
......@@ -9593,8 +9522,6 @@ fn funcCommon(
95939522 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
95949523 const func_src = block.nodeOffset(src_node_offset);
95959524
9596 if (bare_return_type.isGenericPoison() and sema.no_partial_func_ty) return error.GenericPoison;
9597
95989525 const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt);
95999526 var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime;
96009527
......@@ -9611,9 +9538,6 @@ fn funcCommon(
96119538 } });
96129539 const param_ty_comptime = try param_ty.comptimeOnlySema(pt);
96139540 const param_ty_generic = param_ty.isGenericPoison();
9614 if (param_ty_generic and sema.no_partial_func_ty) {
9615 return error.GenericPoison;
9616 }
96179541 if (param_is_comptime or param_ty_comptime or param_ty_generic) {
96189542 is_generic = true;
96199543 }
......@@ -9962,64 +9886,25 @@ fn zirParam(
99629886 const src = block.tokenOffset(inst_data.src_tok);
99639887 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
99649888 const param_name: Zir.NullTerminatedString = extra.data.name;
9965 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
9889 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);
99669890
9967 const param_ty = param_ty: {
9968 const err = err: {
9969 // Make sure any nested param instructions don't clobber our work.
9970 const prev_params = block.params;
9971 const prev_no_partial_func_type = sema.no_partial_func_ty;
9972 block.params = .{};
9973 sema.no_partial_func_ty = true;
9974 defer {
9975 block.params = prev_params;
9976 sema.no_partial_func_ty = prev_no_partial_func_type;
9977 }
9978
9979 if (sema.resolveInlineBody(block, body, inst)) |param_ty_inst| {
9980 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
9981 break :param_ty param_ty;
9982 } else |err| break :err err;
9983 } else |err| break :err err;
9984 };
9985 switch (err) {
9986 error.GenericPoison => {
9987 // The type is not available until the generic instantiation.
9988 // We result the param instruction with a poison value and
9989 // insert an anytype parameter.
9990 try block.params.append(sema.arena, .{
9991 .ty = .generic_poison_type,
9992 .is_comptime = comptime_syntax,
9993 .name = param_name,
9994 });
9995 sema.inst_map.putAssumeCapacity(inst, .generic_poison);
9996 return;
9997 },
9998 else => |e| return e,
9891 const param_ty: Type = if (extra.data.type.is_generic) .generic_poison else ty: {
9892 // Make sure any nested param instructions don't clobber our work.
9893 const prev_params = block.params;
9894 block.params = .{};
9895 defer {
9896 block.params = prev_params;
99999897 }
10000 };
100019898
10002 const is_comptime = try param_ty.comptimeOnlySema(sema.pt) or comptime_syntax;
9899 const param_ty_inst = try sema.resolveInlineBody(block, body, inst);
9900 break :ty try sema.analyzeAsType(block, src, param_ty_inst);
9901 };
100039902
100049903 try block.params.append(sema.arena, .{
100059904 .ty = param_ty.toIntern(),
100069905 .is_comptime = comptime_syntax,
100079906 .name = param_name,
100089907 });
10009
10010 if (is_comptime) {
10011 // If this is a comptime parameter we can add a constant generic_poison
10012 // since this is also a generic parameter.
10013 sema.inst_map.putAssumeCapacity(inst, .generic_poison);
10014 } else {
10015 // Otherwise we need a dummy runtime instruction.
10016 const result_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
10017 try sema.air_instructions.append(sema.gpa, .{
10018 .tag = .alloc,
10019 .data = .{ .ty = param_ty },
10020 });
10021 sema.inst_map.putAssumeCapacity(inst, result_index.toRef());
10022 }
100239908}
100249909
100259910fn zirParamAnytype(
......@@ -10031,14 +9916,11 @@ fn zirParamAnytype(
100319916 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
100329917 const param_name: Zir.NullTerminatedString = inst_data.start;
100339918
10034 // We are evaluating a generic function without any comptime args provided.
10035
100369919 try block.params.append(sema.arena, .{
100379920 .ty = .generic_poison_type,
100389921 .is_comptime = comptime_syntax,
100399922 .name = param_name,
100409923 });
10041 sema.inst_map.putAssumeCapacity(inst, .generic_poison);
100429924}
100439925
100449926fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -10072,24 +9954,11 @@ fn analyzeAs(
100729954 const pt = sema.pt;
100739955 const zcu = pt.zcu;
100749956 const operand = try sema.resolveInst(zir_operand);
10075 const operand_air_inst = sema.resolveInst(zir_dest_type) catch |err| switch (err) {
10076 error.GenericPoison => return operand,
10077 else => |e| return e,
10078 };
10079 const dest_ty = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
10080 error.GenericPoison => return operand,
10081 else => |e| return e,
10082 };
10083 const dest_ty_tag = dest_ty.zigTypeTagOrPoison(zcu) catch |err| switch (err) {
10084 error.GenericPoison => return operand,
10085 };
10086
10087 if (dest_ty_tag == .@"opaque") {
10088 return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)});
10089 }
10090
10091 if (dest_ty_tag == .noreturn) {
10092 return sema.fail(block, src, "cannot cast to noreturn", .{});
9957 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
9958 switch (dest_ty.zigTypeTag(zcu)) {
9959 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)}),
9960 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
9961 else => {},
100939962 }
100949963
100959964 const is_ret = if (zir_dest_type.toIndex()) |ptr_index|
......@@ -15071,9 +14940,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1507114940 // and have a tuple, coerce the tuple immediately.
1507214941 no_coerce: {
1507314942 if (extra.res_ty == .none) break :no_coerce;
15074 const res_ty_inst = try sema.resolveInst(extra.res_ty);
15075 const res_ty = try sema.analyzeAsType(block, src, res_ty_inst);
15076 if (res_ty.isGenericPoison()) break :no_coerce;
14943 const res_ty = try sema.resolveTypeOrPoison(block, src, extra.res_ty) orelse break :no_coerce;
1507714944 if (!uncoerced_lhs_ty.isTuple(zcu)) break :no_coerce;
1507814945 const lhs_len = uncoerced_lhs_ty.structFieldCount(zcu);
1507914946 const lhs_dest_ty = switch (res_ty.zigTypeTag(zcu)) {
......@@ -15313,8 +15180,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1531315180 const rhs = try sema.resolveInst(extra.rhs);
1531415181 const lhs_ty = sema.typeOf(lhs);
1531515182 const rhs_ty = sema.typeOf(rhs);
15316 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
15317 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
15183 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15184 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1531815185 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1531915186 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1532015187
......@@ -15479,8 +15346,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1547915346 const rhs = try sema.resolveInst(extra.rhs);
1548015347 const lhs_ty = sema.typeOf(lhs);
1548115348 const rhs_ty = sema.typeOf(rhs);
15482 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
15483 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
15349 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15350 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1548415351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1548515352 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1548615353
......@@ -15645,8 +15512,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1564515512 const rhs = try sema.resolveInst(extra.rhs);
1564615513 const lhs_ty = sema.typeOf(lhs);
1564715514 const rhs_ty = sema.typeOf(rhs);
15648 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
15649 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
15515 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15516 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1565015517 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1565115518 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1565215519
......@@ -15756,8 +15623,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1575615623 const rhs = try sema.resolveInst(extra.rhs);
1575715624 const lhs_ty = sema.typeOf(lhs);
1575815625 const rhs_ty = sema.typeOf(rhs);
15759 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
15760 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
15626 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15627 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1576115628 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1576215629 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1576315630
......@@ -16000,8 +15867,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1600015867 const rhs = try sema.resolveInst(extra.rhs);
1600115868 const lhs_ty = sema.typeOf(lhs);
1600215869 const rhs_ty = sema.typeOf(rhs);
16003 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
16004 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
15870 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15871 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1600515872 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1600615873 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1600715874
......@@ -16186,8 +16053,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1618616053 const rhs = try sema.resolveInst(extra.rhs);
1618716054 const lhs_ty = sema.typeOf(lhs);
1618816055 const rhs_ty = sema.typeOf(rhs);
16189 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
16190 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
16056 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16057 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1619116058 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1619216059 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1619316060
......@@ -16282,8 +16149,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1628216149 const rhs = try sema.resolveInst(extra.rhs);
1628316150 const lhs_ty = sema.typeOf(lhs);
1628416151 const rhs_ty = sema.typeOf(rhs);
16285 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
16286 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
16152 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16153 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1628716154 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1628816155 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1628916156
......@@ -16623,8 +16490,8 @@ fn analyzeArithmetic(
1662316490 const zcu = pt.zcu;
1662416491 const lhs_ty = sema.typeOf(lhs);
1662516492 const rhs_ty = sema.typeOf(rhs);
16626 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
16627 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
16493 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16494 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
1662816495 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1662916496
1663016497 if (lhs_zig_ty_tag == .pointer) {
......@@ -19028,9 +18895,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1902818895 defer child_block.instructions.deinit(sema.gpa);
1902918896
1903018897 const operand = try sema.resolveInlineBody(&child_block, body, inst);
19031 const operand_ty = sema.typeOf(operand);
19032 if (operand_ty.isGenericPoison()) return error.GenericPoison;
19033 return Air.internedToRef(operand_ty.toIntern());
18898 return Air.internedToRef(sema.typeOf(operand).toIntern());
1903418899}
1903518900
1903618901fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -20100,7 +19965,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2010019965 }
2010119966 return err;
2010219967 };
20103 if (ty.isGenericPoison()) return error.GenericPoison;
19968 assert(!ty.isGenericPoison());
2010419969 break :blk ty;
2010519970 };
2010619971
......@@ -20252,11 +20117,8 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
2025220117 const zcu = pt.zcu;
2025320118 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2025420119 const src = block.nodeOffset(inst_data.src_node);
20255 const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {
20256 // Generic poison means this is an untyped anonymous empty struct/array init
20257 error.GenericPoison => return .empty_tuple,
20258 else => |e| return e,
20259 };
20120 // Generic poison means this is an untyped anonymous empty struct/array init
20121 const ty_operand = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return .empty_tuple;
2026020122 const init_ty = if (is_byref) ty: {
2026120123 const ptr_ty = ty_operand.optEuBaseType(zcu);
2026220124 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
......@@ -20410,12 +20272,9 @@ fn zirStructInit(
2041020272 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
2041120273 const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node;
2041220274 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
20413 const result_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {
20414 error.GenericPoison => {
20415 // The type wasn't actually known, so treat this as an anon struct init.
20416 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
20417 },
20418 else => |e| return e,
20275 const result_ty = try sema.resolveTypeOrPoison(block, src, first_field_type_extra.container_type) orelse {
20276 // The type wasn't actually known, so treat this as an anon struct init.
20277 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
2041920278 };
2042020279 const resolved_ty = result_ty.optEuBaseType(zcu);
2042120280 try resolved_ty.resolveLayout(pt);
......@@ -20932,12 +20791,9 @@ fn zirArrayInit(
2093220791 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
2093320792 assert(args.len >= 2); // array_ty + at least one element
2093420793
20935 const result_ty = sema.resolveType(block, src, args[0]) catch |err| switch (err) {
20936 error.GenericPoison => {
20937 // The type wasn't actually known, so treat this as an anon array init.
20938 return sema.arrayInitAnon(block, src, args[1..], is_ref);
20939 },
20940 else => |e| return e,
20794 const result_ty = try sema.resolveTypeOrPoison(block, src, args[0]) orelse {
20795 // The type wasn't actually known, so treat this as an anon array init.
20796 return sema.arrayInitAnon(block, src, args[1..], is_ref);
2094120797 };
2094220798 const array_ty = result_ty.optEuBaseType(zcu);
2094320799 const is_tuple = array_ty.zigTypeTag(zcu) == .@"struct";
......@@ -21185,14 +21041,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
2118521041 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
2118621042 const ty_src = block.nodeOffset(inst_data.src_node);
2118721043 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });
21188 const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) {
21189 // Since this is a ZIR instruction that returns a type, encountering
21190 // generic poison should not result in a failed compilation, but the
21191 // generic poison type. This prevents unnecessary failures when
21192 // constructing types at compile-time.
21193 error.GenericPoison => return .generic_poison_type,
21194 else => |e| return e,
21195 };
21044 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;
2119621045 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);
2119721046 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
2119821047 const field_name = try ip.getOrPutString(sema.gpa, pt.tid, zir_field_name, .no_embedded_nulls);
......@@ -24068,7 +23917,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
2406823917fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
2406923918 const pt = sema.pt;
2407023919 const zcu = pt.zcu;
24071 switch (try ty.zigTypeTagOrPoison(zcu)) {
23920 switch (ty.zigTypeTag(zcu)) {
2407223921 .comptime_int => return true,
2407323922 .int => return false,
2407423923 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),
......@@ -24083,7 +23932,7 @@ fn checkInvalidPtrIntArithmetic(
2408323932) CompileError!void {
2408423933 const pt = sema.pt;
2408523934 const zcu = pt.zcu;
24086 switch (try ty.zigTypeTagOrPoison(zcu)) {
23935 switch (ty.zigTypeTag(zcu)) {
2408723936 .pointer => switch (ty.ptrSize(zcu)) {
2408823937 .one, .slice => return,
2408923938 .many, .c => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"),
......@@ -24266,7 +24115,7 @@ fn checkAtomicPtrOperand(
2426624115 };
2426724116
2426824117 const ptr_ty = sema.typeOf(ptr);
24269 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(zcu)) {
24118 const ptr_data = switch (ptr_ty.zigTypeTag(zcu)) {
2427024119 .pointer => ptr_ty.ptrInfo(zcu),
2427124120 else => {
2427224121 const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data);
......@@ -24307,11 +24156,11 @@ fn checkIntOrVector(
2430724156 const pt = sema.pt;
2430824157 const zcu = pt.zcu;
2430924158 const operand_ty = sema.typeOf(operand);
24310 switch (try operand_ty.zigTypeTagOrPoison(zcu)) {
24159 switch (operand_ty.zigTypeTag(zcu)) {
2431124160 .int => return operand_ty,
2431224161 .vector => {
2431324162 const elem_ty = operand_ty.childType(zcu);
24314 switch (try elem_ty.zigTypeTagOrPoison(zcu)) {
24163 switch (elem_ty.zigTypeTag(zcu)) {
2431524164 .int => return elem_ty,
2431624165 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
2431724166 elem_ty.fmt(pt),
......@@ -24332,11 +24181,11 @@ fn checkIntOrVectorAllowComptime(
2433224181) CompileError!Type {
2433324182 const pt = sema.pt;
2433424183 const zcu = pt.zcu;
24335 switch (try operand_ty.zigTypeTagOrPoison(zcu)) {
24184 switch (operand_ty.zigTypeTag(zcu)) {
2433624185 .int, .comptime_int => return operand_ty,
2433724186 .vector => {
2433824187 const elem_ty = operand_ty.childType(zcu);
24339 switch (try elem_ty.zigTypeTagOrPoison(zcu)) {
24188 switch (elem_ty.zigTypeTag(zcu)) {
2434024189 .int, .comptime_int => return elem_ty,
2434124190 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
2434224191 elem_ty.fmt(pt),
......@@ -24406,8 +24255,8 @@ fn checkVectorizableBinaryOperands(
2440624255) CompileError!void {
2440724256 const pt = sema.pt;
2440824257 const zcu = pt.zcu;
24409 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);
24410 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);
24258 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
24259 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
2441124260 if (lhs_zig_ty_tag != .vector and rhs_zig_ty_tag != .vector) return;
2441224261
2441324262 const lhs_is_vector = switch (lhs_zig_ty_tag) {
......@@ -24987,7 +24836,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2498724836 const pred_uncoerced = try sema.resolveInst(extra.pred);
2498824837 const pred_ty = sema.typeOf(pred_uncoerced);
2498924838
24990 const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison(zcu)) {
24839 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {
2499124840 .vector, .array => pred_ty.arrayLen(zcu),
2499224841 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),
2499324842 };
......@@ -26306,7 +26155,9 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2630626155 break :cc .auto;
2630726156 };
2630826157
26309 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
26158 const ret_ty: Type = if (extra.data.bits.ret_ty_is_generic)
26159 .generic_poison
26160 else if (extra.data.bits.has_ret_ty_body) blk: {
2631026161 const body_len = sema.code.extra[extra_index];
2631126162 extra_index += 1;
2631226163 const body = sema.code.bodySlice(extra_index, body_len);
......@@ -26318,14 +26169,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2631826169 } else if (extra.data.bits.has_ret_ty_ref) blk: {
2631926170 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
2632026171 extra_index += 1;
26321 const ret_ty_air_ref = sema.resolveInst(ret_ty_ref) catch |err| switch (err) {
26322 error.GenericPoison => break :blk Type.generic_poison,
26323 else => |e| return e,
26324 };
26325 const ret_ty_val = sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{ .simple = .function_ret_ty }) catch |err| switch (err) {
26326 error.GenericPoison => break :blk Type.generic_poison,
26327 else => |e| return e,
26328 };
26172 const ret_ty_air_ref = try sema.resolveInst(ret_ty_ref);
26173 const ret_ty_val = try sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{ .simple = .function_ret_ty });
2632926174 break :blk ret_ty_val.toType();
2633026175 } else Type.void;
2633126176
......@@ -27625,7 +27470,7 @@ fn fieldVal(
2762527470 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;
2762627471 const child_type = val.toType();
2762727472
27628 switch (try child_type.zigTypeTagOrPoison(zcu)) {
27473 switch (child_type.zigTypeTag(zcu)) {
2762927474 .error_set => {
2763027475 switch (ip.indexToKey(child_type.toIntern())) {
2763127476 .error_set_type => |error_set_type| blk: {
......@@ -35180,7 +35025,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
3518035025 if (struct_type.layout == .@"packed") {
3518135026 sema.backingIntType(struct_type) catch |err| switch (err) {
3518235027 error.OutOfMemory, error.AnalysisFail => |e| return e,
35183 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35028 error.ComptimeBreak, error.ComptimeReturn => unreachable,
3518435029 };
3518535030 return;
3518635031 }
......@@ -35688,7 +35533,7 @@ pub fn resolveStructFieldTypes(
3568835533
3568935534 sema.structFields(struct_type) catch |err| switch (err) {
3569035535 error.AnalysisFail, error.OutOfMemory => |e| return e,
35691 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35536 error.ComptimeBreak, error.ComptimeReturn => unreachable,
3569235537 };
3569335538}
3569435539
......@@ -35717,7 +35562,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
3571735562
3571835563 sema.structFieldInits(struct_type) catch |err| switch (err) {
3571935564 error.AnalysisFail, error.OutOfMemory => |e| return e,
35720 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35565 error.ComptimeBreak, error.ComptimeReturn => unreachable,
3572135566 };
3572235567 struct_type.setHaveFieldInits(ip);
3572335568}
......@@ -35751,7 +35596,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
3575135596 errdefer union_type.setStatus(ip, .none);
3575235597 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {
3575335598 error.AnalysisFail, error.OutOfMemory => |e| return e,
35754 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35599 error.ComptimeBreak, error.ComptimeReturn => unreachable,
3575535600 };
3575635601 union_type.setStatus(ip, .have_field_types);
3575735602}
......@@ -36078,9 +35923,6 @@ fn structFields(
3607835923 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
3607935924 break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref);
3608035925 };
36081 if (field_ty.isGenericPoison()) {
36082 return error.GenericPoison;
36083 }
3608435926
3608535927 struct_type.field_types.get(ip)[field_i] = field_ty.toIntern();
3608635928
......@@ -36523,10 +36365,6 @@ fn unionFields(
3652336365 else
3652436366 try sema.resolveType(&block_scope, type_src, field_type_ref);
3652536367
36526 if (field_ty.isGenericPoison()) {
36527 return error.GenericPoison;
36528 }
36529
3653036368 if (explicit_tags_seen.len > 0) {
3653136369 const tag_ty = union_type.tagTypeUnordered(ip);
3653236370 const tag_info = ip.loadEnumType(tag_ty);
......@@ -36779,7 +36617,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3677936617 .null_type => Value.null,
3678036618 .undefined_type => Value.undef,
3678136619 .optional_noreturn_type => try pt.nullValue(ty),
36782 .generic_poison_type => error.GenericPoison,
36620 .generic_poison_type => unreachable,
3678336621 .empty_tuple_type => Value.empty_tuple,
3678436622 // values, not types
3678536623 .undef,
......@@ -36797,7 +36635,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3679736635 .bool_true,
3679836636 .bool_false,
3679936637 .empty_tuple,
36800 .generic_poison,
3680136638 // invalid
3680236639 .none,
3680336640 => unreachable,
......@@ -38095,7 +37932,6 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3809537932 ) catch |err| switch (err) {
3809637933 error.OutOfMemory => |e| return e,
3809737934 error.AnalysisFail => unreachable,
38098 error.GenericPoison => unreachable,
3809937935 error.ComptimeReturn => unreachable,
3810037936 error.ComptimeBreak => unreachable,
3810137937 };
......@@ -38410,7 +38246,6 @@ pub fn resolveDeclaredEnum(
3841038246 zir,
3841138247 body_end,
3841238248 ) catch |err| switch (err) {
38413 error.GenericPoison => unreachable,
3841438249 error.ComptimeBreak => unreachable,
3841538250 error.ComptimeReturn => unreachable,
3841638251 error.OutOfMemory => |e| return e,
src/Type.zig+5-8
......@@ -22,11 +22,7 @@ const SemaError = Zcu.SemaError;
2222ip_index: InternPool.Index,
2323
2424pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId {
25 return ty.zigTypeTagOrPoison(zcu) catch unreachable;
26}
27
28pub fn zigTypeTagOrPoison(ty: Type, zcu: *const Zcu) error{GenericPoison}!std.builtin.TypeId {
29 return zcu.intern_pool.zigTypeTagOrPoison(ty.toIntern());
25 return zcu.intern_pool.zigTypeTag(ty.toIntern());
3026}
3127
3228pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId {
......@@ -2503,14 +2499,16 @@ pub fn fnCallingConvention(ty: Type, zcu: *const Zcu) std.builtin.CallingConvent
25032499}
25042500
25052501pub fn isValidParamType(self: Type, zcu: *const Zcu) bool {
2506 return switch (self.zigTypeTagOrPoison(zcu) catch return true) {
2502 if (self.toIntern() == .generic_poison_type) return true;
2503 return switch (self.zigTypeTag(zcu)) {
25072504 .@"opaque", .noreturn => false,
25082505 else => true,
25092506 };
25102507}
25112508
25122509pub fn isValidReturnType(self: Type, zcu: *const Zcu) bool {
2513 return switch (self.zigTypeTagOrPoison(zcu) catch return true) {
2510 if (self.toIntern() == .generic_poison_type) return true;
2511 return switch (self.zigTypeTag(zcu)) {
25142512 .@"opaque" => false,
25152513 else => true,
25162514 };
......@@ -3784,7 +3782,6 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
37843782 .bool_true => unreachable,
37853783 .bool_false => unreachable,
37863784 .empty_tuple => unreachable,
3787 .generic_poison => unreachable,
37883785
37893786 else => switch (ty_ip.unwrap(ip).getTag(ip)) {
37903787 .type_struct,
src/Value.zig-5
......@@ -3673,10 +3673,6 @@ pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 {
36733673 return first_byte;
36743674}
36753675
3676pub fn isGenericPoison(val: Value) bool {
3677 return val.toIntern() == .generic_poison;
3678}
3679
36803676pub fn typeOf(val: Value, zcu: *const Zcu) Type {
36813677 return Type.fromInterned(zcu.intern_pool.typeOf(val.toIntern()));
36823678}
......@@ -3709,7 +3705,6 @@ pub const @"false": Value = .{ .ip_index = .bool_false };
37093705pub const @"true": Value = .{ .ip_index = .bool_true };
37103706pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };
37113707
3712pub const generic_poison: Value = .{ .ip_index = .generic_poison };
37133708pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
37143709pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
37153710
src/Zcu.zig-4
......@@ -2404,10 +2404,6 @@ pub const CompileError = error{
24042404 OutOfMemory,
24052405 /// When this is returned, the compile error for the failure has already been recorded.
24062406 AnalysisFail,
2407 /// A Type or Value was needed to be used during semantic analysis, but it was not available
2408 /// because the function is generic. This is only seen when analyzing the body of a param
2409 /// instruction.
2410 GenericPoison,
24112407 /// In a comptime scope, a return instruction was encountered. This error is only seen when
24122408 /// doing a comptime function call.
24132409 ComptimeReturn,
src/Zcu/PerThread.zig-10
......@@ -627,7 +627,6 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
627627 // TODO: same as for `ensureComptimeUnitUpToDate` etc
628628 return error.OutOfMemory;
629629 },
630 error.GenericPoison => unreachable,
631630 error.ComptimeReturn => unreachable,
632631 error.ComptimeBreak => unreachable,
633632 };
......@@ -781,7 +780,6 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
781780 // for reporting OOM errors without allocating.
782781 return error.OutOfMemory;
783782 },
784 error.GenericPoison => unreachable,
785783 error.ComptimeReturn => unreachable,
786784 error.ComptimeBreak => unreachable,
787785 };
......@@ -967,7 +965,6 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
967965 // for reporting OOM errors without allocating.
968966 return error.OutOfMemory;
969967 },
970 error.GenericPoison => unreachable,
971968 error.ComptimeReturn => unreachable,
972969 error.ComptimeBreak => unreachable,
973970 };
......@@ -1168,7 +1165,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
11681165 };
11691166
11701167 switch (nav_val.toIntern()) {
1171 .generic_poison => unreachable, // assertion failure
11721168 .unreachable_value => unreachable, // assertion failure
11731169 else => {},
11741170 }
......@@ -1347,7 +1343,6 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
13471343 // for reporting OOM errors without allocating.
13481344 return error.OutOfMemory;
13491345 },
1350 error.GenericPoison => unreachable,
13511346 error.ComptimeReturn => unreachable,
13521347 error.ComptimeBreak => unreachable,
13531348 };
......@@ -2665,7 +2660,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
26652660 runtime_param_index += 1;
26662661
26672662 const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) {
2668 error.GenericPoison => unreachable,
26692663 error.ComptimeReturn => unreachable,
26702664 error.ComptimeBreak => unreachable,
26712665 else => |e| return e,
......@@ -2698,7 +2692,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
26982692 inner_block.error_return_trace_index = error_return_trace_index;
26992693
27002694 sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
2701 error.GenericPoison => unreachable,
27022695 error.ComptimeReturn => unreachable,
27032696 else => |e| return e,
27042697 };
......@@ -2720,7 +2713,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27202713 !sema.fn_ret_ty.isError(zcu))
27212714 {
27222715 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
2723 error.GenericPoison => unreachable,
27242716 error.ComptimeReturn => unreachable,
27252717 error.ComptimeBreak => unreachable,
27262718 else => |e| return e,
......@@ -2744,7 +2736,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27442736 .base_node_inst = inner_block.src_base_inst,
27452737 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),
27462738 }, ies) catch |err| switch (err) {
2747 error.GenericPoison => unreachable,
27482739 error.ComptimeReturn => unreachable,
27492740 error.ComptimeBreak => unreachable,
27502741 else => |e| return e,
......@@ -2763,7 +2754,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27632754 // TODO: this can go away once we fix backends having to resolve `StackTrace`.
27642755 // The codegen timing guarantees that the parameter types will be populated.
27652756 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(0)) catch |err| switch (err) {
2766 error.GenericPoison => unreachable,
27672757 error.ComptimeReturn => unreachable,
27682758 error.ComptimeBreak => unreachable,
27692759 else => |e| return e,
src/arch/wasm/CodeGen.zig-1
......@@ -3170,7 +3170,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {
31703170 .null,
31713171 .empty_tuple,
31723172 .@"unreachable",
3173 .generic_poison,
31743173 => unreachable, // non-runtime values
31753174 .false, .true => return .{ .imm32 = switch (simple_value) {
31763175 .false => 0,
src/codegen.zig-1
......@@ -229,7 +229,6 @@ pub fn generateSymbol(
229229 .void => unreachable, // non-runtime value
230230 .null => unreachable, // non-runtime value
231231 .@"unreachable" => unreachable, // non-runtime value
232 .generic_poison => unreachable, // non-runtime value
233232 .empty_tuple => return,
234233 .false, .true => try code.append(gpa, switch (simple_value) {
235234 .false => 0,
src/codegen/c.zig-1
......@@ -968,7 +968,6 @@ pub const DeclGen = struct {
968968 .null => unreachable,
969969 .empty_tuple => unreachable,
970970 .@"unreachable" => unreachable,
971 .generic_poison => unreachable,
972971
973972 .false => try writer.writeAll("false"),
974973 .true => try writer.writeAll("true"),
src/codegen/c/Type.zig-1
......@@ -1451,7 +1451,6 @@ pub const Pool = struct {
14511451 .bool_true,
14521452 .bool_false,
14531453 .empty_tuple,
1454 .generic_poison,
14551454 .none,
14561455 => unreachable,
14571456
src/codegen/llvm.zig-2
......@@ -3372,7 +3372,6 @@ pub const Object = struct {
33723372 .bool_true,
33733373 .bool_false,
33743374 .empty_tuple,
3375 .generic_poison,
33763375 .none,
33773376 => unreachable,
33783377 else => switch (ip.indexToKey(t.toIntern())) {
......@@ -3923,7 +3922,6 @@ pub const Object = struct {
39233922 .null => unreachable, // non-runtime value
39243923 .empty_tuple => unreachable, // non-runtime value
39253924 .@"unreachable" => unreachable, // non-runtime value
3926 .generic_poison => unreachable, // non-runtime value
39273925
39283926 .false => .false,
39293927 .true => .true,
src/codegen/spirv.zig-1
......@@ -941,7 +941,6 @@ const NavGen = struct {
941941 .null,
942942 .empty_tuple,
943943 .@"unreachable",
944 .generic_poison,
945944 => unreachable, // non-runtime values
946945
947946 .false, .true => break :cache try self.constBool(val.toBool(), repr),
src/print_value.zig-1
......@@ -84,7 +84,6 @@ pub fn print(
8484 .simple_value => |simple_value| switch (simple_value) {
8585 .void => try writer.writeAll("{}"),
8686 .empty_tuple => try writer.writeAll(".{}"),
87 .generic_poison => try writer.writeAll("(generic poison)"),
8887 else => try writer.writeAll(@tagName(simple_value)),
8988 },
9089 .variable => try writer.writeAll("(variable)"),
src/print_zir.zig+9-3
......@@ -948,11 +948,13 @@ const Writer = struct {
948948 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
949949 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
950950 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
951 const body = self.code.bodySlice(extra.end, extra.data.body_len);
951 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
952952 try stream.print("\"{}\", ", .{
953953 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
954954 });
955955
956 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
957
956958 try self.writeBracedBody(stream, body);
957959 try stream.writeAll(") ");
958960 try self.writeSrcTok(stream, inst_data.src_tok);
......@@ -2283,7 +2285,7 @@ const Writer = struct {
22832285 var ret_ty_ref: Zir.Inst.Ref = .none;
22842286 var ret_ty_body: []const Zir.Inst.Index = &.{};
22852287
2286 switch (extra.data.ret_body_len) {
2288 switch (extra.data.ret_ty.body_len) {
22872289 0 => {
22882290 ret_ty_ref = .void_type;
22892291 },
......@@ -2292,7 +2294,7 @@ const Writer = struct {
22922294 extra_index += 1;
22932295 },
22942296 else => {
2295 ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_body_len);
2297 ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
22962298 extra_index += ret_ty_body.len;
22972299 },
22982300 }
......@@ -2314,6 +2316,7 @@ const Writer = struct {
23142316 &.{},
23152317 ret_ty_ref,
23162318 ret_ty_body,
2319 extra.data.ret_ty.is_generic,
23172320
23182321 body,
23192322 inst_data.src_node,
......@@ -2373,6 +2376,7 @@ const Writer = struct {
23732376 cc_body,
23742377 ret_ty_ref,
23752378 ret_ty_body,
2379 extra.data.bits.ret_ty_is_generic,
23762380 body,
23772381 inst_data.src_node,
23782382 src_locs,
......@@ -2532,12 +2536,14 @@ const Writer = struct {
25322536 cc_body: []const Zir.Inst.Index,
25332537 ret_ty_ref: Zir.Inst.Ref,
25342538 ret_ty_body: []const Zir.Inst.Index,
2539 ret_ty_is_generic: bool,
25352540 body: []const Zir.Inst.Index,
25362541 src_node: i32,
25372542 src_locs: Zir.Inst.Func.SrcLocs,
25382543 noalias_bits: u32,
25392544 ) !void {
25402545 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2546 if (ret_ty_is_generic) try stream.writeAll("[generic] ");
25412547 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
25422548 try self.writeFlag(stream, "vargs, ", var_args);
25432549 try self.writeFlag(stream, "inferror, ", inferred_error_set);
test/behavior/fn.zig+39
......@@ -672,3 +672,42 @@ test "function parameter self equality" {
672672 try expect(!S.greaterThan(42));
673673 try expect(S.greaterThanOrEqual(42));
674674}
675
676test "inline call propagates comptime-known argument to generic parameter and return types" {
677 const S = struct {
678 inline fn f(x: bool, y: if (x) u8 else u16) if (x) bool else u32 {
679 if (x) {
680 comptime assert(@TypeOf(y) == u8);
681 return y == 0;
682 } else {
683 comptime assert(@TypeOf(y) == u16);
684 return y * 10;
685 }
686 }
687 fn g(x: bool, y: if (x) u8 else u16) if (x) bool else u32 {
688 if (x) {
689 comptime assert(@TypeOf(y) == u8);
690 return y == 0;
691 } else {
692 comptime assert(@TypeOf(y) == u16);
693 return y * 10;
694 }
695 }
696 };
697
698 const a0 = S.f(true, 200); // false
699 const a1 = S.f(false, 1234); // 12340
700
701 const b0 = @call(.always_inline, S.g, .{ true, 200 }); // false
702 const b1 = @call(.always_inline, S.g, .{ false, 1234 }); // 12340
703
704 comptime assert(@TypeOf(a0) == bool);
705 comptime assert(@TypeOf(b0) == bool);
706 try expect(a0 == false);
707 try expect(b0 == false);
708
709 comptime assert(@TypeOf(a1) == u32);
710 comptime assert(@TypeOf(b1) == u32);
711 try expect(a1 == 12340);
712 try expect(b1 == 12340);
713}
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1
......@@ -15,6 +15,6 @@ pub export fn entry() void {
1515// error
1616//
1717// :7:25: error: unable to resolve comptime value
18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_166.C' must be comptime-known
18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_165.C' must be comptime-known
1919// :4:16: note: struct requires comptime because of this field
2020// :4:16: note: types are not available at runtime
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-3
......@@ -13,10 +13,8 @@ pub export fn entry2() void {
1313}
1414
1515// error
16// backend=stage2
17// target=native
1816//
1917// :3:6: error: no field or member function named 'copy' in '[]const u8'
2018// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
21// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_170'
19// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_169'
2220// :12:6: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig+1-1
......@@ -6,6 +6,6 @@ export fn foo() void {
66
77// error
88//
9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_159'
9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_158'
1010// :3:16: note: struct declared here
1111// :1:11: note: struct declared here
test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig+1-1
......@@ -8,7 +8,7 @@ export fn entry() void {
88fn makeLlamas(count: usize) [count]u8 {}
99
1010// error
11// target=native
1211//
1312// :8:30: error: unable to resolve comptime value
1413// :8:30: note: array length must be comptime-known
14// :2:31: note: called from here