diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 99c80816ad..c208661359 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -2697,7 +2697,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .array_type_sentinel, .elem_type, .indexable_ptr_elem_type, - .vec_arr_elem_type, + .splat_op_result_ty, .vector_type, .indexable_ptr_len, .anyframe_type, @@ -9526,10 +9526,9 @@ fn builtinCall( }); return rvalue(gz, ri, result, node); }, - .splat => { const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name); - const elem_type = try gz.addUnNode(.vec_arr_elem_type, result_type, node); + const elem_type = try gz.addUnNode(.splat_op_result_ty, result_type, node); const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ .lhs = result_type, diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index f6781a74a2..b00d0d78c9 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -273,9 +273,13 @@ pub const Inst = struct { /// element type. Emits a compile error if the type is not an indexable pointer. /// Uses the `un_node` field. indexable_ptr_elem_type, - /// Given a vector or array type, returns its element type. + /// Given a vector or array type, strips off any error unions or + /// optionals layered on top and returns its element type. + /// + /// `!?[N]T` -> `T` + /// /// Uses the `un_node` field. - vec_arr_elem_type, + splat_op_result_ty, /// Given a pointer to an indexable object, returns the len property. This is /// used by for loops. This instruction also emits a for-loop specific compile /// error if the indexable object is not indexable. @@ -1098,7 +1102,7 @@ pub const Inst = struct { .vector_type, .elem_type, .indexable_ptr_elem_type, - .vec_arr_elem_type, + .splat_op_result_ty, .indexable_ptr_len, .anyframe_type, .as_node, @@ -1395,7 +1399,7 @@ pub const Inst = struct { .vector_type, .elem_type, .indexable_ptr_elem_type, - .vec_arr_elem_type, + .splat_op_result_ty, .indexable_ptr_len, .anyframe_type, .as_node, @@ -1630,7 +1634,7 @@ pub const Inst = struct { .vector_type = .pl_node, .elem_type = .un_node, .indexable_ptr_elem_type = .un_node, - .vec_arr_elem_type = .un_node, + .splat_op_result_ty = .un_node, .indexable_ptr_len = .un_node, .anyframe_type = .un_node, .as_node = .pl_node, @@ -4173,7 +4177,7 @@ fn findTrackableInner( .vector_type, .elem_type, .indexable_ptr_elem_type, - .vec_arr_elem_type, + .splat_op_result_ty, .indexable_ptr_len, .anyframe_type, .as_node, diff --git a/src/Sema.zig b/src/Sema.zig index 583d17d00b..378bcaee8b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1197,7 +1197,7 @@ fn analyzeBodyInner( .elem_val_imm => try sema.zirElemValImm(block, inst), .elem_type => try sema.zirElemType(block, inst), .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst), - .vec_arr_elem_type => try sema.zirVecArrElemType(block, inst), + .splat_op_result_ty => try sema.zirSplatOpResultType(block, inst), .enum_literal => try sema.zirEnumLiteral(block, inst), .decl_literal => try sema.zirDeclLiteral(block, inst, true), .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 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin; cur = bin.lhs; }, - .indexable_ptr_elem_type, .vec_arr_elem_type => { + .indexable_ptr_elem_type, .splat_op_result_ty => { const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; cur = un_node.operand; }, @@ -7945,11 +7945,14 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com return Air.internedToRef(elem_ty.toIntern()); } -fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; + + const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; + const vec_ty = raw_ty.optEuBaseType(zcu); + switch (vec_ty.zigTypeTag(zcu)) { .array, .vector => {}, else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}), diff --git a/src/print_zir.zig b/src/print_zir.zig index 846d2ac6b2..16bf959c2e 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -192,7 +192,7 @@ const Writer = struct { .alloc_comptime_mut, .elem_type, .indexable_ptr_elem_type, - .vec_arr_elem_type, + .splat_op_result_ty, .indexable_ptr_len, .anyframe_type, .bit_not, diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 2e776d4653..741e9505b0 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -1112,3 +1112,16 @@ test "sentinel of runtime-known array initialization is populated" { try expect(elems[0] == 42); try expect(elems[1] == 123); } + +test "splat with an error union or optional result type" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + + const S = struct { + fn doTest(T: type) !?T { + return @splat(1); + } + }; + + _ = try S.doTest(@Vector(4, u32)); + _ = try S.doTest([4]u32); +}