authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-18 13:53:47+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-18 13:53:47+02:00
log53241f288e40a9e97a5425cb0e1ac7dbbc9de852
treed63dda15c2615440408100e213e8c97dfd7c4d52
parent56e9575e827208b3df5c90472826f52bfc8342c0
parent6b65590715d0871c11635fc49cb1fc471a60ea59
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10913 from Vexu/err

further parser error improvements

10 files changed, 353 insertions(+), 254 deletions(-)

doc/langref.html.in+1-1
......@@ -10405,7 +10405,7 @@ pub fn main() !void {
1040510405 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.
1040610406 This is why it is an error to pass a string literal to a mutable slice, like this:
1040710407 </p>
10408 {#code_begin|test_err|expected type '[]u8'#}
10408 {#code_begin|test_err|cannot cast pointer to array literal to slice type '[]u8'#}
1040910409fn foo(s: []u8) void {
1041010410 _ = s;
1041110411}
lib/std/zig/Ast.zig+46-48
......@@ -66,20 +66,11 @@ pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8)) RenderError!void
6666
6767/// Returns an extra offset for column and byte offset of errors that
6868/// should point after the token in the error message.
69pub fn errorOffset(tree: Ast, error_tag: Error.Tag, token: TokenIndex) u32 {
70 return switch (error_tag) {
71 .expected_semi_after_decl,
72 .expected_semi_after_stmt,
73 .expected_comma_after_field,
74 .expected_comma_after_arg,
75 .expected_comma_after_param,
76 .expected_comma_after_initializer,
77 .expected_comma_after_switch_prong,
78 .expected_semi_or_else,
79 .expected_semi_or_lbrace,
80 => @intCast(u32, tree.tokenSlice(token).len),
81 else => 0,
82 };
69pub fn errorOffset(tree: Ast, parse_error: Error) u32 {
70 return if (parse_error.token_is_prev)
71 @intCast(u32, tree.tokenSlice(parse_error.token).len)
72 else
73 0;
8374}
8475
8576pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {
......@@ -162,22 +153,22 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
162153 },
163154 .expected_block => {
164155 return stream.print("expected block or field, found '{s}'", .{
165 token_tags[parse_error.token].symbol(),
156 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
166157 });
167158 },
168159 .expected_block_or_assignment => {
169160 return stream.print("expected block or assignment, found '{s}'", .{
170 token_tags[parse_error.token].symbol(),
161 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
171162 });
172163 },
173164 .expected_block_or_expr => {
174165 return stream.print("expected block or expression, found '{s}'", .{
175 token_tags[parse_error.token].symbol(),
166 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
176167 });
177168 },
178169 .expected_block_or_field => {
179170 return stream.print("expected block or field, found '{s}'", .{
180 token_tags[parse_error.token].symbol(),
171 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
181172 });
182173 },
183174 .expected_container_members => {
......@@ -187,42 +178,42 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
187178 },
188179 .expected_expr => {
189180 return stream.print("expected expression, found '{s}'", .{
190 token_tags[parse_error.token].symbol(),
181 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
191182 });
192183 },
193184 .expected_expr_or_assignment => {
194185 return stream.print("expected expression or assignment, found '{s}'", .{
195 token_tags[parse_error.token].symbol(),
186 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
196187 });
197188 },
198189 .expected_fn => {
199190 return stream.print("expected function, found '{s}'", .{
200 token_tags[parse_error.token].symbol(),
191 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
201192 });
202193 },
203194 .expected_inlinable => {
204195 return stream.print("expected 'while' or 'for', found '{s}'", .{
205 token_tags[parse_error.token].symbol(),
196 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
206197 });
207198 },
208199 .expected_labelable => {
209200 return stream.print("expected 'while', 'for', 'inline', 'suspend', or '{{', found '{s}'", .{
210 token_tags[parse_error.token].symbol(),
201 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
211202 });
212203 },
213204 .expected_param_list => {
214205 return stream.print("expected parameter list, found '{s}'", .{
215 token_tags[parse_error.token].symbol(),
206 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
216207 });
217208 },
218209 .expected_prefix_expr => {
219210 return stream.print("expected prefix expression, found '{s}'", .{
220 token_tags[parse_error.token].symbol(),
211 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
221212 });
222213 },
223214 .expected_primary_type_expr => {
224215 return stream.print("expected primary type expression, found '{s}'", .{
225 token_tags[parse_error.token].symbol(),
216 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
226217 });
227218 },
228219 .expected_pub_item => {
......@@ -230,7 +221,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
230221 },
231222 .expected_return_type => {
232223 return stream.print("expected return type expression, found '{s}'", .{
233 token_tags[parse_error.token].symbol(),
224 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
234225 });
235226 },
236227 .expected_semi_or_else => {
......@@ -244,39 +235,34 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
244235 token_tags[parse_error.token].symbol(),
245236 });
246237 },
247 .expected_string_literal => {
248 return stream.print("expected string literal, found '{s}'", .{
249 token_tags[parse_error.token].symbol(),
250 });
251 },
252238 .expected_suffix_op => {
253239 return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
254 token_tags[parse_error.token].symbol(),
240 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
255241 });
256242 },
257243 .expected_type_expr => {
258244 return stream.print("expected type expression, found '{s}'", .{
259 token_tags[parse_error.token].symbol(),
245 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
260246 });
261247 },
262248 .expected_var_decl => {
263249 return stream.print("expected variable declaration, found '{s}'", .{
264 token_tags[parse_error.token].symbol(),
250 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
265251 });
266252 },
267253 .expected_var_decl_or_fn => {
268254 return stream.print("expected variable declaration or function, found '{s}'", .{
269 token_tags[parse_error.token].symbol(),
255 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
270256 });
271257 },
272258 .expected_loop_payload => {
273259 return stream.print("expected loop payload, found '{s}'", .{
274 token_tags[parse_error.token].symbol(),
260 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
275261 });
276262 },
277263 .expected_container => {
278264 return stream.print("expected a struct, enum or union, found '{s}'", .{
279 token_tags[parse_error.token].symbol(),
265 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
280266 });
281267 },
282268 .extern_fn_body => {
......@@ -305,11 +291,6 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
305291 .invalid_bit_range => {
306292 return stream.writeAll("bit range not allowed on slices and arrays");
307293 },
308 .invalid_token => {
309 return stream.print("invalid token: '{s}'", .{
310 token_tags[parse_error.token].symbol(),
311 });
312 },
313294 .same_line_doc_comment => {
314295 return stream.writeAll("same line documentation comment");
315296 },
......@@ -319,6 +300,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
319300 .varargs_nonfinal => {
320301 return stream.writeAll("function prototype has parameter after varargs");
321302 },
303 .expected_continue_expr => {
304 return stream.writeAll("expected ':' before while continue expression");
305 },
322306
323307 .expected_semi_after_decl => {
324308 return stream.writeAll("expected ';' after declaration");
......@@ -341,9 +325,19 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
341325 .expected_comma_after_switch_prong => {
342326 return stream.writeAll("expected ',' after switch prong");
343327 },
328 .expected_initializer => {
329 return stream.writeAll("expected field initializer");
330 },
331
332 .previous_field => {
333 return stream.writeAll("field before declarations here");
334 },
335 .next_field => {
336 return stream.writeAll("field after declarations here");
337 },
344338
345339 .expected_token => {
346 const found_tag = token_tags[parse_error.token];
340 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
347341 const expected_symbol = parse_error.extra.expected_tag.symbol();
348342 switch (found_tag) {
349343 .invalid => return stream.print("expected '{s}', found invalid bytes", .{
......@@ -2483,6 +2477,9 @@ pub const full = struct {
24832477
24842478pub const Error = struct {
24852479 tag: Tag,
2480 is_note: bool = false,
2481 /// True if `token` points to the token before the token causing an issue.
2482 token_is_prev: bool = false,
24862483 token: TokenIndex,
24872484 extra: union {
24882485 none: void,
......@@ -2511,7 +2508,6 @@ pub const Error = struct {
25112508 expected_semi_or_else,
25122509 expected_semi_or_lbrace,
25132510 expected_statement,
2514 expected_string_literal,
25152511 expected_suffix_op,
25162512 expected_type_expr,
25172513 expected_var_decl,
......@@ -2526,12 +2522,10 @@ pub const Error = struct {
25262522 extra_volatile_qualifier,
25272523 ptr_mod_on_array_child_type,
25282524 invalid_bit_range,
2529 invalid_token,
25302525 same_line_doc_comment,
25312526 unattached_doc_comment,
25322527 varargs_nonfinal,
2533
2534 // these have `token` set to token after which a semicolon was expected
2528 expected_continue_expr,
25352529 expected_semi_after_decl,
25362530 expected_semi_after_stmt,
25372531 expected_comma_after_field,
......@@ -2539,6 +2533,10 @@ pub const Error = struct {
25392533 expected_comma_after_param,
25402534 expected_comma_after_initializer,
25412535 expected_comma_after_switch_prong,
2536 expected_initializer,
2537
2538 previous_field,
2539 next_field,
25422540
25432541 /// `expected_tag` is populated.
25442542 expected_token,
lib/std/zig/parse.zig+106-99
......@@ -91,6 +91,9 @@ const Parser = struct {
9191 extra_data: std.ArrayListUnmanaged(Node.Index),
9292 scratch: std.ArrayListUnmanaged(Node.Index),
9393
94 /// Used for the error note of decl_between_fields error.
95 last_field: TokenIndex = undefined,
96
9497 const SmallSpan = union(enum) {
9598 zero_or_one: Node.Index,
9699 multi: Node.SubRange,
......@@ -147,11 +150,6 @@ const Parser = struct {
147150 return result;
148151 }
149152
150 fn warn(p: *Parser, tag: Ast.Error.Tag) error{OutOfMemory}!void {
151 @setCold(true);
152 try p.warnMsg(.{ .tag = tag, .token = p.tok_i });
153 }
154
155153 fn warnExpected(p: *Parser, expected_token: Token.Tag) error{OutOfMemory}!void {
156154 @setCold(true);
157155 try p.warnMsg(.{
......@@ -161,13 +159,53 @@ const Parser = struct {
161159 });
162160 }
163161
164 fn warnExpectedAfter(p: *Parser, error_tag: AstError.Tag) error{OutOfMemory}!void {
162 fn warn(p: *Parser, error_tag: AstError.Tag) error{OutOfMemory}!void {
165163 @setCold(true);
166 try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i - 1 });
164 try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i });
167165 }
168166
169167 fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void {
170168 @setCold(true);
169 switch (msg.tag) {
170 .expected_semi_after_decl,
171 .expected_semi_after_stmt,
172 .expected_comma_after_field,
173 .expected_comma_after_arg,
174 .expected_comma_after_param,
175 .expected_comma_after_initializer,
176 .expected_comma_after_switch_prong,
177 .expected_semi_or_else,
178 .expected_semi_or_lbrace,
179 .expected_token,
180 .expected_block,
181 .expected_block_or_assignment,
182 .expected_block_or_expr,
183 .expected_block_or_field,
184 .expected_container_members,
185 .expected_expr,
186 .expected_expr_or_assignment,
187 .expected_fn,
188 .expected_inlinable,
189 .expected_labelable,
190 .expected_param_list,
191 .expected_prefix_expr,
192 .expected_primary_type_expr,
193 .expected_pub_item,
194 .expected_return_type,
195 .expected_suffix_op,
196 .expected_type_expr,
197 .expected_var_decl,
198 .expected_var_decl_or_fn,
199 .expected_loop_payload,
200 .expected_container,
201 => if (msg.token != 0 and !p.tokensOnSameLine(msg.token - 1, msg.token)) {
202 var copy = msg;
203 copy.token_is_prev = true;
204 copy.token -= 1;
205 return p.errors.append(p.gpa, copy);
206 },
207 else => {},
208 }
171209 try p.errors.append(p.gpa, msg);
172210 }
173211
......@@ -235,6 +273,8 @@ const Parser = struct {
235273 .keyword_comptime => switch (p.token_tags[p.tok_i + 1]) {
236274 .identifier => {
237275 p.tok_i += 1;
276 const identifier = p.tok_i;
277 defer p.last_field = identifier;
238278 const container_field = try p.expectContainerFieldRecoverable();
239279 if (container_field != 0) {
240280 switch (field_state) {
......@@ -245,6 +285,16 @@ const Parser = struct {
245285 .tag = .decl_between_fields,
246286 .token = p.nodes.items(.main_token)[node],
247287 });
288 try p.warnMsg(.{
289 .tag = .previous_field,
290 .is_note = true,
291 .token = p.last_field,
292 });
293 try p.warnMsg(.{
294 .tag = .next_field,
295 .is_note = true,
296 .token = identifier,
297 });
248298 // Continue parsing; error will be reported later.
249299 field_state = .err;
250300 },
......@@ -264,7 +314,7 @@ const Parser = struct {
264314 }
265315 // There is not allowed to be a decl after a field with no comma.
266316 // Report error but recover parser.
267 try p.warnExpectedAfter(.expected_comma_after_field);
317 try p.warn(.expected_comma_after_field);
268318 p.findNextContainerMember();
269319 }
270320 },
......@@ -338,6 +388,8 @@ const Parser = struct {
338388 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
339389 },
340390 .identifier => {
391 const identifier = p.tok_i;
392 defer p.last_field = identifier;
341393 const container_field = try p.expectContainerFieldRecoverable();
342394 if (container_field != 0) {
343395 switch (field_state) {
......@@ -348,6 +400,14 @@ const Parser = struct {
348400 .tag = .decl_between_fields,
349401 .token = p.nodes.items(.main_token)[node],
350402 });
403 try p.warnMsg(.{
404 .tag = .previous_field,
405 .token = p.last_field,
406 });
407 try p.warnMsg(.{
408 .tag = .next_field,
409 .token = identifier,
410 });
351411 // Continue parsing; error will be reported later.
352412 field_state = .err;
353413 },
......@@ -367,7 +427,7 @@ const Parser = struct {
367427 }
368428 // There is not allowed to be a decl after a field with no comma.
369429 // Report error but recover parser.
370 try p.warnExpectedAfter(.expected_comma_after_field);
430 try p.warn(.expected_comma_after_field);
371431 p.findNextContainerMember();
372432 }
373433 },
......@@ -585,7 +645,7 @@ const Parser = struct {
585645 // Since parseBlock only return error.ParseError on
586646 // a missing '}' we can assume this function was
587647 // supposed to end here.
588 try p.warnExpectedAfter(.expected_semi_or_lbrace);
648 try p.warn(.expected_semi_or_lbrace);
589649 return null_node;
590650 },
591651 }
......@@ -996,7 +1056,7 @@ const Parser = struct {
9961056 };
9971057 _ = p.eatToken(.keyword_else) orelse {
9981058 if (else_required) {
999 try p.warnExpectedAfter(.expected_semi_or_else);
1059 try p.warn(.expected_semi_or_else);
10001060 }
10011061 return p.addNode(.{
10021062 .tag = .if_simple,
......@@ -1091,7 +1151,7 @@ const Parser = struct {
10911151 };
10921152 _ = p.eatToken(.keyword_else) orelse {
10931153 if (else_required) {
1094 try p.warnExpectedAfter(.expected_semi_or_else);
1154 try p.warn(.expected_semi_or_else);
10951155 }
10961156 return p.addNode(.{
10971157 .tag = .for_simple,
......@@ -1166,7 +1226,7 @@ const Parser = struct {
11661226 };
11671227 _ = p.eatToken(.keyword_else) orelse {
11681228 if (else_required) {
1169 try p.warnExpectedAfter(.expected_semi_or_else);
1229 try p.warn(.expected_semi_or_else);
11701230 }
11711231 if (cont_expr == 0) {
11721232 return p.addNode(.{
......@@ -1402,7 +1462,8 @@ const Parser = struct {
14021462 }
14031463 const rhs = try p.parseExprPrecedence(info.prec + 1);
14041464 if (rhs == 0) {
1405 return p.fail(.invalid_token);
1465 try p.warn(.expected_expr);
1466 return node;
14061467 }
14071468
14081469 node = try p.addNode(.{
......@@ -1881,7 +1942,7 @@ const Parser = struct {
18811942
18821943 /// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
18831944 fn parseIfExpr(p: *Parser) !Node.Index {
1884 return p.parseIf(parseExpr);
1945 return p.parseIf(expectExpr);
18851946 }
18861947
18871948 /// Block <- LBRACE Statement* RBRACE
......@@ -2050,7 +2111,7 @@ const Parser = struct {
20502111 },
20512112 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
20522113 // Likely just a missing comma; give error but continue parsing.
2053 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
2114 else => try p.warn(.expected_comma_after_initializer),
20542115 }
20552116 if (p.eatToken(.r_brace)) |_| break;
20562117 const next = try p.expectFieldInit();
......@@ -2091,7 +2152,7 @@ const Parser = struct {
20912152 },
20922153 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
20932154 // Likely just a missing comma; give error but continue parsing.
2094 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
2155 else => try p.warn(.expected_comma_after_initializer),
20952156 }
20962157 }
20972158 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2170,7 +2231,7 @@ const Parser = struct {
21702231 },
21712232 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
21722233 // Likely just a missing comma; give error but continue parsing.
2173 else => try p.warnExpectedAfter(.expected_comma_after_arg),
2234 else => try p.warn(.expected_comma_after_arg),
21742235 }
21752236 }
21762237 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2226,7 +2287,7 @@ const Parser = struct {
22262287 },
22272288 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
22282289 // Likely just a missing comma; give error but continue parsing.
2229 else => try p.warnExpectedAfter(.expected_comma_after_arg),
2290 else => try p.warn(.expected_comma_after_arg),
22302291 }
22312292 }
22322293 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2349,7 +2410,7 @@ const Parser = struct {
23492410
23502411 .builtin => return p.parseBuiltinCall(),
23512412 .keyword_fn => return p.parseFnProto(),
2352 .keyword_if => return p.parseIf(parseTypeExpr),
2413 .keyword_if => return p.parseIf(expectTypeExpr),
23532414 .keyword_switch => return p.expectSwitchExpr(),
23542415
23552416 .keyword_extern,
......@@ -2467,7 +2528,7 @@ const Parser = struct {
24672528 },
24682529 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
24692530 // Likely just a missing comma; give error but continue parsing.
2470 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
2531 else => try p.warn(.expected_comma_after_initializer),
24712532 }
24722533 if (p.eatToken(.r_brace)) |_| break;
24732534 const next = try p.expectFieldInit();
......@@ -2519,7 +2580,7 @@ const Parser = struct {
25192580 },
25202581 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
25212582 // Likely just a missing comma; give error but continue parsing.
2522 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
2583 else => try p.warn(.expected_comma_after_initializer),
25232584 }
25242585 }
25252586 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2580,7 +2641,7 @@ const Parser = struct {
25802641 },
25812642 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
25822643 // Likely just a missing comma; give error but continue parsing.
2583 else => try p.warnExpectedAfter(.expected_comma_after_field),
2644 else => try p.warn(.expected_comma_after_field),
25842645 }
25852646 }
25862647 return p.addNode(.{
......@@ -2879,7 +2940,7 @@ const Parser = struct {
28792940 p.tok_i += 2;
28802941 return identifier;
28812942 }
2882 return 0;
2943 return null_node;
28832944 }
28842945
28852946 /// FieldInit <- DOT IDENTIFIER EQUAL Expr
......@@ -2896,15 +2957,23 @@ const Parser = struct {
28962957 }
28972958
28982959 fn expectFieldInit(p: *Parser) !Node.Index {
2899 _ = try p.expectToken(.period);
2900 _ = try p.expectToken(.identifier);
2901 _ = try p.expectToken(.equal);
2960 if (p.token_tags[p.tok_i] != .period or
2961 p.token_tags[p.tok_i + 1] != .identifier or
2962 p.token_tags[p.tok_i + 2] != .equal)
2963 return p.fail(.expected_initializer);
2964
2965 p.tok_i += 3;
29022966 return p.expectExpr();
29032967 }
29042968
29052969 /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
29062970 fn parseWhileContinueExpr(p: *Parser) !Node.Index {
2907 _ = p.eatToken(.colon) orelse return null_node;
2971 _ = p.eatToken(.colon) orelse {
2972 if (p.token_tags[p.tok_i] == .l_paren and
2973 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
2974 return p.fail(.expected_continue_expr);
2975 return null_node;
2976 };
29082977 _ = try p.expectToken(.l_paren);
29092978 const node = try p.parseAssignExpr();
29102979 if (node == 0) return p.fail(.expected_expr_or_assignment);
......@@ -3413,7 +3482,7 @@ const Parser = struct {
34133482 // All possible delimiters.
34143483 .colon, .r_paren, .r_brace, .r_bracket => break,
34153484 // Likely just a missing comma; give error but continue parsing.
3416 else => try p.warnExpectedAfter(.expected_comma_after_switch_prong),
3485 else => try p.warn(.expected_comma_after_switch_prong),
34173486 }
34183487 }
34193488 return p.listToSpan(p.scratch.items[scratch_top..]);
......@@ -3442,7 +3511,7 @@ const Parser = struct {
34423511 },
34433512 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
34443513 // Likely just a missing comma; give error but continue parsing.
3445 else => try p.warnExpectedAfter(.expected_comma_after_param),
3514 else => try p.warn(.expected_comma_after_param),
34463515 }
34473516 }
34483517 if (varargs == .nonfinal) {
......@@ -3486,7 +3555,7 @@ const Parser = struct {
34863555 break;
34873556 },
34883557 // Likely just a missing comma; give error but continue parsing.
3489 else => try p.warnExpectedAfter(.expected_comma_after_arg),
3558 else => try p.warn(.expected_comma_after_arg),
34903559 }
34913560 }
34923561 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -3530,57 +3599,6 @@ const Parser = struct {
35303599 }
35313600 }
35323601
3533 // string literal or multiline string literal
3534 fn parseStringLiteral(p: *Parser) !Node.Index {
3535 switch (p.token_tags[p.tok_i]) {
3536 .string_literal => {
3537 const main_token = p.nextToken();
3538 return p.addNode(.{
3539 .tag = .string_literal,
3540 .main_token = main_token,
3541 .data = .{
3542 .lhs = undefined,
3543 .rhs = undefined,
3544 },
3545 });
3546 },
3547 .multiline_string_literal_line => {
3548 const first_line = p.nextToken();
3549 while (p.token_tags[p.tok_i] == .multiline_string_literal_line) {
3550 p.tok_i += 1;
3551 }
3552 return p.addNode(.{
3553 .tag = .multiline_string_literal,
3554 .main_token = first_line,
3555 .data = .{
3556 .lhs = first_line,
3557 .rhs = p.tok_i - 1,
3558 },
3559 });
3560 },
3561 else => return null_node,
3562 }
3563 }
3564
3565 fn expectStringLiteral(p: *Parser) !Node.Index {
3566 const node = try p.parseStringLiteral();
3567 if (node == 0) {
3568 return p.fail(.expected_string_literal);
3569 }
3570 return node;
3571 }
3572
3573 fn expectIntegerLiteral(p: *Parser) !Node.Index {
3574 return p.addNode(.{
3575 .tag = .integer_literal,
3576 .main_token = try p.expectToken(.integer_literal),
3577 .data = .{
3578 .lhs = undefined,
3579 .rhs = undefined,
3580 },
3581 });
3582 }
3583
35843602 /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
35853603 fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
35863604 const if_token = p.eatToken(.keyword_if) orelse return null_node;
......@@ -3590,7 +3608,7 @@ const Parser = struct {
35903608 _ = try p.parsePtrPayload();
35913609
35923610 const then_expr = try bodyParseFn(p);
3593 if (then_expr == 0) return p.fail(.invalid_token);
3611 assert(then_expr != 0);
35943612
35953613 _ = p.eatToken(.keyword_else) orelse return p.addNode(.{
35963614 .tag = .if_simple,
......@@ -3602,7 +3620,7 @@ const Parser = struct {
36023620 });
36033621 _ = try p.parsePayload();
36043622 const else_expr = try bodyParseFn(p);
3605 if (else_expr == 0) return p.fail(.invalid_token);
3623 assert(then_expr != 0);
36063624
36073625 return p.addNode(.{
36083626 .tag = .@"if",
......@@ -3649,25 +3667,14 @@ const Parser = struct {
36493667 }
36503668
36513669 fn expectToken(p: *Parser, tag: Token.Tag) Error!TokenIndex {
3652 const token = p.nextToken();
3653 if (p.token_tags[token] != tag) {
3654 p.tok_i -= 1; // Go back so that we can recover properly.
3670 if (p.token_tags[p.tok_i] != tag) {
36553671 return p.failMsg(.{
36563672 .tag = .expected_token,
3657 .token = token,
3673 .token = p.tok_i,
36583674 .extra = .{ .expected_tag = tag },
36593675 });
36603676 }
3661 return token;
3662 }
3663
3664 fn expectTokenRecoverable(p: *Parser, tag: Token.Tag) !?TokenIndex {
3665 if (p.token_tags[p.tok_i] != tag) {
3666 try p.warnExpected(tag);
3667 return null;
3668 } else {
3669 return p.nextToken();
3670 }
3677 return p.nextToken();
36713678 }
36723679
36733680 fn expectSemicolon(p: *Parser, error_tag: AstError.Tag, recoverable: bool) Error!void {
......@@ -3675,7 +3682,7 @@ const Parser = struct {
36753682 _ = p.nextToken();
36763683 return;
36773684 }
3678 try p.warnExpectedAfter(error_tag);
3685 try p.warn(error_tag);
36793686 if (!recoverable) return error.ParseError;
36803687 }
36813688
lib/std/zig/parser_test.zig+25-2
......@@ -226,6 +226,8 @@ test "zig fmt: decl between fields" {
226226 \\};
227227 , &[_]Error{
228228 .decl_between_fields,
229 .previous_field,
230 .next_field,
229231 });
230232}
231233
......@@ -5018,6 +5020,25 @@ test "zig fmt: make single-line if no trailing comma" {
50185020 );
50195021}
50205022
5023test "zig fmt: while continue expr" {
5024 try testCanonical(
5025 \\test {
5026 \\ while (i > 0)
5027 \\ (i * 2);
5028 \\}
5029 \\
5030 );
5031 try testError(
5032 \\test {
5033 \\ while (i > 0) (i -= 1) {
5034 \\ print("test123", .{});
5035 \\ }
5036 \\}
5037 , &[_]Error{
5038 .expected_continue_expr,
5039 });
5040}
5041
50215042test "zig fmt: error for invalid bit range" {
50225043 try testError(
50235044 \\var x: []align(0:0:0)u8 = bar;
......@@ -5057,7 +5078,9 @@ test "recovery: block statements" {
50575078 \\ inline;
50585079 \\}
50595080 , &[_]Error{
5060 .invalid_token,
5081 .expected_expr,
5082 .expected_semi_after_stmt,
5083 .expected_statement,
50615084 .expected_inlinable,
50625085 });
50635086}
......@@ -5076,7 +5099,7 @@ test "recovery: missing comma" {
50765099 , &[_]Error{
50775100 .expected_comma_after_switch_prong,
50785101 .expected_comma_after_switch_prong,
5079 .invalid_token,
5102 .expected_expr,
50805103 });
50815104}
50825105
lib/std/zig/tokenizer.zig+12-1
......@@ -322,7 +322,18 @@ pub const Token = struct {
322322 }
323323
324324 pub fn symbol(tag: Tag) []const u8 {
325 return tag.lexeme() orelse @tagName(tag);
325 return tag.lexeme() orelse switch (tag) {
326 .invalid => "invalid bytes",
327 .identifier => "an identifier",
328 .string_literal, .multiline_string_literal_line => "a string literal",
329 .char_literal => "a character literal",
330 .eof => "EOF",
331 .builtin => "a builtin function",
332 .integer_literal => "an integer literal",
333 .float_literal => "a floating point literal",
334 .doc_comment, .container_doc_comment => "a document comment",
335 else => unreachable,
336 };
326337 }
327338 };
328339};
src/Module.zig+15-4
......@@ -2995,7 +2995,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
29952995 const token_starts = file.tree.tokens.items(.start);
29962996 const token_tags = file.tree.tokens.items(.tag);
29972997
2998 const extra_offset = file.tree.errorOffset(parse_err.tag, parse_err.token);
2998 const extra_offset = file.tree.errorOffset(parse_err);
29992999 try file.tree.renderError(parse_err, msg.writer());
30003000 const err_msg = try gpa.create(ErrorMsg);
30013001 err_msg.* = .{
......@@ -3006,14 +3006,25 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
30063006 },
30073007 .msg = msg.toOwnedSlice(),
30083008 };
3009 if (token_tags[parse_err.token] == .invalid) {
3010 const bad_off = @intCast(u32, file.tree.tokenSlice(parse_err.token).len);
3011 const byte_abs = token_starts[parse_err.token] + bad_off;
3009 if (token_tags[parse_err.token + @boolToInt(parse_err.token_is_prev)] == .invalid) {
3010 const bad_off = @intCast(u32, file.tree.tokenSlice(parse_err.token + @boolToInt(parse_err.token_is_prev)).len);
3011 const byte_abs = token_starts[parse_err.token + @boolToInt(parse_err.token_is_prev)] + bad_off;
30123012 try mod.errNoteNonLazy(.{
30133013 .file_scope = file,
30143014 .parent_decl_node = 0,
30153015 .lazy = .{ .byte_abs = byte_abs },
30163016 }, err_msg, "invalid byte: '{'}'", .{std.zig.fmtEscapes(source[byte_abs..][0..1])});
3017 } else if (parse_err.tag == .decl_between_fields) {
3018 try mod.errNoteNonLazy(.{
3019 .file_scope = file,
3020 .parent_decl_node = 0,
3021 .lazy = .{ .byte_abs = token_starts[file.tree.errors[1].token] },
3022 }, err_msg, "field before declarations here", .{});
3023 try mod.errNoteNonLazy(.{
3024 .file_scope = file,
3025 .parent_decl_node = 0,
3026 .lazy = .{ .byte_abs = token_starts[file.tree.errors[2].token] },
3027 }, err_msg, "field after declarations here", .{});
30173028 }
30183029
30193030 {
src/main.zig+80-61
......@@ -3799,9 +3799,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
37993799 };
38003800 defer tree.deinit(gpa);
38013801
3802 for (tree.errors) |parse_error| {
3803 try printErrMsgToStdErr(gpa, arena, parse_error, tree, "<stdin>", color);
3804 }
3802 try printErrsMsgToStdErr(gpa, arena, tree.errors, tree, "<stdin>", color);
38053803 var has_ast_error = false;
38063804 if (check_ast_flag) {
38073805 const Module = @import("Module.zig");
......@@ -3989,9 +3987,7 @@ fn fmtPathFile(
39893987 var tree = try std.zig.parse(fmt.gpa, source_code);
39903988 defer tree.deinit(fmt.gpa);
39913989
3992 for (tree.errors) |parse_error| {
3993 try printErrMsgToStdErr(fmt.gpa, fmt.arena, parse_error, tree, file_path, fmt.color);
3994 }
3990 try printErrsMsgToStdErr(fmt.gpa, fmt.arena, tree.errors, tree, file_path, fmt.color);
39953991 if (tree.errors.len != 0) {
39963992 fmt.any_error = true;
39973993 return;
......@@ -4071,66 +4067,95 @@ fn fmtPathFile(
40714067 }
40724068}
40734069
4074fn printErrMsgToStdErr(
4070fn printErrsMsgToStdErr(
40754071 gpa: mem.Allocator,
40764072 arena: mem.Allocator,
4077 parse_error: Ast.Error,
4073 parse_errors: []const Ast.Error,
40784074 tree: Ast,
40794075 path: []const u8,
40804076 color: Color,
40814077) !void {
4082 const lok_token = parse_error.token;
4083 const token_tags = tree.tokens.items(.tag);
4084 const start_loc = tree.tokenLocation(0, lok_token);
4085 const source_line = tree.source[start_loc.line_start..start_loc.line_end];
4086
4087 var text_buf = std.ArrayList(u8).init(gpa);
4088 defer text_buf.deinit();
4089 const writer = text_buf.writer();
4090 try tree.renderError(parse_error, writer);
4091 const text = text_buf.items;
4092
4093 var notes_buffer: [1]Compilation.AllErrors.Message = undefined;
4094 var notes_len: usize = 0;
4095
4096 if (token_tags[parse_error.token] == .invalid) {
4097 const bad_off = @intCast(u32, tree.tokenSlice(parse_error.token).len);
4098 const byte_offset = @intCast(u32, start_loc.line_start) + bad_off;
4099 notes_buffer[notes_len] = .{
4078 var i: usize = 0;
4079 while (i < parse_errors.len) : (i += 1) {
4080 const parse_error = parse_errors[i];
4081 const lok_token = parse_error.token;
4082 const token_tags = tree.tokens.items(.tag);
4083 const start_loc = tree.tokenLocation(0, lok_token);
4084 const source_line = tree.source[start_loc.line_start..start_loc.line_end];
4085
4086 var text_buf = std.ArrayList(u8).init(gpa);
4087 defer text_buf.deinit();
4088 const writer = text_buf.writer();
4089 try tree.renderError(parse_error, writer);
4090 const text = text_buf.items;
4091
4092 var notes_buffer: [2]Compilation.AllErrors.Message = undefined;
4093 var notes_len: usize = 0;
4094
4095 if (token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)] == .invalid) {
4096 const bad_off = @intCast(u32, tree.tokenSlice(parse_error.token + @boolToInt(parse_error.token_is_prev)).len);
4097 const byte_offset = @intCast(u32, start_loc.line_start) + @intCast(u32, start_loc.column) + bad_off;
4098 notes_buffer[notes_len] = .{
4099 .src = .{
4100 .src_path = path,
4101 .msg = try std.fmt.allocPrint(arena, "invalid byte: '{'}'", .{
4102 std.zig.fmtEscapes(tree.source[byte_offset..][0..1]),
4103 }),
4104 .byte_offset = byte_offset,
4105 .line = @intCast(u32, start_loc.line),
4106 .column = @intCast(u32, start_loc.column) + bad_off,
4107 .source_line = source_line,
4108 },
4109 };
4110 notes_len += 1;
4111 } else if (parse_error.tag == .decl_between_fields) {
4112 const prev_loc = tree.tokenLocation(0, parse_errors[i + 1].token);
4113 notes_buffer[0] = .{
4114 .src = .{
4115 .src_path = path,
4116 .msg = "field before declarations here",
4117 .byte_offset = @intCast(u32, prev_loc.line_start),
4118 .line = @intCast(u32, prev_loc.line),
4119 .column = @intCast(u32, prev_loc.column),
4120 .source_line = tree.source[prev_loc.line_start..prev_loc.line_end],
4121 },
4122 };
4123 const next_loc = tree.tokenLocation(0, parse_errors[i + 2].token);
4124 notes_buffer[1] = .{
4125 .src = .{
4126 .src_path = path,
4127 .msg = "field after declarations here",
4128 .byte_offset = @intCast(u32, next_loc.line_start),
4129 .line = @intCast(u32, next_loc.line),
4130 .column = @intCast(u32, next_loc.column),
4131 .source_line = tree.source[next_loc.line_start..next_loc.line_end],
4132 },
4133 };
4134 notes_len = 2;
4135 i += 2;
4136 }
4137
4138 const extra_offset = tree.errorOffset(parse_error);
4139 const message: Compilation.AllErrors.Message = .{
41004140 .src = .{
41014141 .src_path = path,
4102 .msg = try std.fmt.allocPrint(arena, "invalid byte: '{'}'", .{
4103 std.zig.fmtEscapes(tree.source[byte_offset..][0..1]),
4104 }),
4105 .byte_offset = byte_offset,
4142 .msg = text,
4143 .byte_offset = @intCast(u32, start_loc.line_start) + extra_offset,
41064144 .line = @intCast(u32, start_loc.line),
4107 .column = @intCast(u32, start_loc.column) + bad_off,
4145 .column = @intCast(u32, start_loc.column) + extra_offset,
41084146 .source_line = source_line,
4147 .notes = notes_buffer[0..notes_len],
41094148 },
41104149 };
4111 notes_len += 1;
4112 }
41134150
4114 const extra_offset = tree.errorOffset(parse_error.tag, parse_error.token);
4115 const message: Compilation.AllErrors.Message = .{
4116 .src = .{
4117 .src_path = path,
4118 .msg = text,
4119 .byte_offset = @intCast(u32, start_loc.line_start) + extra_offset,
4120 .line = @intCast(u32, start_loc.line),
4121 .column = @intCast(u32, start_loc.column) + extra_offset,
4122 .source_line = source_line,
4123 .notes = notes_buffer[0..notes_len],
4124 },
4125 };
4126
4127 const ttyconf: std.debug.TTY.Config = switch (color) {
4128 .auto => std.debug.detectTTYConfig(),
4129 .on => .escape_codes,
4130 .off => .no_color,
4131 };
4151 const ttyconf: std.debug.TTY.Config = switch (color) {
4152 .auto => std.debug.detectTTYConfig(),
4153 .on => .escape_codes,
4154 .off => .no_color,
4155 };
41324156
4133 message.renderToStdErr(ttyconf);
4157 message.renderToStdErr(ttyconf);
4158 }
41344159}
41354160
41364161pub const info_zen =
......@@ -4688,9 +4713,7 @@ pub fn cmdAstCheck(
46884713 file.tree_loaded = true;
46894714 defer file.tree.deinit(gpa);
46904715
4691 for (file.tree.errors) |parse_error| {
4692 try printErrMsgToStdErr(gpa, arena, parse_error, file.tree, file.sub_file_path, color);
4693 }
4716 try printErrsMsgToStdErr(gpa, arena, file.tree.errors, file.tree, file.sub_file_path, color);
46944717 if (file.tree.errors.len != 0) {
46954718 process.exit(1);
46964719 }
......@@ -4816,9 +4839,7 @@ pub fn cmdChangelist(
48164839 file.tree_loaded = true;
48174840 defer file.tree.deinit(gpa);
48184841
4819 for (file.tree.errors) |parse_error| {
4820 try printErrMsgToStdErr(gpa, arena, parse_error, file.tree, old_source_file, .auto);
4821 }
4842 try printErrsMsgToStdErr(gpa, arena, file.tree.errors, file.tree, old_source_file, .auto);
48224843 if (file.tree.errors.len != 0) {
48234844 process.exit(1);
48244845 }
......@@ -4855,9 +4876,7 @@ pub fn cmdChangelist(
48554876 var new_tree = try std.zig.parse(gpa, new_source);
48564877 defer new_tree.deinit(gpa);
48574878
4858 for (new_tree.errors) |parse_error| {
4859 try printErrMsgToStdErr(gpa, arena, parse_error, new_tree, new_source_file, .auto);
4860 }
4879 try printErrsMsgToStdErr(gpa, arena, new_tree.errors, new_tree, new_source_file, .auto);
48614880 if (new_tree.errors.len != 0) {
48624881 process.exit(1);
48634882 }
src/stage1/ir.cpp+27-4
......@@ -7843,7 +7843,7 @@ static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *sou
78437843 bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
78447844 || !actual_type->data.pointer.is_const);
78457845
7846 if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
7846 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
78477847 array_type->data.array.child_type, source_node,
78487848 !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk &&
78497849 (slice_ptr_type->data.pointer.sentinel == nullptr ||
......@@ -7851,6 +7851,14 @@ static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *sou
78517851 const_values_equal(ira->codegen, array_type->data.array.sentinel,
78527852 slice_ptr_type->data.pointer.sentinel))))
78537853 {
7854 if (!const_ok) {
7855 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7856 buf_sprintf("cannot cast pointer to array literal to slice type '%s'",
7857 buf_ptr(&wanted_type->name)));
7858 add_error_note(ira->codegen, msg, source_node,
7859 buf_sprintf("cast discards const qualifier"));
7860 return ira->codegen->invalid_inst_gen;
7861 }
78547862 // If the pointers both have ABI align, it works.
78557863 // Or if the array length is 0, alignment doesn't matter.
78567864 bool ok_align = array_type->data.array.len == 0 ||
......@@ -8208,8 +8216,16 @@ static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *sou
82088216 ZigType *wanted_child = wanted_type->data.pointer.child_type;
82098217 bool const_ok = (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const);
82108218 if (wanted_child->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
8211 wanted_child->data.array.len == field_count && (const_ok || field_count == 0))
8219 wanted_child->data.array.len == field_count)
82128220 {
8221 if (!const_ok && field_count != 0) {
8222 ErrorMsg *msg = ir_add_error_node(ira, source_node,
8223 buf_sprintf("cannot cast pointer to array literal to '%s'",
8224 buf_ptr(&wanted_type->name)));
8225 add_error_note(ira->codegen, msg, source_node,
8226 buf_sprintf("cast discards const qualifier"));
8227 return ira->codegen->invalid_inst_gen;
8228 }
82138229 Stage1AirInst *res = ir_analyze_struct_literal_to_array(ira, scope, source_node, value, anon_type, wanted_child);
82148230 if (res->value->type->id == ZigTypeIdPointer)
82158231 return res;
......@@ -8241,6 +8257,13 @@ static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *sou
82418257 res = ir_get_ref(ira, scope, source_node, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
82428258
82438259 return ir_resolve_ptr_of_array_to_slice(ira, scope, source_node, res, wanted_type, nullptr);
8260 } else if (!slice_type->data.pointer.is_const && actual_type->data.pointer.is_const && field_count != 0) {
8261 ErrorMsg *msg = ir_add_error_node(ira, source_node,
8262 buf_sprintf("cannot cast pointer to array literal to slice type '%s'",
8263 buf_ptr(&wanted_type->name)));
8264 add_error_note(ira->codegen, msg, source_node,
8265 buf_sprintf("cast discards const qualifier"));
8266 return ira->codegen->invalid_inst_gen;
82448267 }
82458268 }
82468269 }
......@@ -15068,7 +15091,7 @@ static Stage1AirInst *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, Stage1ZirI
1506815091 return ira->codegen->invalid_inst_gen;
1506915092 if (actual_array_type->id != ZigTypeIdArray) {
1507015093 ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
15071 buf_sprintf("array literal requires address-of operator to coerce to slice type '%s'",
15094 buf_sprintf("array literal requires address-of operator (&) to coerce to slice type '%s'",
1507215095 buf_ptr(&actual_array_type->name)));
1507315096 return ira->codegen->invalid_inst_gen;
1507415097 }
......@@ -17473,7 +17496,7 @@ static Stage1AirInst *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1747317496
1747417497 if (is_slice(container_type)) {
1747517498 ir_add_error_node(ira, instruction->init_array_type_source_node,
17476 buf_sprintf("array literal requires address-of operator to coerce to slice type '%s'",
17499 buf_sprintf("array literal requires address-of operator (&) to coerce to slice type '%s'",
1747717500 buf_ptr(&container_type->name)));
1747817501 return ira->codegen->invalid_inst_gen;
1747917502 }
test/compile_errors.zig+40-33
......@@ -86,9 +86,12 @@ pub fn addCases(ctx: *TestContext) !void {
8686 \\ _ = c;
8787 \\}
8888 , &[_][]const u8{
89 "tmp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'",
90 "tmp.zig:6:33: error: expected type '*[2][]const u8', found '*const struct:6:33'",
89 "tmp.zig:2:31: error: cannot cast pointer to array literal to slice type '[][]const u8'",
90 "tmp.zig:2:31: note: cast discards const qualifier",
91 "tmp.zig:6:33: error: cannot cast pointer to array literal to '*[2][]const u8'",
92 "tmp.zig:6:33: note: cast discards const qualifier",
9193 "tmp.zig:11:21: error: expected type '*S', found '*const struct:11:21'",
94 "tmp.zig:11:21: note: cast discards const qualifier",
9295 });
9396
9497 ctx.objErrStage1("@Type() union payload is undefined",
......@@ -874,6 +877,8 @@ pub fn addCases(ctx: *TestContext) !void {
874877 \\}
875878 , &[_][]const u8{
876879 "tmp.zig:6:5: error: declarations are not allowed between container fields",
880 "tmp.zig:5:5: note: field before declarations here",
881 "tmp.zig:9:5: note: field after declarations here",
877882 });
878883
879884 ctx.objErrStage1("non-extern function with var args",
......@@ -1540,7 +1545,7 @@ pub fn addCases(ctx: *TestContext) !void {
15401545 \\ std.debug.assert(bad_float < 1.0);
15411546 \\}
15421547 , &[_][]const u8{
1543 "tmp.zig:5:29: error: invalid token: '.'",
1548 "tmp.zig:5:29: error: expected expression, found '.'",
15441549 });
15451550
15461551 ctx.objErrStage1("invalid exponent in float literal - 1",
......@@ -1549,7 +1554,7 @@ pub fn addCases(ctx: *TestContext) !void {
15491554 \\ _ = bad;
15501555 \\}
15511556 , &[_][]const u8{
1552 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1557 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
15531558 "tmp.zig:2:28: note: invalid byte: 'a'",
15541559 });
15551560
......@@ -1559,7 +1564,7 @@ pub fn addCases(ctx: *TestContext) !void {
15591564 \\ _ = bad;
15601565 \\}
15611566 , &[_][]const u8{
1562 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1567 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
15631568 "tmp.zig:2:29: note: invalid byte: 'F'",
15641569 });
15651570
......@@ -1569,7 +1574,7 @@ pub fn addCases(ctx: *TestContext) !void {
15691574 \\ _ = bad;
15701575 \\}
15711576 , &[_][]const u8{
1572 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1577 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
15731578 "tmp.zig:2:23: note: invalid byte: '_'",
15741579 });
15751580
......@@ -1579,7 +1584,7 @@ pub fn addCases(ctx: *TestContext) !void {
15791584 \\ _ = bad;
15801585 \\}
15811586 , &[_][]const u8{
1582 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1587 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
15831588 "tmp.zig:2:23: note: invalid byte: '.'",
15841589 });
15851590
......@@ -1589,7 +1594,7 @@ pub fn addCases(ctx: *TestContext) !void {
15891594 \\ _ = bad;
15901595 \\}
15911596 , &[_][]const u8{
1592 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1597 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
15931598 "tmp.zig:2:25: note: invalid byte: ';'",
15941599 });
15951600
......@@ -1599,7 +1604,7 @@ pub fn addCases(ctx: *TestContext) !void {
15991604 \\ _ = bad;
16001605 \\}
16011606 , &[_][]const u8{
1602 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1607 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16031608 "tmp.zig:2:25: note: invalid byte: '_'",
16041609 });
16051610
......@@ -1609,7 +1614,7 @@ pub fn addCases(ctx: *TestContext) !void {
16091614 \\ _ = bad;
16101615 \\}
16111616 , &[_][]const u8{
1612 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1617 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16131618 "tmp.zig:2:26: note: invalid byte: '_'",
16141619 });
16151620
......@@ -1619,7 +1624,7 @@ pub fn addCases(ctx: *TestContext) !void {
16191624 \\ _ = bad;
16201625 \\}
16211626 , &[_][]const u8{
1622 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1627 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16231628 "tmp.zig:2:26: note: invalid byte: '_'",
16241629 });
16251630
......@@ -1629,7 +1634,7 @@ pub fn addCases(ctx: *TestContext) !void {
16291634 \\ _ = bad;
16301635 \\}
16311636 , &[_][]const u8{
1632 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1637 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16331638 "tmp.zig:2:28: note: invalid byte: ';'",
16341639 });
16351640
......@@ -1639,7 +1644,7 @@ pub fn addCases(ctx: *TestContext) !void {
16391644 \\ _ = bad;
16401645 \\}
16411646 , &[_][]const u8{
1642 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1647 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16431648 "tmp.zig:2:23: note: invalid byte: '_'",
16441649 });
16451650
......@@ -1649,7 +1654,7 @@ pub fn addCases(ctx: *TestContext) !void {
16491654 \\ _ = bad;
16501655 \\}
16511656 , &[_][]const u8{
1652 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1657 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16531658 "tmp.zig:2:25: note: invalid byte: '_'",
16541659 });
16551660
......@@ -1659,7 +1664,7 @@ pub fn addCases(ctx: *TestContext) !void {
16591664 \\ _ = bad;
16601665 \\}
16611666 , &[_][]const u8{
1662 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1667 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16631668 "tmp.zig:2:28: note: invalid byte: '_'",
16641669 });
16651670
......@@ -1669,7 +1674,7 @@ pub fn addCases(ctx: *TestContext) !void {
16691674 \\ _ = bad;
16701675 \\}
16711676 , &[_][]const u8{
1672 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1677 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16731678 "tmp.zig:2:23: note: invalid byte: 'x'",
16741679 });
16751680
......@@ -1679,7 +1684,7 @@ pub fn addCases(ctx: *TestContext) !void {
16791684 \\ _ = bad;
16801685 \\}
16811686 , &[_][]const u8{
1682 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1687 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16831688 "tmp.zig:2:23: note: invalid byte: '_'",
16841689 });
16851690
......@@ -1689,7 +1694,7 @@ pub fn addCases(ctx: *TestContext) !void {
16891694 \\ _ = bad;
16901695 \\}
16911696 , &[_][]const u8{
1692 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1697 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
16931698 "tmp.zig:2:27: note: invalid byte: 'p'",
16941699 });
16951700
......@@ -1699,7 +1704,7 @@ pub fn addCases(ctx: *TestContext) !void {
16991704 \\ _ = bad;
17001705 \\}
17011706 , &[_][]const u8{
1702 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1707 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
17031708 "tmp.zig:2:26: note: invalid byte: ';'",
17041709 });
17051710
......@@ -1709,7 +1714,7 @@ pub fn addCases(ctx: *TestContext) !void {
17091714 \\ _ = bad;
17101715 \\}
17111716 , &[_][]const u8{
1712 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1717 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
17131718 "tmp.zig:2:28: note: invalid byte: ';'",
17141719 });
17151720
......@@ -1719,7 +1724,7 @@ pub fn addCases(ctx: *TestContext) !void {
17191724 \\ _ = bad;
17201725 \\}
17211726 , &[_][]const u8{
1722 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1727 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
17231728 "tmp.zig:2:28: note: invalid byte: ';'",
17241729 });
17251730
......@@ -1729,7 +1734,7 @@ pub fn addCases(ctx: *TestContext) !void {
17291734 \\ _ = bad;
17301735 \\}
17311736 , &[_][]const u8{
1732 "tmp.zig:2:21: error: expected expression, found 'invalid'",
1737 "tmp.zig:2:21: error: expected expression, found 'invalid bytes'",
17331738 "tmp.zig:2:28: note: invalid byte: ';'",
17341739 });
17351740
......@@ -1962,7 +1967,7 @@ pub fn addCases(ctx: *TestContext) !void {
19621967 \\ _ = geo_data;
19631968 \\}
19641969 , &[_][]const u8{
1965 "tmp.zig:4:30: error: array literal requires address-of operator to coerce to slice type '[][2]f32'",
1970 "tmp.zig:4:30: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32'",
19661971 });
19671972
19681973 ctx.objErrStage1("slicing of global undefined pointer",
......@@ -2171,7 +2176,7 @@ pub fn addCases(ctx: *TestContext) !void {
21712176 \\ _ = x;
21722177 \\}
21732178 , &[_][]const u8{
2174 "tmp.zig:3:6: error: expected ',' after field",
2179 "tmp.zig:3:7: error: expected ',' after field",
21752180 });
21762181
21772182 ctx.objErrStage1("bad alignment type",
......@@ -2537,7 +2542,7 @@ pub fn addCases(ctx: *TestContext) !void {
25372542 \\ _ = x;
25382543 \\}
25392544 , &[_][]const u8{
2540 "tmp.zig:2:15: error: array literal requires address-of operator to coerce to slice type '[]u8'",
2545 "tmp.zig:2:15: error: array literal requires address-of operator (&) to coerce to slice type '[]u8'",
25412546 });
25422547
25432548 ctx.objErrStage1("slice passed as array init type",
......@@ -2546,7 +2551,7 @@ pub fn addCases(ctx: *TestContext) !void {
25462551 \\ _ = x;
25472552 \\}
25482553 , &[_][]const u8{
2549 "tmp.zig:2:15: error: array literal requires address-of operator to coerce to slice type '[]u8'",
2554 "tmp.zig:2:15: error: array literal requires address-of operator (&) to coerce to slice type '[]u8'",
25502555 });
25512556
25522557 ctx.objErrStage1("inferred array size invalid here",
......@@ -3493,7 +3498,8 @@ pub fn addCases(ctx: *TestContext) !void {
34933498 \\ _ = sliceA;
34943499 \\}
34953500 , &[_][]const u8{
3496 "tmp.zig:3:27: error: expected type '[]u8', found '*const [1]u8'",
3501 "tmp.zig:3:27: error: cannot cast pointer to array literal to slice type '[]u8'",
3502 "tmp.zig:3:27: note: cast discards const qualifier",
34973503 });
34983504
34993505 ctx.objErrStage1("deref slice and get len field",
......@@ -4865,11 +4871,11 @@ pub fn addCases(ctx: *TestContext) !void {
48654871 \\export fn entry() void {
48664872 \\ while(true) {}
48674873 \\ var good = {};
4868 \\ while(true) ({})
4874 \\ while(true) 1
48694875 \\ var bad = {};
48704876 \\}
48714877 , &[_][]const u8{
4872 "tmp.zig:4:21: error: expected ';' or 'else' after statement",
4878 "tmp.zig:4:18: error: expected ';' or 'else' after statement",
48734879 });
48744880
48754881 ctx.objErrStage1("implicit semicolon - while expression",
......@@ -5733,7 +5739,7 @@ pub fn addCases(ctx: *TestContext) !void {
57335739 \\const foo = "a
57345740 \\b";
57355741 , &[_][]const u8{
5736 "tmp.zig:1:13: error: expected expression, found 'invalid'",
5742 "tmp.zig:1:13: error: expected expression, found 'invalid bytes'",
57375743 "tmp.zig:1:15: note: invalid byte: '\\n'",
57385744 });
57395745
......@@ -7638,7 +7644,7 @@ pub fn addCases(ctx: *TestContext) !void {
76387644 \\ const a = '\U1234';
76397645 \\}
76407646 , &[_][]const u8{
7641 "tmp.zig:2:15: error: expected expression, found 'invalid'",
7647 "tmp.zig:2:15: error: expected expression, found 'invalid bytes'",
76427648 "tmp.zig:2:18: note: invalid byte: '1'",
76437649 });
76447650
......@@ -7654,7 +7660,7 @@ pub fn addCases(ctx: *TestContext) !void {
76547660 "fn foo() bool {\r\n" ++
76557661 " return true;\r\n" ++
76567662 "}\r\n", &[_][]const u8{
7657 "tmp.zig:1:1: error: expected test, comptime, var decl, or container field, found 'invalid'",
7663 "tmp.zig:1:1: error: expected test, comptime, var decl, or container field, found 'invalid bytes'",
76587664 "tmp.zig:1:1: note: invalid byte: '\\xff'",
76597665 });
76607666
......@@ -8717,7 +8723,8 @@ pub fn addCases(ctx: *TestContext) !void {
87178723 \\ comptime ignore(@typeInfo(MyStruct).Struct.fields[0]);
87188724 \\}
87198725 , &[_][]const u8{
8720 ":5:28: error: expected type '[]u8', found '*const [3:0]u8'",
8726 ":5:28: error: cannot cast pointer to array literal to slice type '[]u8'",
8727 ":5:28: note: cast discards const qualifier",
87218728 });
87228729
87238730 ctx.objErrStage1("integer underflow error",
test/stage2/cbe.zig+1-1
......@@ -693,7 +693,7 @@ pub fn addCases(ctx: *TestContext) !void {
693693 \\ _ = E1.a;
694694 \\}
695695 , &.{
696 ":3:6: error: expected ',' after field",
696 ":3:7: error: expected ',' after field",
697697 });
698698
699699 // Redundant non-exhaustive enum mark.