authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-04-21 06:39:50-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-04-24 11:08:01-04:00
log57a8af2272f9116d43bcd9b3d8942ea58ccc1398
treef9db6b475348bbaceb6175580f2b019a0986c846
parent20e7929f6db4404ee343d993aa3d483e9a7ac71f

Sema: more restricted type support


4 files changed, 65 insertions(+), 73 deletions(-)

src/Sema.zig+53-64
...@@ -926,6 +926,12 @@ const ComptimeReason = union(enum) {...@@ -926,6 +926,12 @@ const ComptimeReason = union(enum) {
926 comptime_src: LazySrcLoc,926 comptime_src: LazySrcLoc,
927 },927 },
928928
929 /// Evaluating at comptime because we're coercing to a restricted type.
930 restricted_coercion: struct {
931 restricted_ty: Type,
932 unrestricted_ty: Type,
933 },
934
929 fn explain(reason: ComptimeReason, sema: *Sema, src: LazySrcLoc, err_msg: *Zcu.ErrorMsg) !void {935 fn explain(reason: ComptimeReason, sema: *Sema, src: LazySrcLoc, err_msg: *Zcu.ErrorMsg) !void {
930 switch (reason) {936 switch (reason) {
931 .simple => |simple| {937 .simple => |simple| {
...@@ -955,6 +961,12 @@ const ComptimeReason = union(enum) {...@@ -955,6 +961,12 @@ const ComptimeReason = union(enum) {
955 try sema.errNote(src, err_msg, "argument to comptime parameter must be comptime-known", .{});961 try sema.errNote(src, err_msg, "argument to comptime parameter must be comptime-known", .{});
956 try sema.errNote(cp.comptime_src, err_msg, "parameter declared comptime here", .{});962 try sema.errNote(cp.comptime_src, err_msg, "parameter declared comptime here", .{});
957 },963 },
964 .restricted_coercion => |rc| {
965 try sema.errNote(src, err_msg, "coercion to restricted type '{f}' from underlying type '{f}' must be comptime-known", .{
966 rc.restricted_ty.fmt(sema.pt), rc.unrestricted_ty.fmt(sema.pt),
967 });
968 try sema.addDeclaredHereNote(err_msg, rc.restricted_ty);
969 },
958 }970 }
959 }971 }
960};972};
...@@ -4156,7 +4168,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -4156,7 +4168,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4156 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;4168 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;
4157 const uncoerced_val = sema.resolveInst(extra.rhs);4169 const uncoerced_val = sema.resolveInst(extra.rhs);
4158 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val;4170 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val;
4159 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);4171 const ptr_ty = maybe_wrapped_ptr_ty.restrictedOptEuBaseType(zcu);
4160 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction4172 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
4161 const elem_ty = ptr_ty.childType(zcu);4173 const elem_ty = ptr_ty.childType(zcu);
4162 switch (ptr_ty.ptrSize(zcu)) {4174 switch (ptr_ty.ptrSize(zcu)) {
...@@ -4255,7 +4267,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4255,7 +4267,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4255 // In case of GenericPoison, we don't actually have a type, so this will be4267 // In case of GenericPoison, we don't actually have a type, so this will be
4256 // treated as an untyped address-of operator.4268 // treated as an untyped address-of operator.
4257 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;4269 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
4258 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {4270 if (ty_operand.restrictedOptEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
4259 return sema.failWithOwnedErrorMsg(block, msg: {4271 return sema.failWithOwnedErrorMsg(block, msg: {
4260 const msg = try sema.errMsg(src, "expected type '{f}', found pointer", .{ty_operand.fmt(pt)});4272 const msg = try sema.errMsg(src, "expected type '{f}', found pointer", .{ty_operand.fmt(pt)});
4261 errdefer msg.destroy(sema.gpa);4273 errdefer msg.destroy(sema.gpa);
...@@ -4287,7 +4299,7 @@ fn zirValidateArrayInitRefTy(...@@ -4287,7 +4299,7 @@ fn zirValidateArrayInitRefTy(
4287 const src = block.nodeOffset(pl_node.src_node);4299 const src = block.nodeOffset(pl_node.src_node);
4288 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;4300 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;
4289 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.ptr_ty) orelse return .generic_poison_type;4301 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.ptr_ty) orelse return .generic_poison_type;
4290 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);4302 const ptr_ty = maybe_wrapped_ptr_ty.restrictedOptEuBaseType(zcu);
4291 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction4303 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
4292 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) {4304 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) {
4293 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {4305 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
...@@ -4310,7 +4322,7 @@ fn zirValidateArrayInitRefTy(...@@ -4310,7 +4322,7 @@ fn zirValidateArrayInitRefTy(
4310 // The actual array type is unknown, which we represent with a generic poison.4322 // The actual array type is unknown, which we represent with a generic poison.
4311 return .generic_poison_type;4323 return .generic_poison_type;
4312 }4324 }
4313 const arr_ty = ret_ty.optEuBaseType(zcu);4325 const arr_ty = ret_ty.restrictedOptEuBaseType(zcu);
4314 try sema.validateArrayInitTy(block, src, src, extra.elem_count, arr_ty);4326 try sema.validateArrayInitTy(block, src, src, extra.elem_count, arr_ty);
4315 return Air.internedToRef(ret_ty.toIntern());4327 return Air.internedToRef(ret_ty.toIntern());
4316}4328}
...@@ -4329,7 +4341,7 @@ fn zirValidateArrayInitTy(...@@ -4329,7 +4341,7 @@ fn zirValidateArrayInitTy(
4329 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;4341 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
4330 // It's okay for the type to be poison: this will result in an anonymous array init.4342 // It's okay for the type to be poison: this will result in an anonymous array init.
4331 const ty = try sema.resolveTypeOrPoison(block, ty_src, extra.ty) orelse return;4343 const ty = try sema.resolveTypeOrPoison(block, ty_src, extra.ty) orelse return;
4332 const arr_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;4344 const arr_ty = if (is_result_ty) ty.restrictedOptEuBaseType(zcu) else ty;
4333 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);4345 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);
4334}4346}
43354347
...@@ -4388,7 +4400,7 @@ fn zirValidateStructInitTy(...@@ -4388,7 +4400,7 @@ fn zirValidateStructInitTy(
4388 const src = block.nodeOffset(inst_data.src_node);4400 const src = block.nodeOffset(inst_data.src_node);
4389 // It's okay for the type to be poison: this will result in an anonymous struct init.4401 // It's okay for the type to be poison: this will result in an anonymous struct init.
4390 const ty = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return;4402 const ty = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return;
4391 const struct_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty;4403 const struct_ty = if (is_result_ty) ty.restrictedOptEuBaseType(zcu) else ty;
43924404
4393 switch (struct_ty.zigTypeTag(zcu)) {4405 switch (struct_ty.zigTypeTag(zcu)) {
4394 .@"struct", .@"union" => return,4406 .@"struct", .@"union" => return,
...@@ -4414,7 +4426,7 @@ fn zirValidatePtrStructInit(...@@ -4414,7 +4426,7 @@ fn zirValidatePtrStructInit(
4414 const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node;4426 const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node;
4415 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4427 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4416 const object_ptr = sema.resolveInst(field_ptr_extra.lhs);4428 const object_ptr = sema.resolveInst(field_ptr_extra.lhs);
4417 const agg_ty = sema.typeOf(object_ptr).childType(zcu).optEuBaseType(zcu);4429 const agg_ty = sema.typeOf(object_ptr).childType(zcu).restrictedOptEuBaseType(zcu);
4418 switch (agg_ty.zigTypeTag(zcu)) {4430 switch (agg_ty.zigTypeTag(zcu)) {
4419 .@"struct" => return sema.validateStructInit(4431 .@"struct" => return sema.validateStructInit(
4420 block,4432 block,
...@@ -4580,7 +4592,7 @@ fn zirValidatePtrArrayInit(...@@ -4580,7 +4592,7 @@ fn zirValidatePtrArrayInit(
4580 const first_elem_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node;4592 const first_elem_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node;
4581 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;4593 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;
4582 const array_ptr = sema.resolveInst(elem_ptr_extra.ptr);4594 const array_ptr = sema.resolveInst(elem_ptr_extra.ptr);
4583 const array_ty = sema.typeOf(array_ptr).childType(zcu).optEuBaseType(zcu);4595 const array_ty = sema.typeOf(array_ptr).childType(zcu).restrictedOptEuBaseType(zcu);
4584 const array_len = array_ty.arrayLen(zcu);4596 const array_len = array_ty.arrayLen(zcu);
45854597
4586 // Analagously to `validateStructInit`, our job is to handle default fields; either emitting AIR4598 // Analagously to `validateStructInit`, our job is to handle default fields; either emitting AIR
...@@ -4705,21 +4717,14 @@ fn failWithBadMemberAccess(...@@ -4705,21 +4717,14 @@ fn failWithBadMemberAccess(
4705 const pt = sema.pt;4717 const pt = sema.pt;
4706 const zcu = pt.zcu;4718 const zcu = pt.zcu;
4707 const ip = &zcu.intern_pool;4719 const ip = &zcu.intern_pool;
4708 const kw_name = switch (agg_ty.zigTypeTag(zcu)) {
4709 .@"union" => "union",
4710 .@"struct" => "struct",
4711 .@"opaque" => "opaque",
4712 .@"enum" => "enum",
4713 else => unreachable,
4714 };
4715 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {4720 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {
4716 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{4721 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
4717 agg_ty.fmt(pt), field_name.fmt(ip),4722 agg_ty.fmt(pt), field_name.fmt(ip),
4718 });4723 });
4719 };4724 };
47204725
4721 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{4726 return sema.fail(block, field_src, "{t} '{f}' has no member named '{f}'", .{
4722 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),4727 agg_ty.zigTypeTag(zcu), agg_ty.fmt(pt), field_name.fmt(ip),
4723 });4728 });
4724}4729}
47254730
...@@ -4777,13 +4782,7 @@ fn failWithBadUnionFieldAccess(...@@ -4777,13 +4782,7 @@ fn failWithBadUnionFieldAccess(
4777pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void {4782pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void {
4778 const zcu = sema.pt.zcu;4783 const zcu = sema.pt.zcu;
4779 const src_loc = decl_ty.srcLocOrNull(zcu) orelse return;4784 const src_loc = decl_ty.srcLocOrNull(zcu) orelse return;
4780 const category = switch (decl_ty.zigTypeTag(zcu)) {4785 const category = if (zcu.intern_pool.isRestrictedType(decl_ty.toIntern())) "restricted type" else @tagName(decl_ty.zigTypeTag(zcu));
4781 .@"union" => "union",
4782 .@"struct" => "struct",
4783 .@"enum" => "enum",
4784 .@"opaque" => "opaque",
4785 else => unreachable,
4786 };
4787 try sema.errNote(src_loc, parent, "{s} declared here", .{category});4786 try sema.errNote(src_loc, parent, "{s} declared here", .{category});
4788}4787}
47894788
...@@ -7420,7 +7419,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -7420,7 +7419,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
7420 const zcu = pt.zcu;7419 const zcu = pt.zcu;
7421 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;7420 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
7422 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type;7421 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type;
7423 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu);7422 const indexable_ty = maybe_wrapped_indexable_ty.restrictedOptEuBaseType(zcu);
7424 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction7423 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction
7425 const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) {7424 const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) {
7426 .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu),7425 .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu),
...@@ -7434,7 +7433,7 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -7434,7 +7433,7 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
7434 const zcu = pt.zcu;7433 const zcu = pt.zcu;
7435 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;7434 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
7436 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;7435 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
7437 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu);7436 const ptr_ty = maybe_wrapped_ptr_ty.restrictedOptEuBaseType(zcu);
7438 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction7437 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
7439 const elem_ty = ptr_ty.childType(zcu);7438 const elem_ty = ptr_ty.childType(zcu);
7440 if (elem_ty.toIntern() == .anyopaque_type) {7439 if (elem_ty.toIntern() == .anyopaque_type) {
...@@ -7465,7 +7464,7 @@ fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -7465,7 +7464,7 @@ fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
7465 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;7464 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
74667465
7467 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;7466 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
7468 const vec_ty = raw_ty.optEuBaseType(zcu);7467 const vec_ty = raw_ty.restrictedOptEuBaseType(zcu);
74697468
7470 switch (vec_ty.zigTypeTag(zcu)) {7469 switch (vec_ty.zigTypeTag(zcu)) {
7471 .array, .vector => {},7470 .array, .vector => {},
...@@ -9451,13 +9450,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9451,13 +9450,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9451 return sema.failWithOwnedErrorMsg(block, msg);9450 return sema.failWithOwnedErrorMsg(block, msg);
9452 },9451 },
9453 .@"struct", .@"union" => if (dest_ty.containerLayout(zcu) == .auto) {9452 .@"struct", .@"union" => if (dest_ty.containerLayout(zcu) == .auto) {
9454 const container = switch (dest_ty.zigTypeTag(zcu)) {9453 return sema.fail(block, src, "cannot @bitCast to '{f}'; {t} does not have a guaranteed in-memory layout", .{
9455 .@"struct" => "struct",9454 dest_ty.fmt(pt), dest_ty.zigTypeTag(zcu),
9456 .@"union" => "union",
9457 else => unreachable,
9458 };
9459 return sema.fail(block, src, "cannot @bitCast to '{f}'; {s} does not have a guaranteed in-memory layout", .{
9460 dest_ty.fmt(pt), container,
9461 });9455 });
9462 },9456 },
9463 .array => {9457 .array => {
...@@ -9525,13 +9519,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9525,13 +9519,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9525 return sema.failWithOwnedErrorMsg(block, msg);9519 return sema.failWithOwnedErrorMsg(block, msg);
9526 },9520 },
9527 .@"struct", .@"union" => if (operand_ty.containerLayout(zcu) == .auto) {9521 .@"struct", .@"union" => if (operand_ty.containerLayout(zcu) == .auto) {
9528 const container = switch (operand_ty.zigTypeTag(zcu)) {9522 return sema.fail(block, operand_src, "cannot @bitCast from '{f}'; {t} does not have a guaranteed in-memory layout", .{
9529 .@"struct" => "struct",9523 operand_ty.fmt(pt), operand_ty.zigTypeTag(zcu),
9530 .@"union" => "union",
9531 else => unreachable,
9532 };
9533 return sema.fail(block, operand_src, "cannot @bitCast from '{f}'; {s} does not have a guaranteed in-memory layout", .{
9534 operand_ty.fmt(pt), container,
9535 });9524 });
9536 },9525 },
9537 .array => {9526 .array => {
...@@ -17857,7 +17846,7 @@ fn zirRetImplicit(...@@ -17857,7 +17846,7 @@ fn zirRetImplicit(
1785717846
17858 const operand = sema.resolveInst(inst_data.operand);17847 const operand = sema.resolveInst(inst_data.operand);
17859 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });17848 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
17860 const base_tag = sema.fn_ret_ty.optEuBaseType(zcu).zigTypeTag(zcu);17849 const base_tag = sema.fn_ret_ty.restrictedOptEuBaseType(zcu).zigTypeTag(zcu);
17861 if (base_tag == .noreturn) {17850 if (base_tag == .noreturn) {
17862 const msg = msg: {17851 const msg = msg: {
17863 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{17852 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{
...@@ -18372,7 +18361,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is...@@ -18372,7 +18361,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
18372 };18361 };
1837318362
18374 const init_ty = if (is_byref) ty: {18363 const init_ty = if (is_byref) ty: {
18375 const ptr_ty = ty_operand.optEuBaseType(zcu);18364 const ptr_ty = ty_operand.restrictedOptEuBaseType(zcu);
18376 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction18365 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
18377 switch (ptr_ty.ptrSize(zcu)) {18366 switch (ptr_ty.ptrSize(zcu)) {
18378 // Use a zero-length array for a slice or many-ptr result18367 // Use a zero-length array for a slice or many-ptr result
...@@ -18409,7 +18398,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is...@@ -18409,7 +18398,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
1840918398
18410 try sema.ensureLayoutResolved(init_ty, src, .init);18399 try sema.ensureLayoutResolved(init_ty, src, .init);
1841118400
18412 const obj_ty = init_ty.optEuBaseType(zcu);18401 const obj_ty = init_ty.restrictedOptEuBaseType(zcu);
1841318402
18414 const empty_ref = switch (obj_ty.zigTypeTag(zcu)) {18403 const empty_ref = switch (obj_ty.zigTypeTag(zcu)) {
18415 .@"struct" => try sema.structInitEmpty(block, obj_ty, src, src),18404 .@"struct" => try sema.structInitEmpty(block, obj_ty, src, src),
...@@ -18527,7 +18516,7 @@ fn zirStructInit(...@@ -18527,7 +18516,7 @@ fn zirStructInit(
18527 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);18516 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
18528 };18517 };
18529 try sema.ensureLayoutResolved(result_ty, src, .init);18518 try sema.ensureLayoutResolved(result_ty, src, .init);
18530 const resolved_ty = result_ty.optEuBaseType(zcu);18519 const resolved_ty = result_ty.restrictedOptEuBaseType(zcu);
1853118520
18532 if (resolved_ty.zigTypeTag(zcu) == .@"struct") {18521 if (resolved_ty.zigTypeTag(zcu) == .@"struct") {
18533 // This logic must be synchronized with that in `zirStructInitEmpty`.18522 // This logic must be synchronized with that in `zirStructInitEmpty`.
...@@ -19065,7 +19054,7 @@ fn zirArrayInit(...@@ -19065,7 +19054,7 @@ fn zirArrayInit(
19065 // The type wasn't actually known, so treat this as an anon array init.19054 // The type wasn't actually known, so treat this as an anon array init.
19066 return sema.arrayInitAnon(block, src, args[1..], is_ref);19055 return sema.arrayInitAnon(block, src, args[1..], is_ref);
19067 };19056 };
19068 const array_ty = result_ty.optEuBaseType(zcu);19057 const array_ty = result_ty.restrictedOptEuBaseType(zcu);
19069 const is_tuple = array_ty.zigTypeTag(zcu) == .@"struct";19058 const is_tuple = array_ty.zigTypeTag(zcu) == .@"struct";
19070 const sentinel_val = array_ty.sentinel(zcu);19059 const sentinel_val = array_ty.sentinel(zcu);
1907119060
...@@ -19330,7 +19319,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -19330,7 +19319,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
19330 const ty_src = block.nodeOffset(inst_data.src_node);19319 const ty_src = block.nodeOffset(inst_data.src_node);
19331 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });19320 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });
19332 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;19321 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;
19333 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);19322 const aggregate_ty = wrapped_aggregate_ty.restrictedOptEuBaseType(zcu);
19334 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);19323 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
19335 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls);19324 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls);
19336 try sema.ensureLayoutResolved(aggregate_ty, ty_src, .init);19325 try sema.ensureLayoutResolved(aggregate_ty, ty_src, .init);
...@@ -20871,7 +20860,7 @@ fn zirRoundCast(...@@ -20871,7 +20860,7 @@ fn zirRoundCast(
20871 .truncate => return sema.unaryMath(block, operand_src, operand, .trunc_float, Value.trunc),20860 .truncate => return sema.unaryMath(block, operand_src, operand, .trunc_float, Value.trunc),
20872 // zig fmt: on20861 // zig fmt: on
20873 .exact => unreachable,20862 .exact => unreachable,
20874 }).optEuBaseType(zcu);20863 }).restrictedOptEuBaseType(zcu);
2087520864
20876 const operand_ty = sema.typeOf(operand);20865 const operand_ty = sema.typeOf(operand);
2087720866
...@@ -25081,7 +25070,7 @@ fn zirFloatOpResultType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended....@@ -25081,7 +25070,7 @@ fn zirFloatOpResultType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.
25081 const operand_src = block.builtinCallArgSrc(extra.node, 0);25070 const operand_src = block.builtinCallArgSrc(extra.node, 0);
2508225071
25083 const raw_ty = try sema.resolveTypeOrPoison(block, operand_src, extra.operand) orelse return .generic_poison_type;25072 const raw_ty = try sema.resolveTypeOrPoison(block, operand_src, extra.operand) orelse return .generic_poison_type;
25084 const float_ty = raw_ty.optEuBaseType(zcu);25073 const float_ty = raw_ty.restrictedOptEuBaseType(zcu);
2508525074
25086 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {25075 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {
25087 .float, .comptime_float => {},25076 .float, .comptime_float => {},
...@@ -25106,7 +25095,7 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa...@@ -25106,7 +25095,7 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
25106 return .generic_poison_type;25095 return .generic_poison_type;
25107 };25096 };
2510825097
25109 const float_ty = dest_ty.optEuBaseType(zcu);25098 const float_ty = dest_ty.restrictedOptEuBaseType(zcu);
25110 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {25099 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {
25111 .float, .comptime_float => return .fromType(float_ty),25100 .float, .comptime_float => return .fromType(float_ty),
25112 else => return .comptime_float_type,25101 else => return .comptime_float_type,
...@@ -27479,21 +27468,21 @@ fn coerceExtra(...@@ -27479,21 +27468,21 @@ fn coerceExtra(
27479 if (dest_ty.eql(inst_ty, zcu))27468 if (dest_ty.eql(inst_ty, zcu))
27480 return inst;27469 return inst;
2748127470
27482 const maybe_inst_val = sema.resolveValue(inst);
27483
27484 // Restricted coercions27471 // Restricted coercions
27485 if (maybe_inst_val != null) {27472 if (dest_ty.unrestrictedType(zcu)) |dest_unrestricted_ty| {
27486 if (dest_ty.unrestrictedType(zcu)) |dest_unrestricted_ty| {27473 const dest_unrestricted = try sema.coerceExtra(block, dest_unrestricted_ty, inst, inst_src, opts);
27487 if (sema.resolveValue(try sema.coerceExtra(block, dest_unrestricted_ty, inst, inst_src, opts))) |dest_unrestricted_val| {27474 const dest_unrestricted_val = try sema.resolveConstValue(block, inst_src, dest_unrestricted, .{ .restricted_coercion = .{
27488 return .fromIntern(try pt.intern(if (dest_unrestricted_val.isUndef(zcu)) .{27475 .restricted_ty = dest_ty,
27489 .undef = dest_ty.toIntern(),27476 .unrestricted_ty = dest_unrestricted_ty,
27490 } else .{ .restricted_value = .{27477 } });
27491 .ty = dest_ty.toIntern(),27478 return .fromIntern(try pt.intern(if (dest_unrestricted_val.isUndef(zcu)) .{
27492 .unrestricted_value = dest_unrestricted_val.toIntern(),27479 .undef = dest_ty.toIntern(),
27493 } }));27480 } else .{ .restricted_value = .{
27494 }27481 .ty = dest_ty.toIntern(),
27495 }27482 .unrestricted_value = dest_unrestricted_val.toIntern(),
27483 } }));
27496 }27484 }
27485 const maybe_inst_val = sema.resolveValue(inst);
27497 if (inst_ty.unrestrictedType(zcu)) |inst_unrestricted_ty| {27486 if (inst_ty.unrestrictedType(zcu)) |inst_unrestricted_ty| {
27498 const unrestricted_inst: Air.Inst.Ref = if (maybe_inst_val) |inst_val|27487 const unrestricted_inst: Air.Inst.Ref = if (maybe_inst_val) |inst_val|
27499 .fromIntern(ip.indexToKey(inst_val.toIntern()).restricted_value.unrestricted_value)27488 .fromIntern(ip.indexToKey(inst_val.toIntern()).restricted_value.unrestricted_value)
...@@ -28268,7 +28257,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -28268,7 +28257,7 @@ const InMemoryCoercionResult = union(enum) {
28268 for ([_]Type{ pair.actual, pair.wanted }) |restricted_type| {28257 for ([_]Type{ pair.actual, pair.wanted }) |restricted_type| {
28269 try sema.addDeclaredHereNote(msg, restricted_type);28258 try sema.addDeclaredHereNote(msg, restricted_type);
28270 const unrestricted_type = restricted_type.unrestrictedType(pt.zcu) orelse continue;28259 const unrestricted_type = restricted_type.unrestrictedType(pt.zcu) orelse continue;
28271 try sema.errNote(src, msg, "restricted type '{f}' is not guaranteed to have the same representation as its unrestricted type '{f}'", .{28260 try sema.errNote(src, msg, "restricted type '{f}' has a different representation than unrestricted type '{f}'", .{
28272 restricted_type.fmt(pt), unrestricted_type.fmt(pt),28261 restricted_type.fmt(pt), unrestricted_type.fmt(pt),
28273 });28262 });
28274 }28263 }
src/Type.zig+10-7
...@@ -2701,15 +2701,18 @@ pub fn isTuple(ty: Type, zcu: *const Zcu) bool {...@@ -2701,15 +2701,18 @@ pub fn isTuple(ty: Type, zcu: *const Zcu) bool {
2701 };2701 };
2702}2702}
27032703
2704/// Traverses optional child types and error union payloads until the type is neither of those.2704/// Traverses restricted unrestricted types, optional child types, and error union payloads until the type is neither of those.
2705/// For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.2705/// For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
2706pub fn optEuBaseType(ty: Type, zcu: *const Zcu) Type {2706pub fn restrictedOptEuBaseType(ty: Type, zcu: *const Zcu) Type {
2707 var cur = ty;2707 var cur = ty;
2708 while (true) switch (cur.zigTypeTag(zcu)) {2708 while (true) {
2709 .optional => cur = cur.optionalChild(zcu),2709 cur = ty.unrestrictedType(zcu) orelse cur;
2710 .error_union => cur = cur.errorUnionPayload(zcu),2710 switch (cur.zigTypeTag(zcu)) {
2711 else => return cur,2711 .optional => cur = cur.optionalChild(zcu),
2712 };2712 .error_union => cur = cur.errorUnionPayload(zcu),
2713 else => return cur,
2714 }
2715 }
2713}2716}
27142717
2715pub fn toUnsigned(ty: Type, pt: Zcu.PerThread) !Type {2718pub fn toUnsigned(ty: Type, pt: Zcu.PerThread) !Type {
src/link/Coff.zig+1-1
...@@ -2474,7 +2474,7 @@ pub fn printNode(...@@ -2474,7 +2474,7 @@ pub fn printNode(
2474 val.fmtValue(.{ .zcu = zcu, .tid = tid }),2474 val.fmtValue(.{ .zcu = zcu, .tid = tid }),
2475 });2475 });
2476 },2476 },
2477 inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{2477 inline .lazy_code, .lazy_const_data, .lazy_deferred_const_data => |lmi| try w.print("({f})", .{
2478 Value.fromInterned(lmi.lazySymbol(coff).key).fmtValue(2478 Value.fromInterned(lmi.lazySymbol(coff).key).fmtValue(
2479 .{ .zcu = coff.base.comp.zcu.?, .tid = tid },2479 .{ .zcu = coff.base.comp.zcu.?, .tid = tid },
2480 ),2480 ),
src/link/Elf2.zig+1-1
...@@ -3837,7 +3837,7 @@ pub fn printNode(...@@ -3837,7 +3837,7 @@ pub fn printNode(
3837 val.fmtValue(.{ .zcu = zcu, .tid = tid }),3837 val.fmtValue(.{ .zcu = zcu, .tid = tid }),
3838 });3838 });
3839 },3839 },
3840 inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{3840 inline .lazy_code, .lazy_const_data, .lazy_deferred_const_data => |lmi| try w.print("({f})", .{
3841 Value.fromInterned(lmi.lazySymbol(elf).key).fmtValue(3841 Value.fromInterned(lmi.lazySymbol(elf).key).fmtValue(
3842 .{ .zcu = elf.base.comp.zcu.?, .tid = tid },3842 .{ .zcu = elf.base.comp.zcu.?, .tid = tid },
3843 ),3843 ),