authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2025-08-09 18:47:55-07:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-08-13 13:55:57+01:00
log8e02f9f70df97891aabfce615a1ef43434bc5c1f
tree4fae570ff474dbeb7cdafa3fd1840d3e71de3df7
parent6e90ce25364b02555a3ca46013f85b2e80e98705

sema: strip `@splat` operand result type before checking it


5 files changed, 33 insertions(+), 14 deletions(-)

lib/std/zig/AstGen.zig+2-3
...@@ -2697,7 +2697,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2697,7 +2697,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2697 .array_type_sentinel,2697 .array_type_sentinel,
2698 .elem_type,2698 .elem_type,
2699 .indexable_ptr_elem_type,2699 .indexable_ptr_elem_type,
2700 .vec_arr_elem_type,2700 .splat_op_result_ty,
2701 .vector_type,2701 .vector_type,
2702 .indexable_ptr_len,2702 .indexable_ptr_len,
2703 .anyframe_type,2703 .anyframe_type,
...@@ -9526,10 +9526,9 @@ fn builtinCall(...@@ -9526,10 +9526,9 @@ fn builtinCall(
9526 });9526 });
9527 return rvalue(gz, ri, result, node);9527 return rvalue(gz, ri, result, node);
9528 },9528 },
9529
9530 .splat => {9529 .splat => {
9531 const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);9530 const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
9532 const elem_type = try gz.addUnNode(.vec_arr_elem_type, result_type, node);9531 const elem_type = try gz.addUnNode(.splat_op_result_ty, result_type, node);
9533 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);9532 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
9534 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{9533 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
9535 .lhs = result_type,9534 .lhs = result_type,
lib/std/zig/Zir.zig+10-6
...@@ -273,9 +273,13 @@ pub const Inst = struct {...@@ -273,9 +273,13 @@ pub const Inst = struct {
273 /// element type. Emits a compile error if the type is not an indexable pointer.273 /// element type. Emits a compile error if the type is not an indexable pointer.
274 /// Uses the `un_node` field.274 /// Uses the `un_node` field.
275 indexable_ptr_elem_type,275 indexable_ptr_elem_type,
276 /// Given a vector or array type, returns its element type.276 /// Given a vector or array type, strips off any error unions or
277 /// optionals layered on top and returns its element type.
278 ///
279 /// `!?[N]T` -> `T`
280 ///
277 /// Uses the `un_node` field.281 /// Uses the `un_node` field.
278 vec_arr_elem_type,282 splat_op_result_ty,
279 /// Given a pointer to an indexable object, returns the len property. This is283 /// Given a pointer to an indexable object, returns the len property. This is
280 /// used by for loops. This instruction also emits a for-loop specific compile284 /// used by for loops. This instruction also emits a for-loop specific compile
281 /// error if the indexable object is not indexable.285 /// error if the indexable object is not indexable.
...@@ -1098,7 +1102,7 @@ pub const Inst = struct {...@@ -1098,7 +1102,7 @@ pub const Inst = struct {
1098 .vector_type,1102 .vector_type,
1099 .elem_type,1103 .elem_type,
1100 .indexable_ptr_elem_type,1104 .indexable_ptr_elem_type,
1101 .vec_arr_elem_type,1105 .splat_op_result_ty,
1102 .indexable_ptr_len,1106 .indexable_ptr_len,
1103 .anyframe_type,1107 .anyframe_type,
1104 .as_node,1108 .as_node,
...@@ -1395,7 +1399,7 @@ pub const Inst = struct {...@@ -1395,7 +1399,7 @@ pub const Inst = struct {
1395 .vector_type,1399 .vector_type,
1396 .elem_type,1400 .elem_type,
1397 .indexable_ptr_elem_type,1401 .indexable_ptr_elem_type,
1398 .vec_arr_elem_type,1402 .splat_op_result_ty,
1399 .indexable_ptr_len,1403 .indexable_ptr_len,
1400 .anyframe_type,1404 .anyframe_type,
1401 .as_node,1405 .as_node,
...@@ -1630,7 +1634,7 @@ pub const Inst = struct {...@@ -1630,7 +1634,7 @@ pub const Inst = struct {
1630 .vector_type = .pl_node,1634 .vector_type = .pl_node,
1631 .elem_type = .un_node,1635 .elem_type = .un_node,
1632 .indexable_ptr_elem_type = .un_node,1636 .indexable_ptr_elem_type = .un_node,
1633 .vec_arr_elem_type = .un_node,1637 .splat_op_result_ty = .un_node,
1634 .indexable_ptr_len = .un_node,1638 .indexable_ptr_len = .un_node,
1635 .anyframe_type = .un_node,1639 .anyframe_type = .un_node,
1636 .as_node = .pl_node,1640 .as_node = .pl_node,
...@@ -4173,7 +4177,7 @@ fn findTrackableInner(...@@ -4173,7 +4177,7 @@ fn findTrackableInner(
4173 .vector_type,4177 .vector_type,
4174 .elem_type,4178 .elem_type,
4175 .indexable_ptr_elem_type,4179 .indexable_ptr_elem_type,
4176 .vec_arr_elem_type,4180 .splat_op_result_ty,
4177 .indexable_ptr_len,4181 .indexable_ptr_len,
4178 .anyframe_type,4182 .anyframe_type,
4179 .as_node,4183 .as_node,
src/Sema.zig+7-4
...@@ -1197,7 +1197,7 @@ fn analyzeBodyInner(...@@ -1197,7 +1197,7 @@ fn analyzeBodyInner(
1197 .elem_val_imm => try sema.zirElemValImm(block, inst),1197 .elem_val_imm => try sema.zirElemValImm(block, inst),
1198 .elem_type => try sema.zirElemType(block, inst),1198 .elem_type => try sema.zirElemType(block, inst),
1199 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),1199 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),
1200 .vec_arr_elem_type => try sema.zirVecArrElemType(block, inst),1200 .splat_op_result_ty => try sema.zirSplatOpResultType(block, inst),
1201 .enum_literal => try sema.zirEnumLiteral(block, inst),1201 .enum_literal => try sema.zirEnumLiteral(block, inst),
1202 .decl_literal => try sema.zirDeclLiteral(block, inst, true),1202 .decl_literal => try sema.zirDeclLiteral(block, inst, true),
1203 .decl_literal_no_coerce => try sema.zirDeclLiteral(block, inst, false),1203 .decl_literal_no_coerce => try sema.zirDeclLiteral(block, inst, false),
...@@ -2139,7 +2139,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi...@@ -2139,7 +2139,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
2139 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;2139 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
2140 cur = bin.lhs;2140 cur = bin.lhs;
2141 },2141 },
2142 .indexable_ptr_elem_type, .vec_arr_elem_type => {2142 .indexable_ptr_elem_type, .splat_op_result_ty => {
2143 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;2143 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2144 cur = un_node.operand;2144 cur = un_node.operand;
2145 },2145 },
...@@ -7945,11 +7945,14 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -7945,11 +7945,14 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
7945 return Air.internedToRef(elem_ty.toIntern());7945 return Air.internedToRef(elem_ty.toIntern());
7946}7946}
79477947
7948fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7948fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7949 const pt = sema.pt;7949 const pt = sema.pt;
7950 const zcu = pt.zcu;7950 const zcu = pt.zcu;
7951 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;7951 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
7952 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;7952
7953 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
7954 const vec_ty = raw_ty.optEuBaseType(zcu);
7955
7953 switch (vec_ty.zigTypeTag(zcu)) {7956 switch (vec_ty.zigTypeTag(zcu)) {
7954 .array, .vector => {},7957 .array, .vector => {},
7955 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}),7958 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}),
src/print_zir.zig+1-1
...@@ -192,7 +192,7 @@ const Writer = struct {...@@ -192,7 +192,7 @@ const Writer = struct {
192 .alloc_comptime_mut,192 .alloc_comptime_mut,
193 .elem_type,193 .elem_type,
194 .indexable_ptr_elem_type,194 .indexable_ptr_elem_type,
195 .vec_arr_elem_type,195 .splat_op_result_ty,
196 .indexable_ptr_len,196 .indexable_ptr_len,
197 .anyframe_type,197 .anyframe_type,
198 .bit_not,198 .bit_not,
test/behavior/array.zig+13
...@@ -1112,3 +1112,16 @@ test "sentinel of runtime-known array initialization is populated" {...@@ -1112,3 +1112,16 @@ test "sentinel of runtime-known array initialization is populated" {
1112 try expect(elems[0] == 42);1112 try expect(elems[0] == 42);
1113 try expect(elems[1] == 123);1113 try expect(elems[1] == 123);
1114}1114}
1115
1116test "splat with an error union or optional result type" {
1117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1118
1119 const S = struct {
1120 fn doTest(T: type) !?T {
1121 return @splat(1);
1122 }
1123 };
1124
1125 _ = try S.doTest(@Vector(4, u32));
1126 _ = try S.doTest([4]u32);
1127}