authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-29 19:58:39+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-30 09:03:58+01:00
log72d954e7d3cfb8b46a26d5a199a9a5ecd36d87be
tree593dcfa9fd869bab3b94506a588e01d22cab8706
parentfdac89d6cd65fa19bd5c6d381b62d980d97e5852
signaturelock-open Commit is signed but in an unrecognized format.

compiler: remove array multiplication from the language

Resolves: https://github.com/ziglang/zig/issues/24738

21 files changed, 20 insertions(+), 421 deletions(-)

lib/compiler/reduce/Walk.zig-1
...@@ -248,7 +248,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -248,7 +248,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
248 .add_wrap,248 .add_wrap,
249 .add_sat,249 .add_sat,
250 .array_cat,250 .array_cat,
251 .array_mult,
252 .assign,251 .assign,
253 .assign_bit_and,252 .assign_bit_and,
254 .assign_bit_or,253 .assign_bit_or,
lib/docs/wasm/Walk.zig-1
...@@ -709,7 +709,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -709,7 +709,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
709 .less_or_equal,709 .less_or_equal,
710 .array_cat,710 .array_cat,
711711
712 .array_mult,
713 .error_union,712 .error_union,
714 .merge_error_sets,713 .merge_error_sets,
715 .bool_and,714 .bool_and,
lib/docs/wasm/html_render.zig+1-2
...@@ -302,7 +302,6 @@ pub fn fileSourceHtml(...@@ -302,7 +302,6 @@ pub fn fileSourceHtml(
302 .minus_pipe_equal,302 .minus_pipe_equal,
303 .asterisk,303 .asterisk,
304 .asterisk_equal,304 .asterisk_equal,
305 .asterisk_asterisk,
306 .asterisk_percent,305 .asterisk_percent,
307 .asterisk_percent_equal,306 .asterisk_percent_equal,
308 .asterisk_pipe,307 .asterisk_pipe,
...@@ -328,7 +327,7 @@ pub fn fileSourceHtml(...@@ -328,7 +327,7 @@ pub fn fileSourceHtml(
328 .tilde,327 .tilde,
329 => try appendEscaped(out, slice),328 => try appendEscaped(out, slice),
330329
331 .invalid, .invalid_periodasterisks => return error.InvalidToken,330 .invalid => return error.InvalidToken,
332 }331 }
333 }332 }
334}333}
lib/std/crypto/Certificate.zig+1-1
...@@ -1092,7 +1092,7 @@ pub const rsa = struct {...@@ -1092,7 +1092,7 @@ pub const rsa = struct {
1092 }1092 }
1093 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;1093 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
1094 var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];1094 var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];
1095 std.mem.copyForwards(u8, m_p, @as(*const [8]u8, @splat(0)));1095 std.mem.copyForwards(u8, m_p, @as(*const [8]u8, &@splat(0)));
1096 std.mem.copyForwards(u8, m_p[8..], &mHash);1096 std.mem.copyForwards(u8, m_p[8..], &mHash);
1097 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);1097 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);
10981098
lib/std/zig.zig-2
...@@ -811,7 +811,6 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -811,7 +811,6 @@ pub const SimpleComptimeReason = enum(u32) {
811 compile_error_string,811 compile_error_string,
812 inline_assembly_code,812 inline_assembly_code,
813 atomic_order,813 atomic_order,
814 array_mul_factor,
815 slice_cat_operand,814 slice_cat_operand,
816 inline_call_target,815 inline_call_target,
817 generic_call_target,816 generic_call_target,
...@@ -899,7 +898,6 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -899,7 +898,6 @@ pub const SimpleComptimeReason = enum(u32) {
899 .compile_error_string => "compile error string must be comptime-known",898 .compile_error_string => "compile error string must be comptime-known",
900 .inline_assembly_code => "inline assembly code must be comptime-known",899 .inline_assembly_code => "inline assembly code must be comptime-known",
901 .atomic_order => "atomic order must be comptime-known",900 .atomic_order => "atomic order must be comptime-known",
902 .array_mul_factor => "array multiplication factor must be comptime-known",
903 .slice_cat_operand => "slice being concatenated must be comptime-known",901 .slice_cat_operand => "slice being concatenated must be comptime-known",
904 .inline_call_target => "function being called inline must be comptime-known",902 .inline_call_target => "function being called inline must be comptime-known",
905 .generic_call_target => "generic function being called must be comptime-known",903 .generic_call_target => "generic function being called must be comptime-known",
lib/std/zig/Ast.zig+1-21
...@@ -331,11 +331,6 @@ pub fn rootDecls(tree: Ast) []const Node.Index {...@@ -331,11 +331,6 @@ pub fn rootDecls(tree: Ast) []const Node.Index {
331331
332pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void {332pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void {
333 switch (parse_error.tag) {333 switch (parse_error.tag) {
334 .asterisk_after_ptr_deref => {
335 // Note that the token will point at the `.*` but ideally the source
336 // location would point to the `*` after the `.*`.
337 return w.writeAll("'.*' cannot be followed by '*'; are you missing a space?");
338 },
339 .chained_comparison_operators => {334 .chained_comparison_operators => {
340 return w.writeAll("comparison operators cannot be chained");335 return w.writeAll("comparison operators cannot be chained");
341 },336 },
...@@ -687,7 +682,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -687,7 +682,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
687 .mul,682 .mul,
688 .div,683 .div,
689 .mod,684 .mod,
690 .array_mult,
691 .mul_wrap,685 .mul_wrap,
692 .mul_sat,686 .mul_sat,
693 .add,687 .add,
...@@ -924,7 +918,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -924,7 +918,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
924 .mul,918 .mul,
925 .div,919 .div,
926 .mod,920 .mod,
927 .array_mult,
928 .mul_wrap,921 .mul_wrap,
929 .mul_sat,922 .mul_sat,
930 .add,923 .add,
...@@ -2111,9 +2104,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto...@@ -2111,9 +2104,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
21112104
2112fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {2105fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {
2113 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {2106 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {
2114 .asterisk,2107 .asterisk => .one,
2115 .asterisk_asterisk,
2116 => .one,
2117 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {2108 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {
2118 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,2109 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,
2119 else => .slice,2110 else => .slice,
...@@ -2842,7 +2833,6 @@ pub const Error = struct {...@@ -2842,7 +2833,6 @@ pub const Error = struct {
2842 } = .{ .none = {} },2833 } = .{ .none = {} },
28432834
2844 pub const Tag = enum {2835 pub const Tag = enum {
2845 asterisk_after_ptr_deref,
2846 chained_comparison_operators,2836 chained_comparison_operators,
2847 decl_between_fields,2837 decl_between_fields,
2848 expected_block,2838 expected_block,
...@@ -3178,8 +3168,6 @@ pub const Node = struct {...@@ -3178,8 +3168,6 @@ pub const Node = struct {
3178 div,3168 div,
3179 /// `lhs % rhs`. The `main_token` field is the `%` token.3169 /// `lhs % rhs`. The `main_token` field is the `%` token.
3180 mod,3170 mod,
3181 /// `lhs ** rhs`. The `main_token` field is the `**` token.
3182 array_mult,
3183 /// `lhs *% rhs`. The `main_token` field is the `*%` token.3171 /// `lhs *% rhs`. The `main_token` field is the `*%` token.
3184 mul_wrap,3172 mul_wrap,
3185 /// `lhs *| rhs`. The `main_token` field is the `*|` token.3173 /// `lhs *| rhs`. The `main_token` field is the `*|` token.
...@@ -3250,8 +3238,6 @@ pub const Node = struct {...@@ -3250,8 +3238,6 @@ pub const Node = struct {
3250 ///3238 ///
3251 /// The `main_token` is the asterisk if a single item pointer or the3239 /// The `main_token` is the asterisk if a single item pointer or the
3252 /// lbracket if a slice, many-item pointer, or C-pointer.3240 /// lbracket if a slice, many-item pointer, or C-pointer.
3253 /// The `main_token` might be a ** token, which is shared with a
3254 /// parent/child pointer type and may require special handling.
3255 ptr_type_aligned,3241 ptr_type_aligned,
3256 /// `[*:lhs]rhs`,3242 /// `[*:lhs]rhs`,
3257 /// `*rhs`,3243 /// `*rhs`,
...@@ -3263,8 +3249,6 @@ pub const Node = struct {...@@ -3263,8 +3249,6 @@ pub const Node = struct {
3263 ///3249 ///
3264 /// The `main_token` is the asterisk if a single item pointer or the3250 /// The `main_token` is the asterisk if a single item pointer or the
3265 /// lbracket if a slice, many-item pointer, or C-pointer.3251 /// lbracket if a slice, many-item pointer, or C-pointer.
3266 /// The `main_token` might be a ** token, which is shared with a
3267 /// parent/child pointer type and may require special handling.
3268 ptr_type_sentinel,3252 ptr_type_sentinel,
3269 /// The `data` field is a `.extra_and_node`:3253 /// The `data` field is a `.extra_and_node`:
3270 /// 1. a `ExtraIndex` to `PtrType`.3254 /// 1. a `ExtraIndex` to `PtrType`.
...@@ -3272,8 +3256,6 @@ pub const Node = struct {...@@ -3272,8 +3256,6 @@ pub const Node = struct {
3272 ///3256 ///
3273 /// The `main_token` is the asterisk if a single item pointer or the3257 /// The `main_token` is the asterisk if a single item pointer or the
3274 /// lbracket if a slice, many-item pointer, or C-pointer.3258 /// lbracket if a slice, many-item pointer, or C-pointer.
3275 /// The `main_token` might be a ** token, which is shared with a
3276 /// parent/child pointer type and may require special handling.
3277 ptr_type,3259 ptr_type,
3278 /// The `data` field is a `.extra_and_node`:3260 /// The `data` field is a `.extra_and_node`:
3279 /// 1. a `ExtraIndex` to `PtrTypeBitRange`.3261 /// 1. a `ExtraIndex` to `PtrTypeBitRange`.
...@@ -3281,8 +3263,6 @@ pub const Node = struct {...@@ -3281,8 +3263,6 @@ pub const Node = struct {
3281 ///3263 ///
3282 /// The `main_token` is the asterisk if a single item pointer or the3264 /// The `main_token` is the asterisk if a single item pointer or the
3283 /// lbracket if a slice, many-item pointer, or C-pointer.3265 /// lbracket if a slice, many-item pointer, or C-pointer.
3284 /// The `main_token` might be a ** token, which is shared with a
3285 /// parent/child pointer type and may require special handling.
3286 ptr_type_bit_range,3266 ptr_type_bit_range,
3287 /// `lhs[rhs..]`3267 /// `lhs[rhs..]`
3288 ///3268 ///
lib/std/zig/Ast/Render.zig-12
...@@ -508,7 +508,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -508,7 +508,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
508 .add_wrap,508 .add_wrap,
509 .add_sat,509 .add_sat,
510 .array_cat,510 .array_cat,
511 .array_mult,
512 .bang_equal,511 .bang_equal,
513 .bit_and,512 .bit_and,
514 .bit_or,513 .bit_or,
...@@ -1028,16 +1027,6 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi...@@ -1028,16 +1027,6 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
10281027
1029 switch (ptr_type.size) {1028 switch (ptr_type.size) {
1030 .one => {1029 .one => {
1031 // Since ** tokens exist and the same token is shared by two
1032 // nested pointer types, we check to see if we are the parent
1033 // in such a relationship. If so, skip rendering anything for
1034 // this pointer type and rely on the child to render our asterisk
1035 // as well when it renders the ** token.
1036 if (tree.tokenTag(main_token) == .asterisk_asterisk and
1037 main_token == tree.nodeMainToken(ptr_type.ast.child_type))
1038 {
1039 return renderExpression(r, ptr_type.ast.child_type, space);
1040 }
1041 try renderToken(r, main_token, .none); // asterisk1030 try renderToken(r, main_token, .none); // asterisk
1042 },1031 },
1043 .many => {1032 .many => {
...@@ -3223,7 +3212,6 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {...@@ -3223,7 +3212,6 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {
3223 .add,3212 .add,
3224 .add_wrap,3213 .add_wrap,
3225 .array_cat,3214 .array_cat,
3226 .array_mult,
3227 .assign,3215 .assign,
3228 .assign_bit_and,3216 .assign_bit_and,
3229 .assign_bit_or,3217 .assign_bit_or,
lib/std/zig/AstGen.zig-16
...@@ -507,7 +507,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins...@@ -507,7 +507,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
507 .less_than,507 .less_than,
508 .less_or_equal,508 .less_or_equal,
509 .array_cat,509 .array_cat,
510 .array_mult,
511 .bool_and,510 .bool_and,
512 .bool_or,511 .bool_or,
513 .@"asm",512 .@"asm",
...@@ -777,19 +776,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -777,19 +776,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
777 .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte),776 .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte),
778 .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat),777 .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat),
779778
780 .array_mult => {
781 // This syntax form does not currently use the result type in the language specification.
782 // However, the result type can be used to emit more optimal code for large multiplications by
783 // having Sema perform a coercion before the multiplication operation.
784 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
785 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{
786 .res_ty = if (try ri.rl.resultType(gz, node)) |t| t else .none,
787 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
788 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node, .array_mul_factor),
789 });
790 return rvalue(gz, ri, result, node);
791 },
792
793 .error_union, .merge_error_sets => |tag| {779 .error_union, .merge_error_sets => |tag| {
794 const inst_tag: Zir.Inst.Tag = switch (tag) {780 const inst_tag: Zir.Inst.Tag = switch (tag) {
795 .error_union => .error_union_type,781 .error_union => .error_union_type,
...@@ -2713,7 +2699,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2713,7 +2699,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2713 .alloc_inferred_comptime_mut,2699 .alloc_inferred_comptime_mut,
2714 .make_ptr_const,2700 .make_ptr_const,
2715 .array_cat,2701 .array_cat,
2716 .array_mul,
2717 .array_type,2702 .array_type,
2718 .array_type_sentinel,2703 .array_type_sentinel,
2719 .elem_type,2704 .elem_type,
...@@ -10307,7 +10292,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10307,7 +10292,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10307 .add_wrap,10292 .add_wrap,
10308 .add_sat,10293 .add_sat,
10309 .array_cat,10294 .array_cat,
10310 .array_mult,
10311 .assign,10295 .assign,
10312 .assign_destructure,10296 .assign_destructure,
10313 .assign_bit_and,10297 .assign_bit_and,
lib/std/zig/AstRlAnnotate.zig-6
...@@ -269,12 +269,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -269,12 +269,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
269 return false;269 return false;
270 },270 },
271271
272 .array_mult => {
273 const lhs, const rhs = tree.nodeData(node).node_and_node;
274 _ = try astrl.expr(lhs, block, ResultInfo.none);
275 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
276 return false;
277 },
278 .error_union, .merge_error_sets => {272 .error_union, .merge_error_sets => {
279 const lhs, const rhs = tree.nodeData(node).node_and_node;273 const lhs, const rhs = tree.nodeData(node).node_and_node;
280 _ = try astrl.expr(lhs, block, ResultInfo.none);274 _ = try astrl.expr(lhs, block, ResultInfo.none);
lib/std/zig/AstSmith.zig+4-10
...@@ -18,7 +18,6 @@ token_tag_buf: [2048]Token.Tag,...@@ -18,7 +18,6 @@ token_tag_buf: [2048]Token.Tag,
18token_start_buf: [2048]std.zig.Ast.ByteOffset,18token_start_buf: [2048]std.zig.Ast.ByteOffset,
19tokens_len: usize,19tokens_len: usize,
2020
21/// For `.asterisk`, this also includes `.asterisk2`
22not_token: ?Token.Tag,21not_token: ?Token.Tag,
23not_token_comptime: bool,22not_token_comptime: bool,
24/// ExprSuffix23/// ExprSuffix
...@@ -196,7 +195,6 @@ fn preservePegEndOfWord(a: *AstSmith) SourceError!void {...@@ -196,7 +195,6 @@ fn preservePegEndOfWord(a: *AstSmith) SourceError!void {
196/// Assumes the token has not been written yet195/// Assumes the token has not been written yet
197fn addTokenTag(a: *AstSmith, tag: Token.Tag) SourceError!void {196fn addTokenTag(a: *AstSmith, tag: Token.Tag) SourceError!void {
198 assert(tag != a.not_token);197 assert(tag != a.not_token);
199 if (a.not_token == .asterisk) assert(tag != .asterisk_asterisk);
200 a.not_token = null;198 a.not_token = null;
201199
202 if (a.not_token_comptime) assert(tag != .keyword_comptime);200 if (a.not_token_comptime) assert(tag != .keyword_comptime);
...@@ -240,9 +238,7 @@ fn pegToken(a: *AstSmith, tag: Token.Tag) SourceError!void {...@@ -240,9 +238,7 @@ fn pegToken(a: *AstSmith, tag: Token.Tag) SourceError!void {
240238
241 switch (lexeme[0]) {239 switch (lexeme[0]) {
242 '_', 'a'...'z', 'A'...'Z', '0'...'9' => try a.preservePegEndOfWord(),240 '_', 'a'...'z', 'A'...'Z', '0'...'9' => try a.preservePegEndOfWord(),
243 '*' => if (a.tokens_len > 0 and a.source_buf[a.source_len - 1] == '*' and241 '*' => if (a.tokens_len > 0 and a.source_buf[a.source_len - 1] == '*') {
244 a.token_tag_buf[a.tokens_len - 1] != .asterisk_asterisk)
245 {
246 try a.addSourceByte(' ');242 try a.addSourceByte(' ');
247 },243 },
248 '.' => if (a.tokens_len > 0 and switch (a.source_buf[a.source_len - 1]) {244 '.' => if (a.tokens_len > 0 and switch (a.source_buf[a.source_len - 1]) {
...@@ -1723,13 +1719,11 @@ fn pegAdditionOp(a: *AstSmith) SourceError!void {...@@ -1723,13 +1719,11 @@ fn pegAdditionOp(a: *AstSmith) SourceError!void {
1723/// / ASTERISK1719/// / ASTERISK
1724/// / SLASH1720/// / SLASH
1725/// / PERCENT1721/// / PERCENT
1726/// / ASTERISK2
1727/// / ASTERISKPERCENT1722/// / ASTERISKPERCENT
1728/// / ASTERISKPIPE1723/// / ASTERISKPIPE
1729fn pegMultiplyOp(a: *AstSmith) SourceError!void {1724fn pegMultiplyOp(a: *AstSmith) SourceError!void {
1730 const tags = [_]Token.Tag{1725 const tags = [_]Token.Tag{
1731 .asterisk,1726 .asterisk,
1732 .asterisk_asterisk,
1733 .pipe_pipe,1727 .pipe_pipe,
1734 .slash,1728 .slash,
1735 .percent,1729 .percent,
...@@ -1865,9 +1859,9 @@ fn pegSliceTypeStart(a: *AstSmith) SourceError!void {...@@ -1865,9 +1859,9 @@ fn pegSliceTypeStart(a: *AstSmith) SourceError!void {
1865 try a.pegToken(.r_bracket);1859 try a.pegToken(.r_bracket);
1866}1860}
18671861
1868/// SinglePtrTypeStart <- ASTERISK / ASTERISK21862/// SinglePtrTypeStart <- ASTERISK
1869fn pegSinglePtrTypeStart(a: *AstSmith) SourceError!void {1863fn pegSinglePtrTypeStart(a: *AstSmith) SourceError!void {
1870 try a.pegToken(if (!a.smith.value(bool)) .asterisk else .asterisk_asterisk);1864 try a.pegToken(.asterisk);
1871}1865}
18721866
1873/// ManyPtrTypeStart <- LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET1867/// ManyPtrTypeStart <- LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
...@@ -1889,7 +1883,7 @@ fn pegManyPtrTypeStart(a: *AstSmith) SourceError!void {...@@ -1889,7 +1883,7 @@ fn pegManyPtrTypeStart(a: *AstSmith) SourceError!void {
1889 try a.pegToken(.r_bracket);1883 try a.pegToken(.r_bracket);
1890}1884}
18911885
1892/// ArrayTypeStart <- LBRACKET !(ASTERISK / ASTERISK2) Expr (COLON Expr)? RBRACKET1886/// ArrayTypeStart <- LBRACKET !ASTERISK Expr (COLON Expr)? RBRACKET
1893fn pegArrayTypeStart(a: *AstSmith) SourceError!void {1887fn pegArrayTypeStart(a: *AstSmith) SourceError!void {
1894 try a.pegToken(.l_bracket);1888 try a.pegToken(.l_bracket);
1895 a.not_token = .asterisk;1889 a.not_token = .asterisk;
lib/std/zig/Parse.zig+2-64
...@@ -1609,7 +1609,6 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec...@@ -1609,7 +1609,6 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec
1609 .asterisk = .{ .prec = 70, .tag = .mul },1609 .asterisk = .{ .prec = 70, .tag = .mul },
1610 .slash = .{ .prec = 70, .tag = .div },1610 .slash = .{ .prec = 70, .tag = .div },
1611 .percent = .{ .prec = 70, .tag = .mod },1611 .percent = .{ .prec = 70, .tag = .mod },
1612 .asterisk_asterisk = .{ .prec = 70, .tag = .array_mult },
1613 .asterisk_percent = .{ .prec = 70, .tag = .mul_wrap },1612 .asterisk_percent = .{ .prec = 70, .tag = .mul_wrap },
1614 .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat },1613 .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat },
1615});1614});
...@@ -1709,11 +1708,11 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index {...@@ -1709,11 +1708,11 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index {
1709///1708///
1710/// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET1709/// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
1711///1710///
1712/// SinglePtrTypeStart <- ASTERISK / ASTERISK21711/// SinglePtrTypeStart <- ASTERISK
1713///1712///
1714/// ManyPtrTypeStart <- LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET1713/// ManyPtrTypeStart <- LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
1715///1714///
1716/// ArrayTypeStart <- LBRACKET Expr !(ASTERISK / ASTERISK2) (COLON Expr)? RBRACKET1715/// ArrayTypeStart <- LBRACKET Expr !ASTERISK (COLON Expr)? RBRACKET
1717///1716///
1718/// BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN1717/// BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN
1719fn parseTypeExpr(p: *Parse) Error!?Node.Index {1718fn parseTypeExpr(p: *Parse) Error!?Node.Index {
...@@ -1777,59 +1776,6 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {...@@ -1777,59 +1776,6 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1777 });1776 });
1778 }1777 }
1779 },1778 },
1780 .asterisk_asterisk => {
1781 const asterisk = p.nextToken();
1782 const mods = try p.parsePtrModifiers();
1783 const elem_type = try p.expectTypeExpr();
1784 const inner: Node.Index = inner: {
1785 if (mods.bit_range_start != .none) {
1786 break :inner try p.addNode(.{
1787 .tag = .ptr_type_bit_range,
1788 .main_token = asterisk,
1789 .data = .{ .extra_and_node = .{
1790 try p.addExtra(Node.PtrTypeBitRange{
1791 .sentinel = .none,
1792 .align_node = mods.align_node.unwrap().?,
1793 .addrspace_node = mods.addrspace_node,
1794 .bit_range_start = mods.bit_range_start.unwrap().?,
1795 .bit_range_end = mods.bit_range_end.unwrap().?,
1796 }),
1797 elem_type,
1798 } },
1799 });
1800 } else if (mods.addrspace_node != .none) {
1801 break :inner try p.addNode(.{
1802 .tag = .ptr_type,
1803 .main_token = asterisk,
1804 .data = .{ .extra_and_node = .{
1805 try p.addExtra(Node.PtrType{
1806 .sentinel = .none,
1807 .align_node = mods.align_node,
1808 .addrspace_node = mods.addrspace_node,
1809 }),
1810 elem_type,
1811 } },
1812 });
1813 } else {
1814 break :inner try p.addNode(.{
1815 .tag = .ptr_type_aligned,
1816 .main_token = asterisk,
1817 .data = .{ .opt_node_and_node = .{
1818 mods.align_node,
1819 elem_type,
1820 } },
1821 });
1822 }
1823 };
1824 return try p.addNode(.{
1825 .tag = .ptr_type_aligned,
1826 .main_token = asterisk,
1827 .data = .{ .opt_node_and_node = .{
1828 .none,
1829 inner,
1830 } },
1831 });
1832 },
1833 .l_bracket => switch (p.tokenTag(p.tok_i + 1)) {1779 .l_bracket => switch (p.tokenTag(p.tok_i + 1)) {
1834 .asterisk => {1780 .asterisk => {
1835 const l_bracket = p.nextToken();1781 const l_bracket = p.nextToken();
...@@ -3257,14 +3203,6 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {...@@ -3257,14 +3203,6 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
3257 .main_token = p.nextToken(),3203 .main_token = p.nextToken(),
3258 .data = .{ .node = lhs },3204 .data = .{ .node = lhs },
3259 }),3205 }),
3260 .invalid_periodasterisks => {
3261 try p.warn(.asterisk_after_ptr_deref);
3262 return try p.addNode(.{
3263 .tag = .deref,
3264 .main_token = p.nextToken(),
3265 .data = .{ .node = lhs },
3266 });
3267 },
3268 .period => switch (p.tokenTag(p.tok_i + 1)) {3206 .period => switch (p.tokenTag(p.tok_i + 1)) {
3269 .identifier => return try p.addNode(.{3207 .identifier => return try p.addNode(.{
3270 .tag = .field_access,3208 .tag = .field_access,
lib/std/zig/TokenSmith.zig-6
...@@ -57,12 +57,6 @@ pub fn gen(smith: *Smith) TokenSmith {...@@ -57,12 +57,6 @@ pub fn gen(smith: *Smith) TokenSmith {
57 @memcpy(t.source_buf[t.source_len..][0..lexeme.len], lexeme);57 @memcpy(t.source_buf[t.source_len..][0..lexeme.len], lexeme);
58 t.source_len += @intCast(lexeme.len);58 t.source_len += @intCast(lexeme.len);
5959
60 if (tag == .invalid_periodasterisks) {
61 t.tag_buf[t.tags_len] = .asterisk;
62 t.start_buf[t.tags_len] = t.source_len - 1;
63 t.tags_len += 1;
64 }
65
66 t.source_buf[t.source_len] = '\n';60 t.source_buf[t.source_len] = '\n';
67 t.source_len += 1;61 t.source_len += 1;
68 } else sw: switch (tag) {62 } else sw: switch (tag) {
lib/std/zig/Zir.zig-16
...@@ -250,9 +250,6 @@ pub const Inst = struct {...@@ -250,9 +250,6 @@ pub const Inst = struct {
250 /// Array concatenation. `a ++ b`250 /// Array concatenation. `a ++ b`
251 /// Uses the `pl_node` union field. Payload is `Bin`.251 /// Uses the `pl_node` union field. Payload is `Bin`.
252 array_cat,252 array_cat,
253 /// Array multiplication `a ** b`
254 /// Uses the `pl_node` union field. Payload is `ArrayMul`.
255 array_mul,
256 /// `[N]T` syntax. No source location provided.253 /// `[N]T` syntax. No source location provided.
257 /// Uses the `pl_node` union field. Payload is `Bin`. lhs is length, rhs is element type.254 /// Uses the `pl_node` union field. Payload is `Bin`. lhs is length, rhs is element type.
258 array_type,255 array_type,
...@@ -1102,7 +1099,6 @@ pub const Inst = struct {...@@ -1102,7 +1099,6 @@ pub const Inst = struct {
1102 .alloc_inferred_comptime_mut,1099 .alloc_inferred_comptime_mut,
1103 .make_ptr_const,1100 .make_ptr_const,
1104 .array_cat,1101 .array_cat,
1105 .array_mul,
1106 .array_type,1102 .array_type,
1107 .array_type_sentinel,1103 .array_type_sentinel,
1108 .reify_int,1104 .reify_int,
...@@ -1396,7 +1392,6 @@ pub const Inst = struct {...@@ -1396,7 +1392,6 @@ pub const Inst = struct {
1396 .resolve_inferred_alloc,1392 .resolve_inferred_alloc,
1397 .make_ptr_const,1393 .make_ptr_const,
1398 .array_cat,1394 .array_cat,
1399 .array_mul,
1400 .array_type,1395 .array_type,
1401 .array_type_sentinel,1396 .array_type_sentinel,
1402 .reify_int,1397 .reify_int,
...@@ -1630,7 +1625,6 @@ pub const Inst = struct {...@@ -1630,7 +1625,6 @@ pub const Inst = struct {
1630 .param_anytype = .str_tok,1625 .param_anytype = .str_tok,
1631 .param_anytype_comptime = .str_tok,1626 .param_anytype_comptime = .str_tok,
1632 .array_cat = .pl_node,1627 .array_cat = .pl_node,
1633 .array_mul = .pl_node,
1634 .array_type = .pl_node,1628 .array_type = .pl_node,
1635 .array_type_sentinel = .pl_node,1629 .array_type_sentinel = .pl_node,
1636 .reify_int = .pl_node,1630 .reify_int = .pl_node,
...@@ -3961,15 +3955,6 @@ pub const Inst = struct {...@@ -3961,15 +3955,6 @@ pub const Inst = struct {
3961 expect_len: u32,3955 expect_len: u32,
3962 };3956 };
39633957
3964 pub const ArrayMul = struct {
3965 /// The result type of the array multiplication operation, or `.none` if none was available.
3966 res_ty: Ref,
3967 /// The LHS of the array multiplication.
3968 lhs: Ref,
3969 /// The RHS of the array multiplication.
3970 rhs: Ref,
3971 };
3972
3973 pub const RestoreErrRetIndex = struct {3958 pub const RestoreErrRetIndex = struct {
3974 src_node: Ast.Node.Offset,3959 src_node: Ast.Node.Offset,
3975 /// If `.none`, restore the trace to its state upon function entry.3960 /// If `.none`, restore the trace to its state upon function entry.
...@@ -4121,7 +4106,6 @@ fn findTrackableInner(...@@ -4121,7 +4106,6 @@ fn findTrackableInner(
4121 .param_anytype,4106 .param_anytype,
4122 .param_anytype_comptime,4107 .param_anytype_comptime,
4123 .array_cat,4108 .array_cat,
4124 .array_mul,
4125 .array_type,4109 .array_type,
4126 .array_type_sentinel,4110 .array_type_sentinel,
4127 .reify_int,4111 .reify_int,
lib/std/zig/ZonGen.zig-1
...@@ -166,7 +166,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -166,7 +166,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
166 .less_than,166 .less_than,
167 .less_or_equal,167 .less_or_equal,
168 .array_cat,168 .array_cat,
169 .array_mult,
170 .bool_and,169 .bool_and,
171 .bool_or,170 .bool_or,
172 .bool_not,171 .bool_not,
lib/std/zig/llvm/Builder.zig+2-2
...@@ -7628,7 +7628,7 @@ pub const Constant = enum(u32) {...@@ -7628,7 +7628,7 @@ pub const Constant = enum(u32) {
7628 const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));7628 const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
7629 string: [7629 string: [
7630 (std.math.big.int.Const{7630 (std.math.big.int.Const{
7631 .limbs = &@splat(maxInt(std.math.big.Limb)),7631 .limbs = &@as([expected_limbs]std.math.big.Limb, @splat(maxInt(std.math.big.Limb))),
7632 .positive = false,7632 .positive = false,
7633 }).sizeInBaseUpperBound(10)7633 }).sizeInBaseUpperBound(10)
7634 ]u8,7634 ]u8,
...@@ -10595,7 +10595,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10595,7 +10595,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10595 const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));10595 const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
10596 string: [10596 string: [
10597 (std.math.big.int.Const{10597 (std.math.big.int.Const{
10598 .limbs = &@splat(maxInt(std.math.big.Limb)),10598 .limbs = &@as([expected_limbs]std.math.big.Limb, @splat(maxInt(std.math.big.Limb))),
10599 .positive = false,10599 .positive = false,
10600 }).sizeInBaseUpperBound(10)10600 }).sizeInBaseUpperBound(10)
10601 ]u8,10601 ]u8,
lib/std/zig/parser_test.zig+3-30
...@@ -2764,13 +2764,6 @@ test "zig fmt: comments before var decl in struct" {...@@ -2764,13 +2764,6 @@ test "zig fmt: comments before var decl in struct" {
2764 );2764 );
2765}2765}
27662766
2767test "zig fmt: array literal with 1 item on 1 line" {
2768 try testCanonical(
2769 \\var s = []const u64{0} ** 25;
2770 \\
2771 );
2772}
2773
2774test "zig fmt: comments before global variables" {2767test "zig fmt: comments before global variables" {
2775 try testCanonical(2768 try testCanonical(
2776 \\/// Foo copies keys and values before they go into the map, and2769 \\/// Foo copies keys and values before they go into the map, and
...@@ -2911,7 +2904,7 @@ test "zig fmt: function attributes" {...@@ -2911,7 +2904,7 @@ test "zig fmt: function attributes" {
2911 );2904 );
2912}2905}
29132906
2914test "zig fmt: nested pointers with ** tokens" {2907test "zig fmt: deeply nested pointers" {
2915 try testCanonical(2908 try testCanonical(
2916 \\const x: *u32 = undefined;2909 \\const x: *u32 = undefined;
2917 \\const x: **u32 = undefined;2910 \\const x: **u32 = undefined;
...@@ -3001,7 +2994,6 @@ test "zig fmt: infix operators" {...@@ -3001,7 +2994,6 @@ test "zig fmt: infix operators" {
3001 \\ _ = i.i;2994 \\ _ = i.i;
3002 \\ _ = i || i;2995 \\ _ = i || i;
3003 \\ _ = i!i;2996 \\ _ = i!i;
3004 \\ _ = i ** i;
3005 \\ _ = i ++ i;2997 \\ _ = i ++ i;
3006 \\ _ = i orelse i;2998 \\ _ = i orelse i;
3007 \\ _ = i % i;2999 \\ _ = i % i;
...@@ -4565,7 +4557,7 @@ test "zig fmt: integer literals with underscore separators" {...@@ -4565,7 +4557,7 @@ test "zig fmt: integer literals with underscore separators" {
4565test "zig fmt: hex literals with underscore separators" {4557test "zig fmt: hex literals with underscore separators" {
4566 try testTransform(4558 try testTransform(
4567 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {4559 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
4568 \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;4560 \\ var c: [1_000]u64 = @splat(0xFFFF_FFFF_FFFF_FFFF);
4569 \\ for (c [ 1_0 .. ], 0..) |_, i| {4561 \\ for (c [ 1_0 .. ], 0..) |_, i| {
4570 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;4562 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
4571 \\ }4563 \\ }
...@@ -4575,7 +4567,7 @@ test "zig fmt: hex literals with underscore separators" {...@@ -4575,7 +4567,7 @@ test "zig fmt: hex literals with underscore separators" {
4575 \\4567 \\
4576 ,4568 ,
4577 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {4569 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
4578 \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;4570 \\ var c: [1_000]u64 = @splat(0xFFFF_FFFF_FFFF_FFFF);
4579 \\ for (c[1_0..], 0..) |_, i| {4571 \\ for (c[1_0..], 0..) |_, i| {
4580 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;4572 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
4581 \\ }4573 \\ }
...@@ -7083,25 +7075,6 @@ test "recovery: invalid global error set access" {...@@ -7083,25 +7075,6 @@ test "recovery: invalid global error set access" {
7083 });7075 });
7084}7076}
70857077
7086test "recovery: invalid asterisk after pointer dereference" {
7087 try testError(
7088 \\test "" {
7089 \\ var sequence = "repeat".*** 10;
7090 \\}
7091 , &[_]Error{
7092 .asterisk_after_ptr_deref,
7093 .mismatched_binary_op_whitespace,
7094 });
7095 try testError(
7096 \\test "" {
7097 \\ var sequence = "repeat".** 10&a;
7098 \\}
7099 , &[_]Error{
7100 .asterisk_after_ptr_deref,
7101 .mismatched_binary_op_whitespace,
7102 });
7103}
7104
7105test "recovery: missing semicolon after if, for, while stmt" {7078test "recovery: missing semicolon after if, for, while stmt" {
7106 try testError(7079 try testError(
7107 \\test "" {7080 \\test "" {
lib/std/zig/tokenizer.zig+4-43
...@@ -64,7 +64,6 @@ pub const Token = struct {...@@ -64,7 +64,6 @@ pub const Token = struct {
6464
65 pub const Tag = enum {65 pub const Tag = enum {
66 invalid,66 invalid,
67 invalid_periodasterisks,
68 identifier,67 identifier,
69 string_literal,68 string_literal,
70 multiline_string_literal_line,69 multiline_string_literal_line,
...@@ -109,7 +108,6 @@ pub const Token = struct {...@@ -109,7 +108,6 @@ pub const Token = struct {
109 minus_pipe_equal,108 minus_pipe_equal,
110 asterisk,109 asterisk,
111 asterisk_equal,110 asterisk_equal,
112 asterisk_asterisk,
113 asterisk_percent,111 asterisk_percent,
114 asterisk_percent_equal,112 asterisk_percent_equal,
115 asterisk_pipe,113 asterisk_pipe,
...@@ -197,7 +195,6 @@ pub const Token = struct {...@@ -197,7 +195,6 @@ pub const Token = struct {
197 .container_doc_comment,195 .container_doc_comment,
198 => null,196 => null,
199197
200 .invalid_periodasterisks => ".**",
201 .bang => "!",198 .bang => "!",
202 .pipe => "|",199 .pipe => "|",
203 .pipe_pipe => "||",200 .pipe_pipe => "||",
...@@ -236,7 +233,6 @@ pub const Token = struct {...@@ -236,7 +233,6 @@ pub const Token = struct {
236 .minus_pipe_equal => "-|=",233 .minus_pipe_equal => "-|=",
237 .asterisk => "*",234 .asterisk => "*",
238 .asterisk_equal => "*=",235 .asterisk_equal => "*=",
239 .asterisk_asterisk => "**",
240 .asterisk_percent => "*%",236 .asterisk_percent => "*%",
241 .asterisk_percent_equal => "*%=",237 .asterisk_percent_equal => "*%=",
242 .asterisk_pipe => "*|",238 .asterisk_pipe => "*|",
...@@ -386,7 +382,6 @@ pub const Tokenizer = struct {...@@ -386,7 +382,6 @@ pub const Tokenizer = struct {
386 angle_bracket_angle_bracket_right,382 angle_bracket_angle_bracket_right,
387 period,383 period,
388 period_2,384 period_2,
389 period_asterisk,
390 saw_at_sign,385 saw_at_sign,
391 invalid,386 invalid,
392 };387 };
...@@ -569,10 +564,6 @@ pub const Tokenizer = struct {...@@ -569,10 +564,6 @@ pub const Tokenizer = struct {
569 result.tag = .asterisk_equal;564 result.tag = .asterisk_equal;
570 self.index += 1;565 self.index += 1;
571 },566 },
572 '*' => {
573 result.tag = .asterisk_asterisk;
574 self.index += 1;
575 },
576 '%' => continue :state .asterisk_percent,567 '%' => continue :state .asterisk_percent,
577 '|' => continue :state .asterisk_pipe,568 '|' => continue :state .asterisk_pipe,
578 else => result.tag = .asterisk,569 else => result.tag = .asterisk,
...@@ -915,7 +906,10 @@ pub const Tokenizer = struct {...@@ -915,7 +906,10 @@ pub const Tokenizer = struct {
915 self.index += 1;906 self.index += 1;
916 switch (self.buffer[self.index]) {907 switch (self.buffer[self.index]) {
917 '.' => continue :state .period_2,908 '.' => continue :state .period_2,
918 '*' => continue :state .period_asterisk,909 '*' => {
910 result.tag = .period_asterisk;
911 self.index += 1;
912 },
919 else => result.tag = .period,913 else => result.tag = .period,
920 }914 }
921 },915 },
...@@ -931,14 +925,6 @@ pub const Tokenizer = struct {...@@ -931,14 +925,6 @@ pub const Tokenizer = struct {
931 }925 }
932 },926 },
933927
934 .period_asterisk => {
935 self.index += 1;
936 switch (self.buffer[self.index]) {
937 '*' => result.tag = .invalid_periodasterisks,
938 else => result.tag = .period_asterisk,
939 }
940 },
941
942 .slash => {928 .slash => {
943 self.index += 1;929 self.index += 1;
944 switch (self.buffer[self.index]) {930 switch (self.buffer[self.index]) {
...@@ -1343,31 +1329,6 @@ test "correctly parse pointer assignment" {...@@ -1343,31 +1329,6 @@ test "correctly parse pointer assignment" {
1343 });1329 });
1344}1330}
13451331
1346test "correctly parse pointer dereference followed by asterisk" {
1347 try testTokenize("\"b\".* ** 10", &.{
1348 .string_literal,
1349 .period_asterisk,
1350 .asterisk_asterisk,
1351 .number_literal,
1352 });
1353
1354 try testTokenize("(\"b\".*)** 10", &.{
1355 .l_paren,
1356 .string_literal,
1357 .period_asterisk,
1358 .r_paren,
1359 .asterisk_asterisk,
1360 .number_literal,
1361 });
1362
1363 try testTokenize("\"b\".*** 10", &.{
1364 .string_literal,
1365 .invalid_periodasterisks,
1366 .asterisk_asterisk,
1367 .number_literal,
1368 });
1369}
1370
1371test "range literals" {1332test "range literals" {
1372 try testTokenize("0...9", &.{ .number_literal, .ellipsis3, .number_literal });1333 try testTokenize("0...9", &.{ .number_literal, .ellipsis3, .number_literal });
1373 try testTokenize("'0'...'9'", &.{ .char_literal, .ellipsis3, .char_literal });1334 try testTokenize("'0'...'9'", &.{ .char_literal, .ellipsis3, .char_literal });
src/Sema.zig-169
...@@ -1171,7 +1171,6 @@ fn analyzeBodyInner(...@@ -1171,7 +1171,6 @@ fn analyzeBodyInner(
1171 .make_ptr_const => try sema.zirMakePtrConst(block, inst),1171 .make_ptr_const => try sema.zirMakePtrConst(block, inst),
1172 .anyframe_type => try sema.zirAnyframeType(block, inst),1172 .anyframe_type => try sema.zirAnyframeType(block, inst),
1173 .array_cat => try sema.zirArrayCat(block, inst),1173 .array_cat => try sema.zirArrayCat(block, inst),
1174 .array_mul => try sema.zirArrayMul(block, inst),
1175 .array_type => try sema.zirArrayType(block, inst),1174 .array_type => try sema.zirArrayType(block, inst),
1176 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),1175 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
1177 .reify_int => try sema.zirReifyInt(block, inst),1176 .reify_int => try sema.zirReifyInt(block, inst),
...@@ -13861,174 +13860,6 @@ fn analyzeTupleMul(...@@ -13861,174 +13860,6 @@ fn analyzeTupleMul(
13861 return block.addAggregateInit(tuple_ty, element_refs);13860 return block.addAggregateInit(tuple_ty, element_refs);
13862}13861}
1386313862
13864fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13865 const tracy = trace(@src());
13866 defer tracy.end();
13867
13868 const pt = sema.pt;
13869 const zcu = pt.zcu;
13870 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
13871 const extra = sema.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;
13872 const uncoerced_lhs = sema.resolveInst(extra.lhs);
13873 const uncoerced_lhs_ty = sema.typeOf(uncoerced_lhs);
13874 const src: LazySrcLoc = block.nodeOffset(inst_data.src_node);
13875 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
13876 const operator_src = block.src(.{ .node_offset_main_token = inst_data.src_node });
13877 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
13878
13879 const lhs, const lhs_ty = coerced_lhs: {
13880 // If we have a result type, we might be able to do this more efficiently
13881 // by coercing the LHS first. Specifically, if we want an array or vector
13882 // and have a tuple, coerce the tuple immediately.
13883 no_coerce: {
13884 if (extra.res_ty == .none) break :no_coerce;
13885 const res_ty = try sema.resolveTypeOrPoison(block, src, extra.res_ty) orelse break :no_coerce;
13886 if (!uncoerced_lhs_ty.isTuple(zcu)) break :no_coerce;
13887 const lhs_len = uncoerced_lhs_ty.structFieldCount(zcu);
13888 const lhs_dest_ty = switch (res_ty.zigTypeTag(zcu)) {
13889 else => break :no_coerce,
13890 .array => try pt.arrayType(.{
13891 .child = res_ty.childType(zcu).toIntern(),
13892 .len = lhs_len,
13893 .sentinel = if (res_ty.sentinel(zcu)) |s| s.toIntern() else .none,
13894 }),
13895 .vector => try pt.vectorType(.{
13896 .child = res_ty.childType(zcu).toIntern(),
13897 .len = lhs_len,
13898 }),
13899 };
13900 // Attempt to coerce to this type, but don't emit an error if it fails. Instead,
13901 // just exit out of this path and let the usual error happen later, so that error
13902 // messages are consistent.
13903 const coerced = sema.coerceExtra(block, lhs_dest_ty, uncoerced_lhs, lhs_src, .{ .report_err = false }) catch |err| switch (err) {
13904 error.NotCoercible => break :no_coerce,
13905 else => |e| return e,
13906 };
13907 break :coerced_lhs .{ coerced, lhs_dest_ty };
13908 }
13909 break :coerced_lhs .{ uncoerced_lhs, uncoerced_lhs_ty };
13910 };
13911
13912 if (lhs_ty.isTuple(zcu)) {
13913 // In `**` rhs must be comptime-known, but lhs can be runtime-known
13914 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, .usize, .{ .simple = .array_mul_factor });
13915 const factor_casted = try sema.usizeCast(block, rhs_src, factor);
13916 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor_casted);
13917 }
13918
13919 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
13920 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
13921 const msg = msg: {
13922 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
13923 errdefer msg.destroy(sema.gpa);
13924 switch (lhs_ty.zigTypeTag(zcu)) {
13925 .int, .float, .comptime_float, .comptime_int, .vector => {
13926 try sema.errNote(operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});
13927 },
13928 else => {},
13929 }
13930 break :msg msg;
13931 };
13932 return sema.failWithOwnedErrorMsg(block, msg);
13933 };
13934
13935 // In `**` rhs must be comptime-known, but lhs can be runtime-known
13936 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, .usize, .{ .simple = .array_mul_factor });
13937
13938 const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch
13939 return sema.fail(block, rhs_src, "operation results in overflow", .{});
13940 const result_len = try sema.usizeCast(block, src, result_len_u64);
13941
13942 const result_ty = try pt.arrayType(.{
13943 .len = result_len,
13944 .sentinel = if (lhs_info.sentinel) |s| s.toIntern() else .none,
13945 .child = lhs_info.elem_type.toIntern(),
13946 });
13947
13948 const ptr_addrspace = if (lhs_ty.zigTypeTag(zcu) == .pointer) lhs_ty.ptrAddressSpace(zcu) else null;
13949 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
13950
13951 if (sema.resolveValue(lhs)) |lhs_val| ct: {
13952 const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu))
13953 try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :ct
13954 else if (lhs_ty.isSlice(zcu))
13955 try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :ct
13956 else
13957 lhs_val;
13958
13959 const val = v: {
13960 // Optimization for the common pattern of a single element repeated N times, such
13961 // as zero-filling a byte array.
13962 if (lhs_len == 1 and lhs_info.sentinel == null) {
13963 const elem_val = try lhs_sub_val.elemValue(pt, 0);
13964 break :v try pt.aggregateSplatValue(result_ty, elem_val);
13965 }
13966
13967 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
13968 var elem_i: usize = 0;
13969 while (elem_i < result_len) {
13970 var lhs_i: usize = 0;
13971 while (lhs_i < lhs_len) : (lhs_i += 1) {
13972 const elem_val = try lhs_sub_val.elemValue(pt, lhs_i);
13973 element_vals[elem_i] = elem_val.toIntern();
13974 elem_i += 1;
13975 }
13976 }
13977 break :v try pt.aggregateValue(result_ty, element_vals);
13978 };
13979 return sema.addConstantMaybeRef(val, ptr_addrspace != null);
13980 }
13981
13982 try sema.requireRuntimeBlock(block, src, lhs_src);
13983
13984 // Grab all the LHS values ahead of time, rather than repeatedly emitting instructions
13985 // to get the same elem values.
13986 const lhs_vals = try sema.arena.alloc(Air.Inst.Ref, lhs_len);
13987 for (lhs_vals, 0..) |*lhs_val, idx| {
13988 const idx_ref = try pt.intRef(.usize, idx);
13989 lhs_val.* = try sema.elemVal(block, lhs_src, lhs, idx_ref, src, false);
13990 }
13991
13992 if (ptr_addrspace) |ptr_as| {
13993 const alloc_ty = try pt.ptrType(.{
13994 .child = result_ty.toIntern(),
13995 .flags = .{
13996 .address_space = ptr_as,
13997 .is_const = true,
13998 },
13999 });
14000 const alloc = try block.addTy(.alloc, alloc_ty);
14001 const elem_ptr_ty = try pt.ptrType(.{
14002 .child = lhs_info.elem_type.toIntern(),
14003 .flags = .{ .address_space = ptr_as },
14004 });
14005
14006 var elem_i: usize = 0;
14007 while (elem_i < result_len) {
14008 for (lhs_vals) |lhs_val| {
14009 const elem_index = try pt.intRef(.usize, elem_i);
14010 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
14011 try sema.storePtr2(block, src, elem_ptr, src, lhs_val, lhs_src, .store);
14012 elem_i += 1;
14013 }
14014 }
14015 if (lhs_info.sentinel) |sent_val| {
14016 const elem_index = try pt.intRef(.usize, result_len);
14017 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
14018 const init = Air.internedToRef(sent_val.toIntern());
14019 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
14020 }
14021
14022 return alloc;
14023 }
14024
14025 const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);
14026 for (0..try sema.usizeCast(block, rhs_src, factor)) |i| {
14027 @memcpy(element_refs[i * lhs_len ..][0..lhs_len], lhs_vals);
14028 }
14029 return block.addAggregateInit(result_ty, element_refs);
14030}
14031
14032fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13863fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14033 const pt = sema.pt;13864 const pt = sema.pt;
14034 const zcu = pt.zcu;13865 const zcu = pt.zcu;
src/print_zir.zig-14
...@@ -416,8 +416,6 @@ const Writer = struct {...@@ -416,8 +416,6 @@ const Writer = struct {
416416
417 .for_len => try self.writePlNodeMultiOp(stream, inst),417 .for_len => try self.writePlNodeMultiOp(stream, inst),
418418
419 .array_mul => try self.writeArrayMul(stream, inst),
420
421 .elem_val_imm => try self.writeElemValImm(stream, inst),419 .elem_val_imm => try self.writeElemValImm(stream, inst),
422420
423 .@"export" => try self.writePlNodeExport(stream, inst),421 .@"export" => try self.writePlNodeExport(stream, inst),
...@@ -1046,18 +1044,6 @@ const Writer = struct {...@@ -1046,18 +1044,6 @@ const Writer = struct {
1046 try self.writeSrcNode(stream, inst_data.src_node);1044 try self.writeSrcNode(stream, inst_data.src_node);
1047 }1045 }
10481046
1049 fn writeArrayMul(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1050 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1051 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;
1052 try self.writeInstRef(stream, extra.res_ty);
1053 try stream.writeAll(", ");
1054 try self.writeInstRef(stream, extra.lhs);
1055 try stream.writeAll(", ");
1056 try self.writeInstRef(stream, extra.rhs);
1057 try stream.writeAll(") ");
1058 try self.writeSrcNode(stream, inst_data.src_node);
1059 }
1060
1061 fn writeElemValImm(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {1047 fn writeElemValImm(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1062 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;1048 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;
1063 try self.writeInstRef(stream, inst_data.operand);1049 try self.writeInstRef(stream, inst_data.operand);
tools/docgen.zig+1-2
...@@ -871,7 +871,6 @@ fn tokenizeAndPrintRaw(...@@ -871,7 +871,6 @@ fn tokenizeAndPrintRaw(
871 .minus_pipe_equal,871 .minus_pipe_equal,
872 .asterisk,872 .asterisk,
873 .asterisk_equal,873 .asterisk_equal,
874 .asterisk_asterisk,
875 .asterisk_percent,874 .asterisk_percent,
876 .asterisk_percent_equal,875 .asterisk_percent_equal,
877 .asterisk_pipe,876 .asterisk_pipe,
...@@ -897,7 +896,7 @@ fn tokenizeAndPrintRaw(...@@ -897,7 +896,7 @@ fn tokenizeAndPrintRaw(
897 .tilde,896 .tilde,
898 => try writeEscaped(out, src[token.loc.start..token.loc.end]),897 => try writeEscaped(out, src[token.loc.start..token.loc.end]),
899898
900 .invalid, .invalid_periodasterisks => return parseError(899 .invalid => return parseError(
901 docgen_tokenizer,900 docgen_tokenizer,
902 source_token,901 source_token,
903 "syntax error",902 "syntax error",
tools/doctest.zig+1-2
...@@ -800,7 +800,6 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {...@@ -800,7 +800,6 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
800 .minus_pipe_equal,800 .minus_pipe_equal,
801 .asterisk,801 .asterisk,
802 .asterisk_equal,802 .asterisk_equal,
803 .asterisk_asterisk,
804 .asterisk_percent,803 .asterisk_percent,
805 .asterisk_percent_equal,804 .asterisk_percent_equal,
806 .asterisk_pipe,805 .asterisk_pipe,
...@@ -826,7 +825,7 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {...@@ -826,7 +825,7 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
826 .tilde,825 .tilde,
827 => try writeEscaped(out, src[token.loc.start..token.loc.end]),826 => try writeEscaped(out, src[token.loc.start..token.loc.end]),
828827
829 .invalid, .invalid_periodasterisks => fatal("syntax error", .{}),828 .invalid => fatal("syntax error", .{}),
830 }829 }
831 index = token.loc.end;830 index = token.loc.end;
832 }831 }