diff --git a/doc/langref.html.in b/doc/langref.html.in index 19f9d832298ea89faf70d0d8dc2033abc99f400f..feb39d9e0b2a3cd58a4b98cf2fd17b4acc08d8fb 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5582,7 +5582,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val

Produces an array or vector where each element is the value {#syntax#}element{#endsyntax#}. The return type, including the number of - elements, is inferred. + elements, is inferred. If the result type is a scalar, `element` is returned.

{#code|test_splat_builtin.zig#} {#see_also|Vectors|Arrays|@shuffle#} diff --git a/doc/langref/test_splat_builtin.zig b/doc/langref/test_splat_builtin.zig index d00240620e7dbc738e2ae3468f2059f1f9c8e9a9..b3fd43ff4b75b06aac77b81ae63341c1527e5390 100644 --- a/doc/langref/test_splat_builtin.zig +++ b/doc/langref/test_splat_builtin.zig @@ -1,5 +1,6 @@ const std = @import("std"); const expectEqualSlices = std.testing.expectEqualSlices; +const expectEqual = std.testing.expectEqual; test "vector @splat" { const scalar: u32 = 5; @@ -13,4 +14,10 @@ test "array @splat" { try expectEqualSlices(u32, &[_]u32{ 5, 5, 5, 5 }, &@as([4]u32, result)); } +test "scalar @splat" { + const scalar: u32 = 5; + const result: u32 = @splat(scalar); + try expectEqual(5, result); +} + // test diff --git a/src/Sema.zig b/src/Sema.zig index 208bde58a95cd3c8b0dbf5b5ce6d68d67804e092..b16561b3e58a84c044364cccb2c2aedb8cf53d2f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7515,13 +7515,12 @@ fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; - const vec_ty = raw_ty.optEuBaseType(zcu); + const base_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(zcu)}), + switch (base_ty.zigTypeTag(zcu)) { + .array, .vector => return Air.internedToRef(base_ty.childType(zcu).toIntern()), + else => return Air.internedToRef(base_ty.toIntern()), } - return Air.internedToRef(vec_ty.childType(zcu).toIntern()); } fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -23314,17 +23313,17 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const scalar_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat"); + const operand = sema.resolveInst(extra.rhs); switch (dest_ty.zigTypeTag(zcu)) { .array, .vector => {}, - else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(zcu)}), + else => return sema.coerce(block, dest_ty, operand, operand_src), } - const operand = sema.resolveInst(extra.rhs); const scalar_ty = dest_ty.childType(zcu); - const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src); + const scalar = try sema.coerce(block, scalar_ty, operand, operand_src); const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu)); @@ -23348,7 +23347,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I return .fromValue(try pt.aggregateSplatValue(dest_ty, scalar_val)); } - try sema.requireRuntimeBlock(block, src, scalar_src); + try sema.requireRuntimeBlock(block, src, operand_src); switch (dest_ty.zigTypeTag(zcu)) { .vector, .array => return block.addTyOp(.splat, dest_ty, scalar), diff --git a/test/behavior/splat.zig b/test/behavior/splat.zig index b440fcbd0aeae203291fc940d4916d1214cb048c..e5ac1290ea93ee5debeee3f2231d74e7da5e8bc4 100644 --- a/test/behavior/splat.zig +++ b/test/behavior/splat.zig @@ -160,3 +160,22 @@ test "vector @splat" { try S.doTheTest(); try comptime S.doTheTest(); } + +test "scalar @splat" { + const S = struct { + fn testForTypes(R: type, result: R, Op: type, op: Op) !void { + try expect(@as(R, result) == @as(Op, @splat(op))); + } + fn doTheTest() !void { + try testForTypes(comptime_float, 3.1415, comptime_float, 3.1415); + try testForTypes(f32, 3.1415, comptime_float, 3.1415); + try testForTypes(f32, 3.1415, f32, 3.1415); + try testForTypes(u8, 31, u8, 31); + try testForTypes(u8, 31, u16, 31); + try testForTypes(i16, 31, i16, 31); + try testForTypes(i16, 31, i8, 31); + } + }; + try S.doTheTest(); + try comptime S.doTheTest(); +} diff --git a/test/cases/compile_errors/splat_bad_result_type.zig b/test/cases/compile_errors/splat_bad_result_type.zig deleted file mode 100644 index 60d4b35d45d0cef46fe9ac30b3f155d820c73893..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/splat_bad_result_type.zig +++ /dev/null @@ -1,7 +0,0 @@ -export fn f() void { - _ = @as(u32, @splat(5)); -} - -// error -// -// :2:18: error: expected array or vector type, found 'u32'