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 {...@@ -107,6 +107,8 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
107 Zir.Inst.SwitchBlock.Bits,107 Zir.Inst.SwitchBlock.Bits,
108 Zir.Inst.SwitchBlockErrUnion.Bits,108 Zir.Inst.SwitchBlockErrUnion.Bits,
109 Zir.Inst.FuncFancy.Bits,109 Zir.Inst.FuncFancy.Bits,
110 Zir.Inst.Param.Type,
111 Zir.Inst.Func.RetTy,
110 => @bitCast(@field(extra, field.name)),112 => @bitCast(@field(extra, field.name)),
111113
112 else => @compileError("bad field type"),114 else => @compileError("bad field type"),
...@@ -1384,7 +1386,7 @@ fn fnProtoExprInner(...@@ -1384,7 +1386,7 @@ fn fnProtoExprInner(
1384 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;1386 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
1385 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous1387 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous
1386 // arguments (we haven't set up scopes here).1388 // 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);
1388 assert(param_inst_expected == param_inst);1390 assert(param_inst_expected == param_inst);
1389 }1391 }
1390 }1392 }
...@@ -1416,6 +1418,7 @@ fn fnProtoExprInner(...@@ -1416,6 +1418,7 @@ fn fnProtoExprInner(
14161418
1417 .ret_param_refs = &.{},1419 .ret_param_refs = &.{},
1418 .param_insts = &.{},1420 .param_insts = &.{},
1421 .ret_ty_is_generic = false,
14191422
1420 .param_block = block_inst,1423 .param_block = block_inst,
1421 .body_gz = null,1424 .body_gz = null,
...@@ -4336,6 +4339,9 @@ fn fnDeclInner(...@@ -4336,6 +4339,9 @@ fn fnDeclInner(
4336 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.4339 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
4337 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);4340 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
4339 var noalias_bits: u32 = 0;4345 var noalias_bits: u32 = 0;
4340 var params_scope = scope;4346 var params_scope = scope;
4341 const is_var_args = is_var_args: {4347 const is_var_args = is_var_args: {
...@@ -4409,16 +4415,18 @@ fn fnDeclInner(...@@ -4409,16 +4415,18 @@ fn fnDeclInner(
4409 } else param: {4415 } else param: {
4410 const param_type_node = param.type_expr;4416 const param_type_node = param.type_expr;
4411 assert(param_type_node != 0);4417 assert(param_type_node != 0);
4418 any_param_used = false; // we will check this later
4412 var param_gz = decl_gz.makeSubBlock(scope);4419 var param_gz = decl_gz.makeSubBlock(scope);
4413 defer param_gz.unstack();4420 defer param_gz.unstack();
4414 const param_type = try fullBodyExpr(&param_gz, params_scope, coerced_type_ri, param_type_node, .normal);4421 const param_type = try fullBodyExpr(&param_gz, params_scope, coerced_type_ri, param_type_node, .normal);
4415 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);4422 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
4416 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);4423 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
4424 const param_type_is_generic = any_param_used;
44174425
4418 const main_tokens = tree.nodes.items(.main_token);4426 const main_tokens = tree.nodes.items(.main_token);
4419 const name_token = param.name_token orelse main_tokens[param_type_node];4427 const name_token = param.name_token orelse main_tokens[param_type_node];
4420 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;4428 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);
4422 assert(param_inst_expected == param_inst);4430 assert(param_inst_expected == param_inst);
4423 break :param param_inst.toRef();4431 break :param param_inst.toRef();
4424 };4432 };
...@@ -4433,6 +4441,7 @@ fn fnDeclInner(...@@ -4433,6 +4441,7 @@ fn fnDeclInner(
4433 .inst = param_inst,4441 .inst = param_inst,
4434 .token_src = param.name_token.?,4442 .token_src = param.name_token.?,
4435 .id_cat = .@"function parameter",4443 .id_cat = .@"function parameter",
4444 .is_used_or_discarded = &any_param_used,
4436 };4445 };
4437 params_scope = &sub_scope.base;4446 params_scope = &sub_scope.base;
4438 try param_insts.append(astgen.arena, param_inst.toIndex().?);4447 try param_insts.append(astgen.arena, param_inst.toIndex().?);
...@@ -4446,6 +4455,7 @@ fn fnDeclInner(...@@ -4446,6 +4455,7 @@ fn fnDeclInner(
44464455
4447 var ret_gz = decl_gz.makeSubBlock(params_scope);4456 var ret_gz = decl_gz.makeSubBlock(params_scope);
4448 defer ret_gz.unstack();4457 defer ret_gz.unstack();
4458 any_param_used = false; // we will check this later
4449 const ret_ref: Zir.Inst.Ref = inst: {4459 const ret_ref: Zir.Inst.Ref = inst: {
4450 // Parameters are in scope for the return type, so we use `params_scope` here.4460 // Parameters are in scope for the return type, so we use `params_scope` here.
4451 // The calling convention will not have parameters in scope, so we'll just use `scope`.4461 // The calling convention will not have parameters in scope, so we'll just use `scope`.
...@@ -4459,6 +4469,7 @@ fn fnDeclInner(...@@ -4459,6 +4469,7 @@ fn fnDeclInner(
4459 break :inst inst;4469 break :inst inst;
4460 };4470 };
4461 const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items);4471 const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items);
4472 const ret_ty_is_generic = any_param_used;
44624473
4463 // We're jumping back in source, so restore the cursor.4474 // We're jumping back in source, so restore the cursor.
4464 astgen.restoreSourceCursor(saved_cursor);4475 astgen.restoreSourceCursor(saved_cursor);
...@@ -4556,6 +4567,7 @@ fn fnDeclInner(...@@ -4556,6 +4567,7 @@ fn fnDeclInner(
4556 .ret_ref = ret_ref,4567 .ret_ref = ret_ref,
4557 .ret_gz = &ret_gz,4568 .ret_gz = &ret_gz,
4558 .ret_param_refs = ret_body_param_refs,4569 .ret_param_refs = ret_body_param_refs,
4570 .ret_ty_is_generic = ret_ty_is_generic,
4559 .lbrace_line = lbrace_line,4571 .lbrace_line = lbrace_line,
4560 .lbrace_column = lbrace_column,4572 .lbrace_column = lbrace_column,
4561 .param_block = decl_inst,4573 .param_block = decl_inst,
...@@ -5028,6 +5040,7 @@ fn testDecl(...@@ -5028,6 +5040,7 @@ fn testDecl(
50285040
5029 .ret_param_refs = &.{},5041 .ret_param_refs = &.{},
5030 .param_insts = &.{},5042 .param_insts = &.{},
5043 .ret_ty_is_generic = false,
50315044
5032 .lbrace_line = lbrace_line,5045 .lbrace_line = lbrace_line,
5033 .lbrace_column = lbrace_column,5046 .lbrace_column = lbrace_column,
...@@ -8546,6 +8559,8 @@ fn localVarRef(...@@ -8546,6 +8559,8 @@ fn localVarRef(
8546 local_val.used = ident_token;8559 local_val.used = ident_token;
8547 }8560 }
85488561
8562 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
8563
8549 const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure(8564 const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure(
8550 gz,8565 gz,
8551 ident,8566 ident,
...@@ -11876,6 +11891,7 @@ const Scope = struct {...@@ -11876,6 +11891,7 @@ const Scope = struct {
11876 /// Track the identifier where it is discarded, like this `_ = foo;`.11891 /// Track the identifier where it is discarded, like this `_ = foo;`.
11877 /// 0 means never discarded.11892 /// 0 means never discarded.
11878 discarded: Ast.TokenIndex = 0,11893 discarded: Ast.TokenIndex = 0,
11894 is_used_or_discarded: ?*bool = null,
11879 /// String table index.11895 /// String table index.
11880 name: Zir.NullTerminatedString,11896 name: Zir.NullTerminatedString,
11881 id_cat: IdCat,11897 id_cat: IdCat,
...@@ -12223,6 +12239,7 @@ const GenZir = struct {...@@ -12223,6 +12239,7 @@ const GenZir = struct {
1222312239
12224 ret_param_refs: []Zir.Inst.Index,12240 ret_param_refs: []Zir.Inst.Index,
12225 param_insts: []Zir.Inst.Index, // refs to params in `body_gz` should still be in `astgen.ref_table`12241 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
12227 cc_ref: Zir.Inst.Ref,12244 cc_ref: Zir.Inst.Ref,
12228 ret_ref: Zir.Inst.Ref,12245 ret_ref: Zir.Inst.Ref,
...@@ -12322,6 +12339,8 @@ const GenZir = struct {...@@ -12322,6 +12339,8 @@ const GenZir = struct {
1232212339
12323 .has_cc_body = cc_body.len != 0,12340 .has_cc_body = cc_body.len != 0,
12324 .has_ret_ty_body = ret_body.len != 0,12341 .has_ret_ty_body = ret_body.len != 0,
12342
12343 .ret_ty_is_generic = args.ret_ty_is_generic,
12325 },12344 },
12326 });12345 });
1232712346
...@@ -12372,7 +12391,10 @@ const GenZir = struct {...@@ -12372,7 +12391,10 @@ const GenZir = struct {
1237212391
12373 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{12392 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
12374 .param_block = args.param_block,12393 .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 },
12376 .body_len = body_len,12398 .body_len = body_len,
12377 });12399 });
12378 const zir_datas = astgen.instructions.items(.data);12400 const zir_datas = astgen.instructions.items(.data);
...@@ -12535,6 +12557,7 @@ const GenZir = struct {...@@ -12535,6 +12557,7 @@ const GenZir = struct {
12535 /// Previous parameters, which might be referenced in `param_gz` (the new parameter type).12557 /// Previous parameters, which might be referenced in `param_gz` (the new parameter type).
12536 /// `ref`s of these instructions will be put into this param's type body, and removed from `AstGen.ref_table`.12558 /// `ref`s of these instructions will be put into this param's type body, and removed from `AstGen.ref_table`.
12537 prev_param_insts: []const Zir.Inst.Index,12559 prev_param_insts: []const Zir.Inst.Index,
12560 ty_is_generic: bool,
12538 tag: Zir.Inst.Tag,12561 tag: Zir.Inst.Tag,
12539 /// Absolute token index. This function does the conversion to Decl offset.12562 /// Absolute token index. This function does the conversion to Decl offset.
12540 abs_tok_index: Ast.TokenIndex,12563 abs_tok_index: Ast.TokenIndex,
...@@ -12548,7 +12571,10 @@ const GenZir = struct {...@@ -12548,7 +12571,10 @@ const GenZir = struct {
1254812571
12549 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{12572 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
12550 .name = name,12573 .name = name,
12551 .body_len = @intCast(body_len),12574 .type = .{
12575 .body_len = @intCast(body_len),
12576 .is_generic = ty_is_generic,
12577 },
12552 });12578 });
12553 gz.astgen.appendBodyWithFixupsExtraRefsArrayList(&gz.astgen.extra, param_body, prev_param_insts);12579 gz.astgen.appendBodyWithFixupsExtraRefsArrayList(&gz.astgen.extra, param_body, prev_param_insts);
12554 param_gz.unstack();12580 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) {...@@ -89,6 +89,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
89 Inst.SwitchBlockErrUnion.Bits,89 Inst.SwitchBlockErrUnion.Bits,
90 Inst.FuncFancy.Bits,90 Inst.FuncFancy.Bits,
91 Inst.Declaration.Flags,91 Inst.Declaration.Flags,
92 Inst.Param.Type,
93 Inst.Func.RetTy,
92 => @bitCast(code.extra[i]),94 => @bitCast(code.extra[i]),
9395
94 else => @compileError("bad field type"),96 else => @compileError("bad field type"),
...@@ -2126,7 +2128,7 @@ pub const Inst = struct {...@@ -2126,7 +2128,7 @@ pub const Inst = struct {
2126 ref_start_index = static_len,2128 ref_start_index = static_len,
2127 _,2129 _,
21282130
2129 pub const static_len = 71;2131 pub const static_len = 70;
21302132
2131 pub fn toRef(i: Index) Inst.Ref {2133 pub fn toRef(i: Index) Inst.Ref {
2132 return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i));2134 return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i));
...@@ -2229,7 +2231,6 @@ pub const Inst = struct {...@@ -2229,7 +2231,6 @@ pub const Inst = struct {
2229 bool_true,2231 bool_true,
2230 bool_false,2232 bool_false,
2231 empty_tuple,2233 empty_tuple,
2232 generic_poison,
22332234
2234 /// This Ref does not correspond to any ZIR instruction or constant2235 /// This Ref does not correspond to any ZIR instruction or constant
2235 /// value and may instead be used as a sentinel to indicate null.2236 /// value and may instead be used as a sentinel to indicate null.
...@@ -2472,24 +2473,31 @@ pub const Inst = struct {...@@ -2472,24 +2473,31 @@ pub const Inst = struct {
2472 };2473 };
24732474
2474 /// Trailing:2475 /// Trailing:
2475 /// if (ret_body_len == 1) {2476 /// if (ret_ty.body_len == 1) {
2476 /// 0. return_type: Ref2477 /// 0. return_type: Ref
2477 /// }2478 /// }
2478 /// if (ret_body_len > 1) {2479 /// if (ret_ty.body_len > 1) {
2479 /// 1. return_type: Index // for each ret_body_len2480 /// 1. return_type: Index // for each ret_ty.body_len
2480 /// }2481 /// }
2481 /// 2. body: Index // for each body_len2482 /// 2. body: Index // for each body_len
2482 /// 3. src_locs: SrcLocs // if body_len != 02483 /// 3. src_locs: SrcLocs // if body_len != 0
2483 /// 4. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype2484 /// 4. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype
2484 pub const Func = struct {2485 pub const Func = struct {
2485 /// If this is 0 it means a void return type.2486 ret_ty: RetTy,
2486 /// If this is 1 it means return_type is a simple Ref
2487 ret_body_len: u32,
2488 /// Points to the block that contains the param instructions for this function.2487 /// Points to the block that contains the param instructions for this function.
2489 /// If this is a `declaration`, it refers to the declaration's value body.2488 /// If this is a `declaration`, it refers to the declaration's value body.
2490 param_block: Index,2489 param_block: Index,
2491 body_len: u32,2490 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
2493 pub const SrcLocs = struct {2501 pub const SrcLocs = struct {
2494 /// Line index in the source file relative to the parent decl.2502 /// Line index in the source file relative to the parent decl.
2495 lbrace_line: u32,2503 lbrace_line: u32,
...@@ -2539,7 +2547,8 @@ pub const Inst = struct {...@@ -2539,7 +2547,8 @@ pub const Inst = struct {
2539 has_ret_ty_ref: bool,2547 has_ret_ty_ref: bool,
2540 has_ret_ty_body: bool,2548 has_ret_ty_body: bool,
2541 has_any_noalias: bool,2549 has_any_noalias: bool,
2542 _: u24 = undefined,2550 ret_ty_is_generic: bool,
2551 _: u23 = undefined,
2543 };2552 };
2544 };2553 };
25452554
...@@ -3708,8 +3717,14 @@ pub const Inst = struct {...@@ -3708,8 +3717,14 @@ pub const Inst = struct {
3708 pub const Param = struct {3717 pub const Param = struct {
3709 /// Null-terminated string index.3718 /// Null-terminated string index.
3710 name: NullTerminatedString,3719 name: NullTerminatedString,
3711 /// The body contains the type of the parameter.3720 type: Type,
3712 body_len: u32,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 };
3713 };3728 };
37143729
3715 /// Trailing:3730 /// Trailing:
...@@ -4492,7 +4507,7 @@ fn findTrackableInner(...@@ -4492,7 +4507,7 @@ fn findTrackableInner(
44924507
4493 if (extra.data.body_len == 0) {4508 if (extra.data.body_len == 0) {
4494 // This is just a prototype. No need to track.4509 // 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);
4496 return;4511 return;
4497 }4512 }
44984513
...@@ -4500,11 +4515,11 @@ fn findTrackableInner(...@@ -4500,11 +4515,11 @@ fn findTrackableInner(
4500 contents.func_decl = inst;4515 contents.func_decl = inst;
45014516
4502 var extra_index: usize = extra.end;4517 var extra_index: usize = extra.end;
4503 switch (extra.data.ret_body_len) {4518 switch (extra.data.ret_ty.body_len) {
4504 0 => {},4519 0 => {},
4505 1 => extra_index += 1,4520 1 => extra_index += 1,
4506 else => {4521 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);
4508 extra_index += body.len;4523 extra_index += body.len;
4509 try zir.findTrackableBody(gpa, contents, defers, body);4524 try zir.findTrackableBody(gpa, contents, defers, body);
4510 },4525 },
...@@ -4595,7 +4610,7 @@ fn findTrackableInner(...@@ -4595,7 +4610,7 @@ fn findTrackableInner(
4595 .param, .param_comptime => {4610 .param, .param_comptime => {
4596 const inst_data = datas[@intFromEnum(inst)].pl_tok;4611 const inst_data = datas[@intFromEnum(inst)].pl_tok;
4597 const extra = zir.extraData(Inst.Param, inst_data.payload_index);4612 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);
4599 try zir.findTrackableBody(gpa, contents, defers, body);4614 try zir.findTrackableBody(gpa, contents, defers, body);
4600 },4615 },
46014616
...@@ -4738,6 +4753,7 @@ pub const FnInfo = struct {...@@ -4738,6 +4753,7 @@ pub const FnInfo = struct {
4738 ret_ty_body: []const Inst.Index,4753 ret_ty_body: []const Inst.Index,
4739 body: []const Inst.Index,4754 body: []const Inst.Index,
4740 ret_ty_ref: Zir.Inst.Ref,4755 ret_ty_ref: Zir.Inst.Ref,
4756 ret_ty_is_generic: bool,
4741 total_params_len: u32,4757 total_params_len: u32,
4742 inferred_error_set: bool,4758 inferred_error_set: bool,
4743};4759};
...@@ -4779,6 +4795,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4779,6 +4795,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4779 body: []const Inst.Index,4795 body: []const Inst.Index,
4780 ret_ty_ref: Inst.Ref,4796 ret_ty_ref: Inst.Ref,
4781 ret_ty_body: []const Inst.Index,4797 ret_ty_body: []const Inst.Index,
4798 ret_ty_is_generic: bool,
4782 ies: bool,4799 ies: bool,
4783 } = switch (tags[@intFromEnum(fn_inst)]) {4800 } = switch (tags[@intFromEnum(fn_inst)]) {
4784 .func, .func_inferred => |tag| blk: {4801 .func, .func_inferred => |tag| blk: {
...@@ -4789,7 +4806,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4789,7 +4806,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4789 var ret_ty_ref: Inst.Ref = .none;4806 var ret_ty_ref: Inst.Ref = .none;
4790 var ret_ty_body: []const Inst.Index = &.{};4807 var ret_ty_body: []const Inst.Index = &.{};
47914808
4792 switch (extra.data.ret_body_len) {4809 switch (extra.data.ret_ty.body_len) {
4793 0 => {4810 0 => {
4794 ret_ty_ref = .void_type;4811 ret_ty_ref = .void_type;
4795 },4812 },
...@@ -4798,7 +4815,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4798,7 +4815,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4798 extra_index += 1;4815 extra_index += 1;
4799 },4816 },
4800 else => {4817 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);
4802 extra_index += ret_ty_body.len;4819 extra_index += ret_ty_body.len;
4803 },4820 },
4804 }4821 }
...@@ -4811,6 +4828,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4811,6 +4828,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4811 .ret_ty_ref = ret_ty_ref,4828 .ret_ty_ref = ret_ty_ref,
4812 .ret_ty_body = ret_ty_body,4829 .ret_ty_body = ret_ty_body,
4813 .body = body,4830 .body = body,
4831 .ret_ty_is_generic = extra.data.ret_ty.is_generic,
4814 .ies = tag == .func_inferred,4832 .ies = tag == .func_inferred,
4815 };4833 };
4816 },4834 },
...@@ -4848,6 +4866,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4848,6 +4866,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4848 .ret_ty_ref = ret_ty_ref,4866 .ret_ty_ref = ret_ty_ref,
4849 .ret_ty_body = ret_ty_body,4867 .ret_ty_body = ret_ty_body,
4850 .body = body,4868 .body = body,
4869 .ret_ty_is_generic = extra.data.bits.ret_ty_is_generic,
4851 .ies = extra.data.bits.is_inferred_error,4870 .ies = extra.data.bits.is_inferred_error,
4852 };4871 };
4853 },4872 },
...@@ -4870,6 +4889,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4870,6 +4889,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4870 .ret_ty_ref = info.ret_ty_ref,4889 .ret_ty_ref = info.ret_ty_ref,
4871 .body = info.body,4890 .body = info.body,
4872 .total_params_len = total_params_len,4891 .total_params_len = total_params_len,
4892 .ret_ty_is_generic = info.ret_ty_is_generic,
4873 .inferred_error_set = info.ies,4893 .inferred_error_set = info.ies,
4874 };4894 };
4875}4895}
...@@ -4967,7 +4987,7 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {...@@ -4967,7 +4987,7 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
4967 return null;4987 return null;
4968 }4988 }
4969 const extra_index = extra.end +4989 const extra_index = extra.end +
4970 extra.data.ret_body_len +4990 extra.data.ret_ty.body_len +
4971 extra.data.body_len +4991 extra.data.body_len +
4972 @typeInfo(Inst.Func.SrcLocs).@"struct".fields.len;4992 @typeInfo(Inst.Func.SrcLocs).@"struct".fields.len;
4973 return @bitCast([4]u32{4993 return @bitCast([4]u32{
src/Air.zig-1
...@@ -1004,7 +1004,6 @@ pub const Inst = struct {...@@ -1004,7 +1004,6 @@ pub const Inst = struct {
1004 bool_true = @intFromEnum(InternPool.Index.bool_true),1004 bool_true = @intFromEnum(InternPool.Index.bool_true),
1005 bool_false = @intFromEnum(InternPool.Index.bool_false),1005 bool_false = @intFromEnum(InternPool.Index.bool_false),
1006 empty_tuple = @intFromEnum(InternPool.Index.empty_tuple),1006 empty_tuple = @intFromEnum(InternPool.Index.empty_tuple),
1007 generic_poison = @intFromEnum(InternPool.Index.generic_poison),
10081007
1009 /// This Ref does not correspond to any AIR instruction or constant1008 /// This Ref does not correspond to any AIR instruction or constant
1010 /// value and may instead be used as a sentinel to indicate null.1009 /// 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 {...@@ -455,9 +455,8 @@ pub fn checkVal(val: Value, zcu: *Zcu) bool {
455455
456pub fn checkType(ty: Type, zcu: *Zcu) bool {456pub fn checkType(ty: Type, zcu: *Zcu) bool {
457 const ip = &zcu.intern_pool;457 const ip = &zcu.intern_pool;
458 return switch (ty.zigTypeTagOrPoison(zcu) catch |err| switch (err) {458 if (ty.isGenericPoison()) return true;
459 error.GenericPoison => return true,459 return switch (ty.zigTypeTag(zcu)) {
460 }) {
461 .type,460 .type,
462 .void,461 .void,
463 .bool,462 .bool,
src/InternPool.zig+11-16
...@@ -620,11 +620,11 @@ pub const Nav = struct {...@@ -620,11 +620,11 @@ pub const Nav = struct {
620 return switch (nav.status) {620 return switch (nav.status) {
621 .unresolved => unreachable,621 .unresolved => unreachable,
622 .type_resolved => |r| {622 .type_resolved => |r| {
623 const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable;623 const tag = ip.zigTypeTag(r.type);
624 return tag == .@"fn";624 return tag == .@"fn";
625 },625 },
626 .fully_resolved => |r| {626 .fully_resolved => |r| {
627 const tag = ip.zigTypeTagOrPoison(ip.typeOf(r.val)) catch unreachable;627 const tag = ip.zigTypeTag(ip.typeOf(r.val));
628 return tag == .@"fn";628 return tag == .@"fn";
629 },629 },
630 };630 };
...@@ -639,13 +639,13 @@ pub const Nav = struct {...@@ -639,13 +639,13 @@ pub const Nav = struct {
639 .unresolved => unreachable,639 .unresolved => unreachable,
640 .type_resolved => |r| {640 .type_resolved => |r| {
641 if (r.is_extern_decl) return true;641 if (r.is_extern_decl) return true;
642 const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable;642 const tag = ip.zigTypeTag(r.type);
643 if (tag == .@"fn") return true;643 if (tag == .@"fn") return true;
644 return false;644 return false;
645 },645 },
646 .fully_resolved => |r| {646 .fully_resolved => |r| {
647 if (ip.indexToKey(r.val) == .@"extern") return true;647 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));
649 if (tag == .@"fn") return true;649 if (tag == .@"fn") return true;
650 return false;650 return false;
651 },651 },
...@@ -3216,7 +3216,6 @@ pub const Key = union(enum) {...@@ -3216,7 +3216,6 @@ pub const Key = union(enum) {
3216 .false, .true => .bool_type,3216 .false, .true => .bool_type,
3217 .empty_tuple => .empty_tuple_type,3217 .empty_tuple => .empty_tuple_type,
3218 .@"unreachable" => .noreturn_type,3218 .@"unreachable" => .noreturn_type,
3219 .generic_poison => .generic_poison_type,
3220 },3219 },
32213220
3222 .memoized_call => unreachable,3221 .memoized_call => unreachable,
...@@ -4581,6 +4580,10 @@ pub const Index = enum(u32) {...@@ -4581,6 +4580,10 @@ pub const Index = enum(u32) {
4581 anyerror_void_error_union_type,4580 anyerror_void_error_union_type,
4582 /// Used for the inferred error set of inline/comptime function calls.4581 /// Used for the inferred error set of inline/comptime function calls.
4583 adhoc_inferred_error_set_type,4582 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).
4584 generic_poison_type,4587 generic_poison_type,
4585 /// `@TypeOf(.{})`; a tuple with zero elements.4588 /// `@TypeOf(.{})`; a tuple with zero elements.
4586 /// This is not the same as `struct {}`, since that is a struct rather than a tuple.4589 /// 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) {...@@ -4617,10 +4620,6 @@ pub const Index = enum(u32) {
4617 /// `.{}`4620 /// `.{}`
4618 empty_tuple,4621 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
4624 /// Used by Air/Sema only.4623 /// Used by Air/Sema only.
4625 none = std.math.maxInt(u32),4624 none = std.math.maxInt(u32),
46264625
...@@ -5136,7 +5135,6 @@ pub const static_keys = [_]Key{...@@ -5136,7 +5135,6 @@ pub const static_keys = [_]Key{
5136 .{ .simple_value = .true },5135 .{ .simple_value = .true },
5137 .{ .simple_value = .false },5136 .{ .simple_value = .false },
5138 .{ .simple_value = .empty_tuple },5137 .{ .simple_value = .empty_tuple },
5139 .{ .simple_value = .generic_poison },
5140};5138};
51415139
5142/// How many items in the InternPool are statically known.5140/// How many items in the InternPool are statically known.
...@@ -6054,8 +6052,6 @@ pub const SimpleValue = enum(u32) {...@@ -6054,8 +6052,6 @@ pub const SimpleValue = enum(u32) {
6054 true = @intFromEnum(Index.bool_true),6052 true = @intFromEnum(Index.bool_true),
6055 false = @intFromEnum(Index.bool_false),6053 false = @intFromEnum(Index.bool_false),
6056 @"unreachable" = @intFromEnum(Index.unreachable_value),6054 @"unreachable" = @intFromEnum(Index.unreachable_value),
6057
6058 generic_poison = @intFromEnum(Index.generic_poison),
6059};6055};
60606056
6061/// Stored as a power-of-two, with one special value to indicate none.6057/// 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 {...@@ -11712,7 +11708,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
11712 .null_value => .null_type,11708 .null_value => .null_type,
11713 .bool_true, .bool_false => .bool_type,11709 .bool_true, .bool_false => .bool_type,
11714 .empty_tuple => .empty_tuple_type,11710 .empty_tuple => .empty_tuple_type,
11715 .generic_poison => .generic_poison_type,
1171611711
11717 // This optimization on tags is needed so that indexToKey can call11712 // This optimization on tags is needed so that indexToKey can call
11718 // typeOf without being recursive.11713 // typeOf without being recursive.
...@@ -11954,7 +11949,8 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Ta...@@ -11954,7 +11949,8 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Ta
1195411949
11955/// This is a particularly hot function, so we operate directly on encodings11950/// This is a particularly hot function, so we operate directly on encodings
11956/// rather than the more straightforward implementation of calling `indexToKey`.11951/// 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 {
11958 return switch (index) {11954 return switch (index) {
11959 .u0_type,11955 .u0_type,
11960 .i0_type,11956 .i0_type,
...@@ -12017,7 +12013,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -12017,7 +12013,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
12017 .anyerror_void_error_union_type => .error_union,12013 .anyerror_void_error_union_type => .error_union,
12018 .empty_tuple_type => .@"struct",12014 .empty_tuple_type => .@"struct",
1201912015
12020 .generic_poison_type => return error.GenericPoison,12016 .generic_poison_type => unreachable,
1202112017
12022 // values, not types12018 // values, not types
12023 .undef => unreachable,12019 .undef => unreachable,
...@@ -12035,7 +12031,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -12035,7 +12031,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
12035 .bool_true => unreachable,12031 .bool_true => unreachable,
12036 .bool_false => unreachable,12032 .bool_false => unreachable,
12037 .empty_tuple => unreachable,12033 .empty_tuple => unreachable,
12038 .generic_poison => unreachable,
1203912034
12040 _ => switch (index.unwrap(ip).getTag(ip)) {12035 _ => switch (index.unwrap(ip).getTag(ip)) {
12041 .removed => unreachable,12036 .removed => unreachable,
src/Sema.zig+127-292
...@@ -53,9 +53,6 @@ comptime_break_inst: Zir.Inst.Index = undefined,...@@ -53,9 +53,6 @@ comptime_break_inst: Zir.Inst.Index = undefined,
53post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .empty,53post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .empty,
54/// Populated with the last compile error created.54/// Populated with the last compile error created.
55err: ?*Zcu.ErrorMsg = null,55err: ?*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
60/// The temporary arena is used for the memory of the `InferredAlloc` values57/// The temporary arena is used for the memory of the `InferredAlloc` values
61/// here so the values can be dropped without any cleanup.58/// 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 {...@@ -1935,9 +1932,7 @@ pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1935pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {1932pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1936 assert(zir_ref != .none);1933 assert(zir_ref != .none);
1937 if (zir_ref.toIndex()) |i| {1934 if (zir_ref.toIndex()) |i| {
1938 const inst = sema.inst_map.get(i).?;1935 return sema.inst_map.get(i).?;
1939 if (inst == .generic_poison) return error.GenericPoison;
1940 return inst;
1941 }1936 }
1942 // First section of indexes correspond to a set number of constant values.1937 // First section of indexes correspond to a set number of constant values.
1943 // We intentionally map the same indexes to the same values between ZIR and AIR.1938 // We intentionally map the same indexes to the same values between ZIR and AIR.
...@@ -1997,13 +1992,17 @@ pub fn resolveConstStringIntern(...@@ -1997,13 +1992,17 @@ pub fn resolveConstStringIntern(
1997 return sema.sliceToIpString(block, src, val, reason);1992 return sema.sliceToIpString(block, src, val, reason);
1998}1993}
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 {
2001 const air_inst = try sema.resolveInst(zir_ref);1996 const air_inst = try sema.resolveInst(zir_ref);
2002 const ty = try sema.analyzeAsType(block, src, air_inst);1997 const ty = try sema.analyzeAsType(block, src, air_inst);
2003 if (ty.isGenericPoison()) return error.GenericPoison;1998 if (ty.isGenericPoison()) return null;
2004 return ty;1999 return ty;
2005}2000}
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
2007fn resolveDestType(2006fn resolveDestType(
2008 sema: *Sema,2007 sema: *Sema,
2009 block: *Block,2008 block: *Block,
...@@ -2023,24 +2022,21 @@ fn resolveDestType(...@@ -2023,24 +2022,21 @@ fn resolveDestType(
2023 .remove_eu => false,2022 .remove_eu => false,
2024 };2023 };
20252024
2026 const raw_ty = sema.resolveType(block, src, zir_ref) catch |err| switch (err) {2025 const raw_ty = try sema.resolveTypeOrPoison(block, src, zir_ref) orelse {
2027 error.GenericPoison => {2026 // Cast builtins use their result type as the destination type, but
2028 // Cast builtins use their result type as the destination type, but2027 // it could be an anytype argument, which we can't catch in AstGen.
2029 // it could be an anytype argument, which we can't catch in AstGen.2028 const msg = msg: {
2030 const msg = msg: {2029 const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name});
2031 const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name});2030 errdefer msg.destroy(sema.gpa);
2032 errdefer msg.destroy(sema.gpa);2031 switch (sema.genericPoisonReason(block, zir_ref)) {
2033 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", .{}),
2034 .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", .{}),
2035 .anyopaque_ptr => |ptr_src| try sema.errNote(ptr_src, msg, "result type is unknown due to opaque pointer type", .{}),2034 .unknown => {},
2036 .unknown => {},2035 }
2037 }2036 try sema.errNote(src, msg, "use @as to provide explicit result type", .{});
2038 try sema.errNote(src, msg, "use @as to provide explicit result type", .{});2037 break :msg msg;
2039 break :msg msg;2038 };
2040 };2039 return sema.failWithOwnedErrorMsg(block, msg);
2041 return sema.failWithOwnedErrorMsg(block, msg);
2042 },
2043 else => |e| return e,
2044 };2040 };
20452041
2046 if (remove_eu and raw_ty.zigTypeTag(zcu) == .error_union) {2042 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...@@ -2086,9 +2082,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
2086 // Either the input type was itself poison, or it was a slice, which we cannot translate2082 // Either the input type was itself poison, or it was a slice, which we cannot translate
2087 // to an overall result type.2083 // to an overall result type.
2088 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;2084 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) {2085 const operand_ref = try sema.resolveInst(un_node.operand);
2090 error.GenericPoison => unreachable, // this is a type, not a value
2091 };
2092 if (operand_ref == .generic_poison_type) {2086 if (operand_ref == .generic_poison_type) {
2093 // The input was poison -- keep looking.2087 // The input was poison -- keep looking.
2094 cur = un_node.operand;2088 cur = un_node.operand;
...@@ -2107,9 +2101,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi...@@ -2107,9 +2101,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
2107 // There are two cases here: the pointer type may already have been2101 // There are two cases here: the pointer type may already have been
2108 // generic poison, or it may have been an anyopaque pointer.2102 // generic poison, or it may have been an anyopaque pointer.
2109 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;2103 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) {2104 const operand_ref = try sema.resolveInst(un_node.operand);
2111 error.GenericPoison => unreachable, // this is a type, not a value
2112 };
2113 const operand_val = operand_ref.toInterned() orelse return .unknown;2105 const operand_val = operand_ref.toInterned() orelse return .unknown;
2114 if (operand_val == .generic_poison_type) {2106 if (operand_val == .generic_poison_type) {
2115 // The pointer was generic poison - keep looking.2107 // The pointer was generic poison - keep looking.
...@@ -2187,7 +2179,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)...@@ -2187,7 +2179,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
2187}2179}
21882180
2189/// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value.2181/// 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.
2191fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {2182fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2192 const zcu = sema.pt.zcu;2183 const zcu = sema.pt.zcu;
2193 assert(inst != .none);2184 assert(inst != .none);
...@@ -2201,7 +2192,6 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {...@@ -2201,7 +2192,6 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
22012192
2202 assert(val.getVariable(zcu) == null);2193 assert(val.getVariable(zcu) == null);
2203 if (val.isPtrRuntimeValue(zcu)) return null;2194 if (val.isPtrRuntimeValue(zcu)) return null;
2204 if (val.isGenericPoison()) return error.GenericPoison;
22052195
2206 return val;2196 return val;
2207 } else {2197 } else {
...@@ -2761,8 +2751,7 @@ fn zirTupleDecl(...@@ -2761,8 +2751,7 @@ fn zirTupleDecl(
2761 .elem_index = @intCast(field_index),2751 .elem_index = @intCast(field_index),
2762 } });2752 } });
27632753
2764 const uncoerced_field_ty = try sema.resolveInst(zir_field_ty);2754 const field_type = try sema.resolveType(block, type_src, zir_field_ty);
2765 const field_type = try sema.analyzeAsType(block, type_src, uncoerced_field_ty);
2766 try sema.validateTupleFieldType(block, field_type, type_src);2755 try sema.validateTupleFieldType(block, field_type, type_src);
27672756
2768 field_ty.* = field_type.toIntern();2757 field_ty.* = field_type.toIntern();
...@@ -4555,10 +4544,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -4555,10 +4544,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4555 const src = block.nodeOffset(pl_node.src_node);4544 const src = block.nodeOffset(pl_node.src_node);
4556 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;4545 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;
4557 const uncoerced_val = try sema.resolveInst(extra.rhs);4546 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) {4547 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val;
4559 error.GenericPoison => return uncoerced_val,
4560 else => |e| return e,
4561 };
4562 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);4548 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
4563 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction4549 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
4564 const elem_ty = ptr_ty.childType(zcu);4550 const elem_ty = ptr_ty.childType(zcu);
...@@ -4606,10 +4592,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo...@@ -4606,10 +4592,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
4606 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;4592 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
4607 const src = block.nodeOffset(un_node.src_node);4593 const src = block.nodeOffset(un_node.src_node);
46084594
4609 const operand_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {4595 const operand_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type;
4610 error.GenericPoison => return .generic_poison_type,
4611 else => |e| return e,
4612 };
46134596
4614 const payload_ty = if (is_ref) ty: {4597 const payload_ty = if (is_ref) ty: {
4615 if (!operand_ty.isSinglePointer(zcu)) {4598 if (!operand_ty.isSinglePointer(zcu)) {
...@@ -4656,15 +4639,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4656,15 +4639,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4656 const src = block.tokenOffset(un_tok.src_tok);4639 const src = block.tokenOffset(un_tok.src_tok);
4657 // In case of GenericPoison, we don't actually have a type, so this will be4640 // In case of GenericPoison, we don't actually have a type, so this will be
4658 // treated as an untyped address-of operator.4641 // treated as an untyped address-of operator.
4659 const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) {4642 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
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;
4668 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {4643 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
4669 return sema.failWithOwnedErrorMsg(block, msg: {4644 return sema.failWithOwnedErrorMsg(block, msg: {
4670 const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(pt)});4645 const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(pt)});
...@@ -4696,10 +4671,7 @@ fn zirValidateArrayInitRefTy(...@@ -4696,10 +4671,7 @@ fn zirValidateArrayInitRefTy(
4696 const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;4671 const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
4697 const src = block.nodeOffset(pl_node.src_node);4672 const src = block.nodeOffset(pl_node.src_node);
4698 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;4673 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) {4674 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.ptr_ty) orelse return .generic_poison_type;
4700 error.GenericPoison => return .generic_poison_type,
4701 else => |e| return e,
4702 };
4703 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);4675 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
4704 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction4676 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
4705 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) {4677 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) {
...@@ -4740,11 +4712,8 @@ fn zirValidateArrayInitTy(...@@ -4740,11 +4712,8 @@ fn zirValidateArrayInitTy(
4740 const src = block.nodeOffset(inst_data.src_node);4712 const src = block.nodeOffset(inst_data.src_node);
4741 const ty_src: LazySrcLoc = if (is_result_ty) src else block.src(.{ .node_offset_init_ty = inst_data.src_node });4713 const ty_src: LazySrcLoc = if (is_result_ty) src else block.src(.{ .node_offset_init_ty = inst_data.src_node });
4742 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;4714 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) {4715 // It's okay for the type to be poison: this will result in an anonymous array init.
4744 // It's okay for the type to be unknown: this will result in an anonymous array init.4716 const ty = try sema.resolveTypeOrPoison(block, ty_src, extra.ty) orelse return;
4745 error.GenericPoison => return,
4746 else => |e| return e,
4747 };
4748 const arr_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;4717 const arr_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;
4749 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);4718 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);
4750}4719}
...@@ -4803,11 +4772,8 @@ fn zirValidateStructInitTy(...@@ -4803,11 +4772,8 @@ fn zirValidateStructInitTy(
4803 const zcu = pt.zcu;4772 const zcu = pt.zcu;
4804 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;4773 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
4805 const src = block.nodeOffset(inst_data.src_node);4774 const src = block.nodeOffset(inst_data.src_node);
4806 const ty = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {4775 // It's okay for the type to be poison: this will result in an anonymous struct init.
4807 // It's okay for the type to be unknown: this will result in an anonymous struct init.4776 const ty = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return;
4808 error.GenericPoison => return,
4809 else => |e| return e,
4810 };
4811 const struct_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;4777 const struct_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;
48124778
4813 switch (struct_ty.zigTypeTag(zcu)) {4779 switch (struct_ty.zigTypeTag(zcu)) {
...@@ -7043,7 +7009,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -7043,7 +7009,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
7043 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);7009 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
7044 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {7010 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
7045 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),7011 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
7046 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,7012 error.ComptimeReturn, error.ComptimeBreak => unreachable,
7047 error.OutOfMemory => |e| return e,7013 error.OutOfMemory => |e| return e,
7048 };7014 };
70497015
...@@ -7668,6 +7634,11 @@ fn analyzeCall(...@@ -7668,6 +7634,11 @@ fn analyzeCall(
7668 }7634 }
7669 }7635 }
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
7671 // These values are undefined if `func_val == null`.7642 // These values are undefined if `func_val == null`.
7672 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: {7643 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: {
7673 const info = ip.indexToKey(f.toIntern()).func;7644 const info = ip.indexToKey(f.toIntern()).func;
...@@ -7746,7 +7717,7 @@ fn analyzeCall(...@@ -7746,7 +7717,7 @@ fn analyzeCall(
77467717
7747 const extra = sema.code.extraData(Zir.Inst.Param, param_inst.data.pl_tok.payload_index);7718 const extra = sema.code.extraData(Zir.Inst.Param, param_inst.data.pl_tok.payload_index);
7748 const param_src = generic_block.tokenOffset(param_inst.data.pl_tok.src_tok);7719 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
7751 generic_block.comptime_reason = .{ .reason = .{7722 generic_block.comptime_reason = .{ .reason = .{
7752 .r = .{ .simple = .function_parameters },7723 .r = .{ .simple = .function_parameters },
...@@ -7777,8 +7748,10 @@ fn analyzeCall(...@@ -7777,8 +7748,10 @@ fn analyzeCall(
7777 const param_inst_idx = fn_zir_info.param_body[arg_idx];7748 const param_inst_idx = fn_zir_info.param_body[arg_idx];
7778 const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false;7749 const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false;
7779 const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt);7750 const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt);
7780 if (param_is_comptime) {7751 // We allow comptime-known arguments to propagate to generic types not only for comptime
7781 if (!try sema.isComptimeKnown(arg.*)) {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.*)) {
7782 assert(!declared_comptime); // `analyzeArg` handles this7755 assert(!declared_comptime); // `analyzeArg` handles this
7783 const arg_src = args_info.argSrc(block, arg_idx);7756 const arg_src = args_info.argSrc(block, arg_idx);
7784 const param_ty_src: LazySrcLoc = .{7757 const param_ty_src: LazySrcLoc = .{
...@@ -8313,14 +8286,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -8313,14 +8286,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
8313 const pt = sema.pt;8286 const pt = sema.pt;
8314 const zcu = pt.zcu;8287 const zcu = pt.zcu;
8315 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;8288 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) {8289 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type;
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 };
8324 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu);8290 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu);
8325 try indexable_ty.resolveFields(pt);8291 try indexable_ty.resolveFields(pt);
8326 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction8292 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...@@ -8337,10 +8303,7 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
8337 const pt = sema.pt;8303 const pt = sema.pt;
8338 const zcu = pt.zcu;8304 const zcu = pt.zcu;
8339 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;8305 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) {8306 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
8341 error.GenericPoison => return .generic_poison_type,
8342 else => |e| return e,
8343 };
8344 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);8307 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);
8345 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction8308 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
8346 const elem_ty = ptr_ty.childType(zcu);8309 const elem_ty = ptr_ty.childType(zcu);
...@@ -8357,10 +8320,7 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -8357,10 +8320,7 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
8357 const zcu = pt.zcu;8320 const zcu = pt.zcu;
8358 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;8321 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
8359 const src = block.nodeOffset(un_node.src_node);8322 const src = block.nodeOffset(un_node.src_node);
8360 const ptr_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {8323 const ptr_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type;
8361 error.GenericPoison => return .generic_poison_type,
8362 else => |e| return e,
8363 };
8364 try sema.checkMemOperand(block, src, ptr_ty);8324 try sema.checkMemOperand(block, src, ptr_ty);
8365 const elem_ty = switch (ptr_ty.ptrSize(zcu)) {8325 const elem_ty = switch (ptr_ty.ptrSize(zcu)) {
8366 .slice, .many, .c => ptr_ty.childType(zcu),8326 .slice, .many, .c => ptr_ty.childType(zcu),
...@@ -8373,14 +8333,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8373,14 +8333,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8373 const pt = sema.pt;8333 const pt = sema.pt;
8374 const zcu = pt.zcu;8334 const zcu = pt.zcu;
8375 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;8335 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) {8336 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
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 };
8384 switch (vec_ty.zigTypeTag(zcu)) {8337 switch (vec_ty.zigTypeTag(zcu)) {
8385 .array, .vector => {},8338 .array, .vector => {},
8386 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{}'", .{vec_ty.fmt(pt)}),8339 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...@@ -8702,10 +8655,7 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b
8702 .no_embedded_nulls,8655 .no_embedded_nulls,
8703 );8656 );
87048657
8705 const orig_ty = sema.resolveType(block, src, extra.lhs) catch |err| switch (err) {8658 const orig_ty: Type = try sema.resolveTypeOrPoison(block, src, extra.lhs) orelse .generic_poison;
8706 error.GenericPoison => Type.generic_poison,
8707 else => |e| return e,
8708 };
87098659
8710 const uncoerced_result = res: {8660 const uncoerced_result = res: {
8711 if (orig_ty.toIntern() == .generic_poison_type) {8661 if (orig_ty.toIntern() == .generic_poison_type) {
...@@ -9232,22 +9182,17 @@ fn zirFunc(...@@ -9232,22 +9182,17 @@ fn zirFunc(
92329182
9233 var extra_index = extra.end;9183 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) {
9236 0 => Type.void,9188 0 => Type.void,
9237 1 => blk: {9189 1 => blk: {
9238 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);9190 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
9239 extra_index += 1;9191 extra_index += 1;
9240 if (sema.resolveType(block, ret_ty_src, ret_ty_ref)) |ret_ty| {9192 break :blk try sema.resolveType(block, ret_ty_src, ret_ty_ref);
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 }
9248 },9193 },
9249 else => blk: {9194 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);
9251 extra_index += ret_ty_body.len;9196 extra_index += ret_ty_body.len;
92529197
9253 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, .{ .simple = .function_ret_ty });9198 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(...@@ -9319,32 +9264,16 @@ fn resolveGenericBody(
9319) !Value {9264) !Value {
9320 assert(body.len != 0);9265 assert(body.len != 0);
93219266
9322 const err = err: {9267 // Make sure any nested param instructions don't clobber our work.
9323 // Make sure any nested param instructions don't clobber our work.9268 const prev_params = block.params;
9324 const prev_params = block.params;9269 block.params = .{};
9325 const prev_no_partial_func_type = sema.no_partial_func_ty;9270 defer {
9326 block.params = .{};9271 block.params = prev_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,
9347 }9272 }
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);
9348}9277}
93499278
9350/// Given a library name, examines if the library name should end up in9279/// Given a library name, examines if the library name should end up in
...@@ -9593,8 +9522,6 @@ fn funcCommon(...@@ -9593,8 +9522,6 @@ fn funcCommon(
9593 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });9522 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
9594 const func_src = block.nodeOffset(src_node_offset);9523 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
9598 const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt);9525 const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt);
9599 var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime;9526 var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime;
96009527
...@@ -9611,9 +9538,6 @@ fn funcCommon(...@@ -9611,9 +9538,6 @@ fn funcCommon(
9611 } });9538 } });
9612 const param_ty_comptime = try param_ty.comptimeOnlySema(pt);9539 const param_ty_comptime = try param_ty.comptimeOnlySema(pt);
9613 const param_ty_generic = param_ty.isGenericPoison();9540 const param_ty_generic = param_ty.isGenericPoison();
9614 if (param_ty_generic and sema.no_partial_func_ty) {
9615 return error.GenericPoison;
9616 }
9617 if (param_is_comptime or param_ty_comptime or param_ty_generic) {9541 if (param_is_comptime or param_ty_comptime or param_ty_generic) {
9618 is_generic = true;9542 is_generic = true;
9619 }9543 }
...@@ -9962,64 +9886,25 @@ fn zirParam(...@@ -9962,64 +9886,25 @@ fn zirParam(
9962 const src = block.tokenOffset(inst_data.src_tok);9886 const src = block.tokenOffset(inst_data.src_tok);
9963 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);9887 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
9964 const param_name: Zir.NullTerminatedString = extra.data.name;9888 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: {9891 const param_ty: Type = if (extra.data.type.is_generic) .generic_poison else ty: {
9968 const err = err: {9892 // Make sure any nested param instructions don't clobber our work.
9969 // Make sure any nested param instructions don't clobber our work.9893 const prev_params = block.params;
9970 const prev_params = block.params;9894 block.params = .{};
9971 const prev_no_partial_func_type = sema.no_partial_func_ty;9895 defer {
9972 block.params = .{};9896 block.params = prev_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,
9999 }9897 }
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
10004 try block.params.append(sema.arena, .{9903 try block.params.append(sema.arena, .{
10005 .ty = param_ty.toIntern(),9904 .ty = param_ty.toIntern(),
10006 .is_comptime = comptime_syntax,9905 .is_comptime = comptime_syntax,
10007 .name = param_name,9906 .name = param_name,
10008 });9907 });
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 }
10023}9908}
100249909
10025fn zirParamAnytype(9910fn zirParamAnytype(
...@@ -10031,14 +9916,11 @@ fn zirParamAnytype(...@@ -10031,14 +9916,11 @@ fn zirParamAnytype(
10031 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;9916 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
10032 const param_name: Zir.NullTerminatedString = inst_data.start;9917 const param_name: Zir.NullTerminatedString = inst_data.start;
100339918
10034 // We are evaluating a generic function without any comptime args provided.
10035
10036 try block.params.append(sema.arena, .{9919 try block.params.append(sema.arena, .{
10037 .ty = .generic_poison_type,9920 .ty = .generic_poison_type,
10038 .is_comptime = comptime_syntax,9921 .is_comptime = comptime_syntax,
10039 .name = param_name,9922 .name = param_name,
10040 });9923 });
10041 sema.inst_map.putAssumeCapacity(inst, .generic_poison);
10042}9924}
100439925
10044fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9926fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -10072,24 +9954,11 @@ fn analyzeAs(...@@ -10072,24 +9954,11 @@ fn analyzeAs(
10072 const pt = sema.pt;9954 const pt = sema.pt;
10073 const zcu = pt.zcu;9955 const zcu = pt.zcu;
10074 const operand = try sema.resolveInst(zir_operand);9956 const operand = try sema.resolveInst(zir_operand);
10075 const operand_air_inst = sema.resolveInst(zir_dest_type) catch |err| switch (err) {9957 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
10076 error.GenericPoison => return operand,9958 switch (dest_ty.zigTypeTag(zcu)) {
10077 else => |e| return e,9959 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)}),
10078 };9960 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
10079 const dest_ty = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {9961 else => {},
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", .{});
10093 }9962 }
100949963
10095 const is_ret = if (zir_dest_type.toIndex()) |ptr_index|9964 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...@@ -15071,9 +14940,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15071 // and have a tuple, coerce the tuple immediately.14940 // and have a tuple, coerce the tuple immediately.
15072 no_coerce: {14941 no_coerce: {
15073 if (extra.res_ty == .none) break :no_coerce;14942 if (extra.res_ty == .none) break :no_coerce;
15074 const res_ty_inst = try sema.resolveInst(extra.res_ty);14943 const res_ty = try sema.resolveTypeOrPoison(block, src, extra.res_ty) orelse break :no_coerce;
15075 const res_ty = try sema.analyzeAsType(block, src, res_ty_inst);
15076 if (res_ty.isGenericPoison()) break :no_coerce;
15077 if (!uncoerced_lhs_ty.isTuple(zcu)) break :no_coerce;14944 if (!uncoerced_lhs_ty.isTuple(zcu)) break :no_coerce;
15078 const lhs_len = uncoerced_lhs_ty.structFieldCount(zcu);14945 const lhs_len = uncoerced_lhs_ty.structFieldCount(zcu);
15079 const lhs_dest_ty = switch (res_ty.zigTypeTag(zcu)) {14946 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...@@ -15313,8 +15180,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15313 const rhs = try sema.resolveInst(extra.rhs);15180 const rhs = try sema.resolveInst(extra.rhs);
15314 const lhs_ty = sema.typeOf(lhs);15181 const lhs_ty = sema.typeOf(lhs);
15315 const rhs_ty = sema.typeOf(rhs);15182 const rhs_ty = sema.typeOf(rhs);
15316 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);15183 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15317 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);15184 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
15318 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15185 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
15319 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);15186 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1532015187
...@@ -15479,8 +15346,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15479,8 +15346,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15479 const rhs = try sema.resolveInst(extra.rhs);15346 const rhs = try sema.resolveInst(extra.rhs);
15480 const lhs_ty = sema.typeOf(lhs);15347 const lhs_ty = sema.typeOf(lhs);
15481 const rhs_ty = sema.typeOf(rhs);15348 const rhs_ty = sema.typeOf(rhs);
15482 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);15349 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15483 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);15350 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
15484 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
15485 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);15352 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1548615353
...@@ -15645,8 +15512,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15645,8 +15512,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15645 const rhs = try sema.resolveInst(extra.rhs);15512 const rhs = try sema.resolveInst(extra.rhs);
15646 const lhs_ty = sema.typeOf(lhs);15513 const lhs_ty = sema.typeOf(lhs);
15647 const rhs_ty = sema.typeOf(rhs);15514 const rhs_ty = sema.typeOf(rhs);
15648 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);15515 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15649 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);15516 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
15650 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15517 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
15651 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);15518 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1565215519
...@@ -15756,8 +15623,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15756,8 +15623,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15756 const rhs = try sema.resolveInst(extra.rhs);15623 const rhs = try sema.resolveInst(extra.rhs);
15757 const lhs_ty = sema.typeOf(lhs);15624 const lhs_ty = sema.typeOf(lhs);
15758 const rhs_ty = sema.typeOf(rhs);15625 const rhs_ty = sema.typeOf(rhs);
15759 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);15626 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
15760 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);15627 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
15761 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15628 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
15762 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);15629 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1576315630
...@@ -16000,8 +15867,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -16000,8 +15867,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
16000 const rhs = try sema.resolveInst(extra.rhs);15867 const rhs = try sema.resolveInst(extra.rhs);
16001 const lhs_ty = sema.typeOf(lhs);15868 const lhs_ty = sema.typeOf(lhs);
16002 const rhs_ty = sema.typeOf(rhs);15869 const rhs_ty = sema.typeOf(rhs);
16003 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);15870 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16004 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);15871 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
16005 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15872 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
16006 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);15873 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...@@ -16186,8 +16053,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16186 const rhs = try sema.resolveInst(extra.rhs);16053 const rhs = try sema.resolveInst(extra.rhs);
16187 const lhs_ty = sema.typeOf(lhs);16054 const lhs_ty = sema.typeOf(lhs);
16188 const rhs_ty = sema.typeOf(rhs);16055 const rhs_ty = sema.typeOf(rhs);
16189 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);16056 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16190 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);16057 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
16191 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);16058 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
16192 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);16059 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...@@ -16282,8 +16149,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16282 const rhs = try sema.resolveInst(extra.rhs);16149 const rhs = try sema.resolveInst(extra.rhs);
16283 const lhs_ty = sema.typeOf(lhs);16150 const lhs_ty = sema.typeOf(lhs);
16284 const rhs_ty = sema.typeOf(rhs);16151 const rhs_ty = sema.typeOf(rhs);
16285 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);16152 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16286 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);16153 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
16287 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);16154 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
16288 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);16155 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1628916156
...@@ -16623,8 +16490,8 @@ fn analyzeArithmetic(...@@ -16623,8 +16490,8 @@ fn analyzeArithmetic(
16623 const zcu = pt.zcu;16490 const zcu = pt.zcu;
16624 const lhs_ty = sema.typeOf(lhs);16491 const lhs_ty = sema.typeOf(lhs);
16625 const rhs_ty = sema.typeOf(rhs);16492 const rhs_ty = sema.typeOf(rhs);
16626 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);16493 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
16627 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);16494 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
16628 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);16495 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1662916496
16630 if (lhs_zig_ty_tag == .pointer) {16497 if (lhs_zig_ty_tag == .pointer) {
...@@ -19028,9 +18895,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -19028,9 +18895,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
19028 defer child_block.instructions.deinit(sema.gpa);18895 defer child_block.instructions.deinit(sema.gpa);
1902918896
19030 const operand = try sema.resolveInlineBody(&child_block, body, inst);18897 const operand = try sema.resolveInlineBody(&child_block, body, inst);
19031 const operand_ty = sema.typeOf(operand);18898 return Air.internedToRef(sema.typeOf(operand).toIntern());
19032 if (operand_ty.isGenericPoison()) return error.GenericPoison;
19033 return Air.internedToRef(operand_ty.toIntern());
19034}18899}
1903518900
19036fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {18901fn 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...@@ -20100,7 +19965,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20100 }19965 }
20101 return err;19966 return err;
20102 };19967 };
20103 if (ty.isGenericPoison()) return error.GenericPoison;19968 assert(!ty.isGenericPoison());
20104 break :blk ty;19969 break :blk ty;
20105 };19970 };
2010619971
...@@ -20252,11 +20117,8 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is...@@ -20252,11 +20117,8 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
20252 const zcu = pt.zcu;20117 const zcu = pt.zcu;
20253 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;20118 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
20254 const src = block.nodeOffset(inst_data.src_node);20119 const src = block.nodeOffset(inst_data.src_node);
20255 const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {20120 // Generic poison means this is an untyped anonymous empty struct/array init
20256 // Generic poison means this is an untyped anonymous empty struct/array init20121 const ty_operand = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return .empty_tuple;
20257 error.GenericPoison => return .empty_tuple,
20258 else => |e| return e,
20259 };
20260 const init_ty = if (is_byref) ty: {20122 const init_ty = if (is_byref) ty: {
20261 const ptr_ty = ty_operand.optEuBaseType(zcu);20123 const ptr_ty = ty_operand.optEuBaseType(zcu);
20262 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction20124 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
...@@ -20410,12 +20272,9 @@ fn zirStructInit(...@@ -20410,12 +20272,9 @@ fn zirStructInit(
20410 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;20272 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
20411 const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node;20273 const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node;
20412 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;20274 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) {20275 const result_ty = try sema.resolveTypeOrPoison(block, src, first_field_type_extra.container_type) orelse {
20414 error.GenericPoison => {20276 // The type wasn't actually known, so treat this as an anon struct init.
20415 // 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);
20416 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
20417 },
20418 else => |e| return e,
20419 };20278 };
20420 const resolved_ty = result_ty.optEuBaseType(zcu);20279 const resolved_ty = result_ty.optEuBaseType(zcu);
20421 try resolved_ty.resolveLayout(pt);20280 try resolved_ty.resolveLayout(pt);
...@@ -20932,12 +20791,9 @@ fn zirArrayInit(...@@ -20932,12 +20791,9 @@ fn zirArrayInit(
20932 const args = sema.code.refSlice(extra.end, extra.data.operands_len);20791 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
20933 assert(args.len >= 2); // array_ty + at least one element20792 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) {20794 const result_ty = try sema.resolveTypeOrPoison(block, src, args[0]) orelse {
20936 error.GenericPoison => {20795 // The type wasn't actually known, so treat this as an anon array init.
20937 // The type wasn't actually known, so treat this as an anon array init.20796 return sema.arrayInitAnon(block, src, args[1..], is_ref);
20938 return sema.arrayInitAnon(block, src, args[1..], is_ref);
20939 },
20940 else => |e| return e,
20941 };20797 };
20942 const array_ty = result_ty.optEuBaseType(zcu);20798 const array_ty = result_ty.optEuBaseType(zcu);
20943 const is_tuple = array_ty.zigTypeTag(zcu) == .@"struct";20799 const is_tuple = array_ty.zigTypeTag(zcu) == .@"struct";
...@@ -21185,14 +21041,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -21185,14 +21041,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
21185 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;21041 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
21186 const ty_src = block.nodeOffset(inst_data.src_node);21042 const ty_src = block.nodeOffset(inst_data.src_node);
21187 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });21043 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) {21044 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;
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 };
21196 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);21045 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);
21197 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);21046 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
21198 const field_name = try ip.getOrPutString(sema.gpa, pt.tid, zir_field_name, .no_embedded_nulls);21047 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...@@ -24068,7 +23917,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
24068fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {23917fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
24069 const pt = sema.pt;23918 const pt = sema.pt;
24070 const zcu = pt.zcu;23919 const zcu = pt.zcu;
24071 switch (try ty.zigTypeTagOrPoison(zcu)) {23920 switch (ty.zigTypeTag(zcu)) {
24072 .comptime_int => return true,23921 .comptime_int => return true,
24073 .int => return false,23922 .int => return false,
24074 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),23923 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),
...@@ -24083,7 +23932,7 @@ fn checkInvalidPtrIntArithmetic(...@@ -24083,7 +23932,7 @@ fn checkInvalidPtrIntArithmetic(
24083) CompileError!void {23932) CompileError!void {
24084 const pt = sema.pt;23933 const pt = sema.pt;
24085 const zcu = pt.zcu;23934 const zcu = pt.zcu;
24086 switch (try ty.zigTypeTagOrPoison(zcu)) {23935 switch (ty.zigTypeTag(zcu)) {
24087 .pointer => switch (ty.ptrSize(zcu)) {23936 .pointer => switch (ty.ptrSize(zcu)) {
24088 .one, .slice => return,23937 .one, .slice => return,
24089 .many, .c => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"),23938 .many, .c => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"),
...@@ -24266,7 +24115,7 @@ fn checkAtomicPtrOperand(...@@ -24266,7 +24115,7 @@ fn checkAtomicPtrOperand(
24266 };24115 };
2426724116
24268 const ptr_ty = sema.typeOf(ptr);24117 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)) {
24270 .pointer => ptr_ty.ptrInfo(zcu),24119 .pointer => ptr_ty.ptrInfo(zcu),
24271 else => {24120 else => {
24272 const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data);24121 const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data);
...@@ -24307,11 +24156,11 @@ fn checkIntOrVector(...@@ -24307,11 +24156,11 @@ fn checkIntOrVector(
24307 const pt = sema.pt;24156 const pt = sema.pt;
24308 const zcu = pt.zcu;24157 const zcu = pt.zcu;
24309 const operand_ty = sema.typeOf(operand);24158 const operand_ty = sema.typeOf(operand);
24310 switch (try operand_ty.zigTypeTagOrPoison(zcu)) {24159 switch (operand_ty.zigTypeTag(zcu)) {
24311 .int => return operand_ty,24160 .int => return operand_ty,
24312 .vector => {24161 .vector => {
24313 const elem_ty = operand_ty.childType(zcu);24162 const elem_ty = operand_ty.childType(zcu);
24314 switch (try elem_ty.zigTypeTagOrPoison(zcu)) {24163 switch (elem_ty.zigTypeTag(zcu)) {
24315 .int => return elem_ty,24164 .int => return elem_ty,
24316 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{24165 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
24317 elem_ty.fmt(pt),24166 elem_ty.fmt(pt),
...@@ -24332,11 +24181,11 @@ fn checkIntOrVectorAllowComptime(...@@ -24332,11 +24181,11 @@ fn checkIntOrVectorAllowComptime(
24332) CompileError!Type {24181) CompileError!Type {
24333 const pt = sema.pt;24182 const pt = sema.pt;
24334 const zcu = pt.zcu;24183 const zcu = pt.zcu;
24335 switch (try operand_ty.zigTypeTagOrPoison(zcu)) {24184 switch (operand_ty.zigTypeTag(zcu)) {
24336 .int, .comptime_int => return operand_ty,24185 .int, .comptime_int => return operand_ty,
24337 .vector => {24186 .vector => {
24338 const elem_ty = operand_ty.childType(zcu);24187 const elem_ty = operand_ty.childType(zcu);
24339 switch (try elem_ty.zigTypeTagOrPoison(zcu)) {24188 switch (elem_ty.zigTypeTag(zcu)) {
24340 .int, .comptime_int => return elem_ty,24189 .int, .comptime_int => return elem_ty,
24341 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{24190 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
24342 elem_ty.fmt(pt),24191 elem_ty.fmt(pt),
...@@ -24406,8 +24255,8 @@ fn checkVectorizableBinaryOperands(...@@ -24406,8 +24255,8 @@ fn checkVectorizableBinaryOperands(
24406) CompileError!void {24255) CompileError!void {
24407 const pt = sema.pt;24256 const pt = sema.pt;
24408 const zcu = pt.zcu;24257 const zcu = pt.zcu;
24409 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(zcu);24258 const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu);
24410 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(zcu);24259 const rhs_zig_ty_tag = rhs_ty.zigTypeTag(zcu);
24411 if (lhs_zig_ty_tag != .vector and rhs_zig_ty_tag != .vector) return;24260 if (lhs_zig_ty_tag != .vector and rhs_zig_ty_tag != .vector) return;
2441224261
24413 const lhs_is_vector = switch (lhs_zig_ty_tag) {24262 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...@@ -24987,7 +24836,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
24987 const pred_uncoerced = try sema.resolveInst(extra.pred);24836 const pred_uncoerced = try sema.resolveInst(extra.pred);
24988 const pred_ty = sema.typeOf(pred_uncoerced);24837 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)) {
24991 .vector, .array => pred_ty.arrayLen(zcu),24840 .vector, .array => pred_ty.arrayLen(zcu),
24992 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),24841 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),
24993 };24842 };
...@@ -26306,7 +26155,9 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26306,7 +26155,9 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26306 break :cc .auto;26155 break :cc .auto;
26307 };26156 };
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: {
26310 const body_len = sema.code.extra[extra_index];26161 const body_len = sema.code.extra[extra_index];
26311 extra_index += 1;26162 extra_index += 1;
26312 const body = sema.code.bodySlice(extra_index, body_len);26163 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...@@ -26318,14 +26169,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26318 } else if (extra.data.bits.has_ret_ty_ref) blk: {26169 } else if (extra.data.bits.has_ret_ty_ref) blk: {
26319 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);26170 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
26320 extra_index += 1;26171 extra_index += 1;
26321 const ret_ty_air_ref = sema.resolveInst(ret_ty_ref) catch |err| switch (err) {26172 const ret_ty_air_ref = try sema.resolveInst(ret_ty_ref);
26322 error.GenericPoison => break :blk Type.generic_poison,26173 const ret_ty_val = try sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{ .simple = .function_ret_ty });
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 };
26329 break :blk ret_ty_val.toType();26174 break :blk ret_ty_val.toType();
26330 } else Type.void;26175 } else Type.void;
2633126176
...@@ -27625,7 +27470,7 @@ fn fieldVal(...@@ -27625,7 +27470,7 @@ fn fieldVal(
27625 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;27470 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;
27626 const child_type = val.toType();27471 const child_type = val.toType();
2762727472
27628 switch (try child_type.zigTypeTagOrPoison(zcu)) {27473 switch (child_type.zigTypeTag(zcu)) {
27629 .error_set => {27474 .error_set => {
27630 switch (ip.indexToKey(child_type.toIntern())) {27475 switch (ip.indexToKey(child_type.toIntern())) {
27631 .error_set_type => |error_set_type| blk: {27476 .error_set_type => |error_set_type| blk: {
...@@ -35180,7 +35025,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35180,7 +35025,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35180 if (struct_type.layout == .@"packed") {35025 if (struct_type.layout == .@"packed") {
35181 sema.backingIntType(struct_type) catch |err| switch (err) {35026 sema.backingIntType(struct_type) catch |err| switch (err) {
35182 error.OutOfMemory, error.AnalysisFail => |e| return e,35027 error.OutOfMemory, error.AnalysisFail => |e| return e,
35183 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,35028 error.ComptimeBreak, error.ComptimeReturn => unreachable,
35184 };35029 };
35185 return;35030 return;
35186 }35031 }
...@@ -35688,7 +35533,7 @@ pub fn resolveStructFieldTypes(...@@ -35688,7 +35533,7 @@ pub fn resolveStructFieldTypes(
3568835533
35689 sema.structFields(struct_type) catch |err| switch (err) {35534 sema.structFields(struct_type) catch |err| switch (err) {
35690 error.AnalysisFail, error.OutOfMemory => |e| return e,35535 error.AnalysisFail, error.OutOfMemory => |e| return e,
35691 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,35536 error.ComptimeBreak, error.ComptimeReturn => unreachable,
35692 };35537 };
35693}35538}
3569435539
...@@ -35717,7 +35562,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -35717,7 +35562,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
3571735562
35718 sema.structFieldInits(struct_type) catch |err| switch (err) {35563 sema.structFieldInits(struct_type) catch |err| switch (err) {
35719 error.AnalysisFail, error.OutOfMemory => |e| return e,35564 error.AnalysisFail, error.OutOfMemory => |e| return e,
35720 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,35565 error.ComptimeBreak, error.ComptimeReturn => unreachable,
35721 };35566 };
35722 struct_type.setHaveFieldInits(ip);35567 struct_type.setHaveFieldInits(ip);
35723}35568}
...@@ -35751,7 +35596,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -35751,7 +35596,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
35751 errdefer union_type.setStatus(ip, .none);35596 errdefer union_type.setStatus(ip, .none);
35752 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {35597 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {
35753 error.AnalysisFail, error.OutOfMemory => |e| return e,35598 error.AnalysisFail, error.OutOfMemory => |e| return e,
35754 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,35599 error.ComptimeBreak, error.ComptimeReturn => unreachable,
35755 };35600 };
35756 union_type.setStatus(ip, .have_field_types);35601 union_type.setStatus(ip, .have_field_types);
35757}35602}
...@@ -36078,9 +35923,6 @@ fn structFields(...@@ -36078,9 +35923,6 @@ fn structFields(
36078 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);35923 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
36079 break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref);35924 break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref);
36080 };35925 };
36081 if (field_ty.isGenericPoison()) {
36082 return error.GenericPoison;
36083 }
3608435926
36085 struct_type.field_types.get(ip)[field_i] = field_ty.toIntern();35927 struct_type.field_types.get(ip)[field_i] = field_ty.toIntern();
3608635928
...@@ -36523,10 +36365,6 @@ fn unionFields(...@@ -36523,10 +36365,6 @@ fn unionFields(
36523 else36365 else
36524 try sema.resolveType(&block_scope, type_src, field_type_ref);36366 try sema.resolveType(&block_scope, type_src, field_type_ref);
3652536367
36526 if (field_ty.isGenericPoison()) {
36527 return error.GenericPoison;
36528 }
36529
36530 if (explicit_tags_seen.len > 0) {36368 if (explicit_tags_seen.len > 0) {
36531 const tag_ty = union_type.tagTypeUnordered(ip);36369 const tag_ty = union_type.tagTypeUnordered(ip);
36532 const tag_info = ip.loadEnumType(tag_ty);36370 const tag_info = ip.loadEnumType(tag_ty);
...@@ -36779,7 +36617,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36779,7 +36617,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36779 .null_type => Value.null,36617 .null_type => Value.null,
36780 .undefined_type => Value.undef,36618 .undefined_type => Value.undef,
36781 .optional_noreturn_type => try pt.nullValue(ty),36619 .optional_noreturn_type => try pt.nullValue(ty),
36782 .generic_poison_type => error.GenericPoison,36620 .generic_poison_type => unreachable,
36783 .empty_tuple_type => Value.empty_tuple,36621 .empty_tuple_type => Value.empty_tuple,
36784 // values, not types36622 // values, not types
36785 .undef,36623 .undef,
...@@ -36797,7 +36635,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36797,7 +36635,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36797 .bool_true,36635 .bool_true,
36798 .bool_false,36636 .bool_false,
36799 .empty_tuple,36637 .empty_tuple,
36800 .generic_poison,
36801 // invalid36638 // invalid
36802 .none,36639 .none,
36803 => unreachable,36640 => unreachable,
...@@ -38095,7 +37932,6 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -38095,7 +37932,6 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
38095 ) catch |err| switch (err) {37932 ) catch |err| switch (err) {
38096 error.OutOfMemory => |e| return e,37933 error.OutOfMemory => |e| return e,
38097 error.AnalysisFail => unreachable,37934 error.AnalysisFail => unreachable,
38098 error.GenericPoison => unreachable,
38099 error.ComptimeReturn => unreachable,37935 error.ComptimeReturn => unreachable,
38100 error.ComptimeBreak => unreachable,37936 error.ComptimeBreak => unreachable,
38101 };37937 };
...@@ -38410,7 +38246,6 @@ pub fn resolveDeclaredEnum(...@@ -38410,7 +38246,6 @@ pub fn resolveDeclaredEnum(
38410 zir,38246 zir,
38411 body_end,38247 body_end,
38412 ) catch |err| switch (err) {38248 ) catch |err| switch (err) {
38413 error.GenericPoison => unreachable,
38414 error.ComptimeBreak => unreachable,38249 error.ComptimeBreak => unreachable,
38415 error.ComptimeReturn => unreachable,38250 error.ComptimeReturn => unreachable,
38416 error.OutOfMemory => |e| return e,38251 error.OutOfMemory => |e| return e,
src/Type.zig+5-8
...@@ -22,11 +22,7 @@ const SemaError = Zcu.SemaError;...@@ -22,11 +22,7 @@ const SemaError = Zcu.SemaError;
22ip_index: InternPool.Index,22ip_index: InternPool.Index,
2323
24pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId {24pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId {
25 return ty.zigTypeTagOrPoison(zcu) catch unreachable;25 return zcu.intern_pool.zigTypeTag(ty.toIntern());
26}
27
28pub fn zigTypeTagOrPoison(ty: Type, zcu: *const Zcu) error{GenericPoison}!std.builtin.TypeId {
29 return zcu.intern_pool.zigTypeTagOrPoison(ty.toIntern());
30}26}
3127
32pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId {28pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId {
...@@ -2503,14 +2499,16 @@ pub fn fnCallingConvention(ty: Type, zcu: *const Zcu) std.builtin.CallingConvent...@@ -2503,14 +2499,16 @@ pub fn fnCallingConvention(ty: Type, zcu: *const Zcu) std.builtin.CallingConvent
2503}2499}
25042500
2505pub fn isValidParamType(self: Type, zcu: *const Zcu) bool {2501pub 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)) {
2507 .@"opaque", .noreturn => false,2504 .@"opaque", .noreturn => false,
2508 else => true,2505 else => true,
2509 };2506 };
2510}2507}
25112508
2512pub fn isValidReturnType(self: Type, zcu: *const Zcu) bool {2509pub 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)) {
2514 .@"opaque" => false,2512 .@"opaque" => false,
2515 else => true,2513 else => true,
2516 };2514 };
...@@ -3784,7 +3782,6 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {...@@ -3784,7 +3782,6 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
3784 .bool_true => unreachable,3782 .bool_true => unreachable,
3785 .bool_false => unreachable,3783 .bool_false => unreachable,
3786 .empty_tuple => unreachable,3784 .empty_tuple => unreachable,
3787 .generic_poison => unreachable,
37883785
3789 else => switch (ty_ip.unwrap(ip).getTag(ip)) {3786 else => switch (ty_ip.unwrap(ip).getTag(ip)) {
3790 .type_struct,3787 .type_struct,
src/Value.zig-5
...@@ -3673,10 +3673,6 @@ pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 {...@@ -3673,10 +3673,6 @@ pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 {
3673 return first_byte;3673 return first_byte;
3674}3674}
36753675
3676pub fn isGenericPoison(val: Value) bool {
3677 return val.toIntern() == .generic_poison;
3678}
3679
3680pub fn typeOf(val: Value, zcu: *const Zcu) Type {3676pub fn typeOf(val: Value, zcu: *const Zcu) Type {
3681 return Type.fromInterned(zcu.intern_pool.typeOf(val.toIntern()));3677 return Type.fromInterned(zcu.intern_pool.typeOf(val.toIntern()));
3682}3678}
...@@ -3709,7 +3705,6 @@ pub const @"false": Value = .{ .ip_index = .bool_false };...@@ -3709,7 +3705,6 @@ pub const @"false": Value = .{ .ip_index = .bool_false };
3709pub const @"true": Value = .{ .ip_index = .bool_true };3705pub const @"true": Value = .{ .ip_index = .bool_true };
3710pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };3706pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };
37113707
3712pub const generic_poison: Value = .{ .ip_index = .generic_poison };
3713pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };3708pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
3714pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };3709pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
37153710
src/Zcu.zig-4
...@@ -2404,10 +2404,6 @@ pub const CompileError = error{...@@ -2404,10 +2404,6 @@ pub const CompileError = error{
2404 OutOfMemory,2404 OutOfMemory,
2405 /// When this is returned, the compile error for the failure has already been recorded.2405 /// When this is returned, the compile error for the failure has already been recorded.
2406 AnalysisFail,2406 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,
2411 /// In a comptime scope, a return instruction was encountered. This error is only seen when2407 /// In a comptime scope, a return instruction was encountered. This error is only seen when
2412 /// doing a comptime function call.2408 /// doing a comptime function call.
2413 ComptimeReturn,2409 ComptimeReturn,
src/Zcu/PerThread.zig-10
...@@ -627,7 +627,6 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized...@@ -627,7 +627,6 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
627 // TODO: same as for `ensureComptimeUnitUpToDate` etc627 // TODO: same as for `ensureComptimeUnitUpToDate` etc
628 return error.OutOfMemory;628 return error.OutOfMemory;
629 },629 },
630 error.GenericPoison => unreachable,
631 error.ComptimeReturn => unreachable,630 error.ComptimeReturn => unreachable,
632 error.ComptimeBreak => unreachable,631 error.ComptimeBreak => unreachable,
633 };632 };
...@@ -781,7 +780,6 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -781,7 +780,6 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
781 // for reporting OOM errors without allocating.780 // for reporting OOM errors without allocating.
782 return error.OutOfMemory;781 return error.OutOfMemory;
783 },782 },
784 error.GenericPoison => unreachable,
785 error.ComptimeReturn => unreachable,783 error.ComptimeReturn => unreachable,
786 error.ComptimeBreak => unreachable,784 error.ComptimeBreak => unreachable,
787 };785 };
...@@ -967,7 +965,6 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -967,7 +965,6 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
967 // for reporting OOM errors without allocating.965 // for reporting OOM errors without allocating.
968 return error.OutOfMemory;966 return error.OutOfMemory;
969 },967 },
970 error.GenericPoison => unreachable,
971 error.ComptimeReturn => unreachable,968 error.ComptimeReturn => unreachable,
972 error.ComptimeBreak => unreachable,969 error.ComptimeBreak => unreachable,
973 };970 };
...@@ -1168,7 +1165,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1168,7 +1165,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1168 };1165 };
11691166
1170 switch (nav_val.toIntern()) {1167 switch (nav_val.toIntern()) {
1171 .generic_poison => unreachable, // assertion failure
1172 .unreachable_value => unreachable, // assertion failure1168 .unreachable_value => unreachable, // assertion failure
1173 else => {},1169 else => {},
1174 }1170 }
...@@ -1347,7 +1343,6 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1347,7 +1343,6 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
1347 // for reporting OOM errors without allocating.1343 // for reporting OOM errors without allocating.
1348 return error.OutOfMemory;1344 return error.OutOfMemory;
1349 },1345 },
1350 error.GenericPoison => unreachable,
1351 error.ComptimeReturn => unreachable,1346 error.ComptimeReturn => unreachable,
1352 error.ComptimeBreak => unreachable,1347 error.ComptimeBreak => unreachable,
1353 };1348 };
...@@ -2665,7 +2660,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2665,7 +2660,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2665 runtime_param_index += 1;2660 runtime_param_index += 1;
26662661
2667 const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) {2662 const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) {
2668 error.GenericPoison => unreachable,
2669 error.ComptimeReturn => unreachable,2663 error.ComptimeReturn => unreachable,
2670 error.ComptimeBreak => unreachable,2664 error.ComptimeBreak => unreachable,
2671 else => |e| return e,2665 else => |e| return e,
...@@ -2698,7 +2692,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2698,7 +2692,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2698 inner_block.error_return_trace_index = error_return_trace_index;2692 inner_block.error_return_trace_index = error_return_trace_index;
26992693
2700 sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {2694 sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
2701 error.GenericPoison => unreachable,
2702 error.ComptimeReturn => unreachable,2695 error.ComptimeReturn => unreachable,
2703 else => |e| return e,2696 else => |e| return e,
2704 };2697 };
...@@ -2720,7 +2713,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2720,7 +2713,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2720 !sema.fn_ret_ty.isError(zcu))2713 !sema.fn_ret_ty.isError(zcu))
2721 {2714 {
2722 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {2715 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
2723 error.GenericPoison => unreachable,
2724 error.ComptimeReturn => unreachable,2716 error.ComptimeReturn => unreachable,
2725 error.ComptimeBreak => unreachable,2717 error.ComptimeBreak => unreachable,
2726 else => |e| return e,2718 else => |e| return e,
...@@ -2744,7 +2736,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2744,7 +2736,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2744 .base_node_inst = inner_block.src_base_inst,2736 .base_node_inst = inner_block.src_base_inst,
2745 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),2737 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),
2746 }, ies) catch |err| switch (err) {2738 }, ies) catch |err| switch (err) {
2747 error.GenericPoison => unreachable,
2748 error.ComptimeReturn => unreachable,2739 error.ComptimeReturn => unreachable,
2749 error.ComptimeBreak => unreachable,2740 error.ComptimeBreak => unreachable,
2750 else => |e| return e,2741 else => |e| return e,
...@@ -2763,7 +2754,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2763,7 +2754,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2763 // TODO: this can go away once we fix backends having to resolve `StackTrace`.2754 // TODO: this can go away once we fix backends having to resolve `StackTrace`.
2764 // The codegen timing guarantees that the parameter types will be populated.2755 // The codegen timing guarantees that the parameter types will be populated.
2765 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(0)) catch |err| switch (err) {2756 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(0)) catch |err| switch (err) {
2766 error.GenericPoison => unreachable,
2767 error.ComptimeReturn => unreachable,2757 error.ComptimeReturn => unreachable,
2768 error.ComptimeBreak => unreachable,2758 error.ComptimeBreak => unreachable,
2769 else => |e| return e,2759 else => |e| return e,
src/arch/wasm/CodeGen.zig-1
...@@ -3170,7 +3170,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3170,7 +3170,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3170 .null,3170 .null,
3171 .empty_tuple,3171 .empty_tuple,
3172 .@"unreachable",3172 .@"unreachable",
3173 .generic_poison,
3174 => unreachable, // non-runtime values3173 => unreachable, // non-runtime values
3175 .false, .true => return .{ .imm32 = switch (simple_value) {3174 .false, .true => return .{ .imm32 = switch (simple_value) {
3176 .false => 0,3175 .false => 0,
src/codegen.zig-1
...@@ -229,7 +229,6 @@ pub fn generateSymbol(...@@ -229,7 +229,6 @@ pub fn generateSymbol(
229 .void => unreachable, // non-runtime value229 .void => unreachable, // non-runtime value
230 .null => unreachable, // non-runtime value230 .null => unreachable, // non-runtime value
231 .@"unreachable" => unreachable, // non-runtime value231 .@"unreachable" => unreachable, // non-runtime value
232 .generic_poison => unreachable, // non-runtime value
233 .empty_tuple => return,232 .empty_tuple => return,
234 .false, .true => try code.append(gpa, switch (simple_value) {233 .false, .true => try code.append(gpa, switch (simple_value) {
235 .false => 0,234 .false => 0,
src/codegen/c.zig-1
...@@ -968,7 +968,6 @@ pub const DeclGen = struct {...@@ -968,7 +968,6 @@ pub const DeclGen = struct {
968 .null => unreachable,968 .null => unreachable,
969 .empty_tuple => unreachable,969 .empty_tuple => unreachable,
970 .@"unreachable" => unreachable,970 .@"unreachable" => unreachable,
971 .generic_poison => unreachable,
972971
973 .false => try writer.writeAll("false"),972 .false => try writer.writeAll("false"),
974 .true => try writer.writeAll("true"),973 .true => try writer.writeAll("true"),
src/codegen/c/Type.zig-1
...@@ -1451,7 +1451,6 @@ pub const Pool = struct {...@@ -1451,7 +1451,6 @@ pub const Pool = struct {
1451 .bool_true,1451 .bool_true,
1452 .bool_false,1452 .bool_false,
1453 .empty_tuple,1453 .empty_tuple,
1454 .generic_poison,
1455 .none,1454 .none,
1456 => unreachable,1455 => unreachable,
14571456
src/codegen/llvm.zig-2
...@@ -3372,7 +3372,6 @@ pub const Object = struct {...@@ -3372,7 +3372,6 @@ pub const Object = struct {
3372 .bool_true,3372 .bool_true,
3373 .bool_false,3373 .bool_false,
3374 .empty_tuple,3374 .empty_tuple,
3375 .generic_poison,
3376 .none,3375 .none,
3377 => unreachable,3376 => unreachable,
3378 else => switch (ip.indexToKey(t.toIntern())) {3377 else => switch (ip.indexToKey(t.toIntern())) {
...@@ -3923,7 +3922,6 @@ pub const Object = struct {...@@ -3923,7 +3922,6 @@ pub const Object = struct {
3923 .null => unreachable, // non-runtime value3922 .null => unreachable, // non-runtime value
3924 .empty_tuple => unreachable, // non-runtime value3923 .empty_tuple => unreachable, // non-runtime value
3925 .@"unreachable" => unreachable, // non-runtime value3924 .@"unreachable" => unreachable, // non-runtime value
3926 .generic_poison => unreachable, // non-runtime value
39273925
3928 .false => .false,3926 .false => .false,
3929 .true => .true,3927 .true => .true,
src/codegen/spirv.zig-1
...@@ -941,7 +941,6 @@ const NavGen = struct {...@@ -941,7 +941,6 @@ const NavGen = struct {
941 .null,941 .null,
942 .empty_tuple,942 .empty_tuple,
943 .@"unreachable",943 .@"unreachable",
944 .generic_poison,
945 => unreachable, // non-runtime values944 => unreachable, // non-runtime values
946945
947 .false, .true => break :cache try self.constBool(val.toBool(), repr),946 .false, .true => break :cache try self.constBool(val.toBool(), repr),
src/print_value.zig-1
...@@ -84,7 +84,6 @@ pub fn print(...@@ -84,7 +84,6 @@ pub fn print(
84 .simple_value => |simple_value| switch (simple_value) {84 .simple_value => |simple_value| switch (simple_value) {
85 .void => try writer.writeAll("{}"),85 .void => try writer.writeAll("{}"),
86 .empty_tuple => try writer.writeAll(".{}"),86 .empty_tuple => try writer.writeAll(".{}"),
87 .generic_poison => try writer.writeAll("(generic poison)"),
88 else => try writer.writeAll(@tagName(simple_value)),87 else => try writer.writeAll(@tagName(simple_value)),
89 },88 },
90 .variable => try writer.writeAll("(variable)"),89 .variable => try writer.writeAll("(variable)"),
src/print_zir.zig+9-3
...@@ -948,11 +948,13 @@ const Writer = struct {...@@ -948,11 +948,13 @@ const Writer = struct {
948 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {948 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
949 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;949 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
950 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);950 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);
952 try stream.print("\"{}\", ", .{952 try stream.print("\"{}\", ", .{
953 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),953 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
954 });954 });
955955
956 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
957
956 try self.writeBracedBody(stream, body);958 try self.writeBracedBody(stream, body);
957 try stream.writeAll(") ");959 try stream.writeAll(") ");
958 try self.writeSrcTok(stream, inst_data.src_tok);960 try self.writeSrcTok(stream, inst_data.src_tok);
...@@ -2283,7 +2285,7 @@ const Writer = struct {...@@ -2283,7 +2285,7 @@ const Writer = struct {
2283 var ret_ty_ref: Zir.Inst.Ref = .none;2285 var ret_ty_ref: Zir.Inst.Ref = .none;
2284 var ret_ty_body: []const Zir.Inst.Index = &.{};2286 var ret_ty_body: []const Zir.Inst.Index = &.{};
22852287
2286 switch (extra.data.ret_body_len) {2288 switch (extra.data.ret_ty.body_len) {
2287 0 => {2289 0 => {
2288 ret_ty_ref = .void_type;2290 ret_ty_ref = .void_type;
2289 },2291 },
...@@ -2292,7 +2294,7 @@ const Writer = struct {...@@ -2292,7 +2294,7 @@ const Writer = struct {
2292 extra_index += 1;2294 extra_index += 1;
2293 },2295 },
2294 else => {2296 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);
2296 extra_index += ret_ty_body.len;2298 extra_index += ret_ty_body.len;
2297 },2299 },
2298 }2300 }
...@@ -2314,6 +2316,7 @@ const Writer = struct {...@@ -2314,6 +2316,7 @@ const Writer = struct {
2314 &.{},2316 &.{},
2315 ret_ty_ref,2317 ret_ty_ref,
2316 ret_ty_body,2318 ret_ty_body,
2319 extra.data.ret_ty.is_generic,
23172320
2318 body,2321 body,
2319 inst_data.src_node,2322 inst_data.src_node,
...@@ -2373,6 +2376,7 @@ const Writer = struct {...@@ -2373,6 +2376,7 @@ const Writer = struct {
2373 cc_body,2376 cc_body,
2374 ret_ty_ref,2377 ret_ty_ref,
2375 ret_ty_body,2378 ret_ty_body,
2379 extra.data.bits.ret_ty_is_generic,
2376 body,2380 body,
2377 inst_data.src_node,2381 inst_data.src_node,
2378 src_locs,2382 src_locs,
...@@ -2532,12 +2536,14 @@ const Writer = struct {...@@ -2532,12 +2536,14 @@ const Writer = struct {
2532 cc_body: []const Zir.Inst.Index,2536 cc_body: []const Zir.Inst.Index,
2533 ret_ty_ref: Zir.Inst.Ref,2537 ret_ty_ref: Zir.Inst.Ref,
2534 ret_ty_body: []const Zir.Inst.Index,2538 ret_ty_body: []const Zir.Inst.Index,
2539 ret_ty_is_generic: bool,
2535 body: []const Zir.Inst.Index,2540 body: []const Zir.Inst.Index,
2536 src_node: i32,2541 src_node: i32,
2537 src_locs: Zir.Inst.Func.SrcLocs,2542 src_locs: Zir.Inst.Func.SrcLocs,
2538 noalias_bits: u32,2543 noalias_bits: u32,
2539 ) !void {2544 ) !void {
2540 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);2545 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2546 if (ret_ty_is_generic) try stream.writeAll("[generic] ");
2541 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);2547 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2542 try self.writeFlag(stream, "vargs, ", var_args);2548 try self.writeFlag(stream, "vargs, ", var_args);
2543 try self.writeFlag(stream, "inferror, ", inferred_error_set);2549 try self.writeFlag(stream, "inferror, ", inferred_error_set);
test/behavior/fn.zig+39
...@@ -672,3 +672,42 @@ test "function parameter self equality" {...@@ -672,3 +672,42 @@ test "function parameter self equality" {
672 try expect(!S.greaterThan(42));672 try expect(!S.greaterThan(42));
673 try expect(S.greaterThanOrEqual(42));673 try expect(S.greaterThanOrEqual(42));
674}674}
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 {...@@ -15,6 +15,6 @@ pub export fn entry() void {
15// error15// error
16//16//
17// :7:25: error: unable to resolve comptime value17// :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-known18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_165.C' must be comptime-known
19// :4:16: note: struct requires comptime because of this field19// :4:16: note: struct requires comptime because of this field
20// :4:16: note: types are not available at runtime20// :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 {...@@ -13,10 +13,8 @@ pub export fn entry2() void {
13}13}
1414
15// error15// error
16// backend=stage2
17// target=native
18//16//
19// :3:6: error: no field or member function named 'copy' in '[]const u8'17// :3:6: error: no field or member function named 'copy' in '[]const u8'
20// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'18// :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'
22// :12:6: note: struct declared here20// :12:6: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig+1-1
...@@ -6,6 +6,6 @@ export fn foo() void {...@@ -6,6 +6,6 @@ export fn foo() void {
66
7// error7// error
8//8//
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'
10// :3:16: note: struct declared here10// :3:16: note: struct declared here
11// :1:11: note: struct declared here11// :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 {...@@ -8,7 +8,7 @@ export fn entry() void {
8fn makeLlamas(count: usize) [count]u8 {}8fn makeLlamas(count: usize) [count]u8 {}
99
10// error10// error
11// target=native
12//11//
13// :8:30: error: unable to resolve comptime value12// :8:30: error: unable to resolve comptime value
14// :8:30: note: array length must be comptime-known13// :8:30: note: array length must be comptime-known
14// :2:31: note: called from here