| author | |
| committer | |
| log | abfee127353cbdadab4282b61056222cdfbec2d4 |
| tree | abcb5e07640b1cf3b426dbbfc7b115bf536ea20e |
| parent | 24c432608f6b07020fa0b18fc9c868ad6abd9b15 |
* Implement "initializing array with struct syntax"
* Implement "'_' used as an identifier without @\"_\" syntax"
* Fix source location of "missing parameter name"
* Update test cases where appropriate2 files changed, 50 insertions(+), 26 deletions(-)
src/AstGen.zig+36-19| ... | ... | @@ -1313,22 +1313,23 @@ fn structInitExpr( |
| 1313 | 1313 | const astgen = gz.astgen; |
| 1314 | 1314 | const tree = astgen.tree; |
| 1315 | 1315 | |
| 1316 | if (struct_init.ast.fields.len == 0) { | |
| 1317 | if (struct_init.ast.type_expr == 0) { | |
| 1316 | if (struct_init.ast.type_expr == 0) { | |
| 1317 | if (struct_init.ast.fields.len == 0) { | |
| 1318 | 1318 | return rvalue(gz, rl, .empty_struct, node); |
| 1319 | 1319 | } |
| 1320 | array: { | |
| 1321 | const node_tags = tree.nodes.items(.tag); | |
| 1322 | const main_tokens = tree.nodes.items(.main_token); | |
| 1323 | const array_type: ast.full.ArrayType = switch (node_tags[struct_init.ast.type_expr]) { | |
| 1324 | .array_type => tree.arrayType(struct_init.ast.type_expr), | |
| 1325 | .array_type_sentinel => tree.arrayTypeSentinel(struct_init.ast.type_expr), | |
| 1326 | else => break :array, | |
| 1327 | }; | |
| 1320 | } else array: { | |
| 1321 | const node_tags = tree.nodes.items(.tag); | |
| 1322 | const main_tokens = tree.nodes.items(.main_token); | |
| 1323 | const array_type: ast.full.ArrayType = switch (node_tags[struct_init.ast.type_expr]) { | |
| 1324 | .array_type => tree.arrayType(struct_init.ast.type_expr), | |
| 1325 | .array_type_sentinel => tree.arrayTypeSentinel(struct_init.ast.type_expr), | |
| 1326 | else => break :array, | |
| 1327 | }; | |
| 1328 | const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and | |
| 1328 | 1329 | // This intentionally does not support `@"_"` syntax. |
| 1329 | if (node_tags[array_type.ast.elem_count] == .identifier and | |
| 1330 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_")) | |
| 1331 | { | |
| 1330 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"); | |
| 1331 | if (struct_init.ast.fields.len == 0) { | |
| 1332 | if (is_inferred_array_len) { | |
| 1332 | 1333 | const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type); |
| 1333 | 1334 | const array_type_inst = if (array_type.ast.sentinel == 0) blk: { |
| 1334 | 1335 | break :blk try gz.addBin(.array_type, .zero_usize, elem_type); |
| ... | ... | @@ -1339,11 +1340,18 @@ fn structInitExpr( |
| 1339 | 1340 | const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node); |
| 1340 | 1341 | return rvalue(gz, rl, result, node); |
| 1341 | 1342 | } |
| 1343 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1344 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); | |
| 1345 | return rvalue(gz, rl, result, node); | |
| 1346 | } else { | |
| 1347 | return astgen.failNode( | |
| 1348 | struct_init.ast.type_expr, | |
| 1349 | "initializing array with struct syntax", | |
| 1350 | .{}, | |
| 1351 | ); | |
| 1342 | 1352 | } |
| 1343 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1344 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); | |
| 1345 | return rvalue(gz, rl, result, node); | |
| 1346 | 1353 | } |
| 1354 | ||
| 1347 | 1355 | switch (rl) { |
| 1348 | 1356 | .discard => { |
| 1349 | 1357 | if (struct_init.ast.type_expr != 0) |
| ... | ... | @@ -2266,6 +2274,10 @@ fn varDecl( |
| 2266 | 2274 | const token_tags = tree.tokens.items(.tag); |
| 2267 | 2275 | |
| 2268 | 2276 | const name_token = var_decl.ast.mut_token + 1; |
| 2277 | const ident_name_raw = tree.tokenSlice(name_token); | |
| 2278 | if (mem.eql(u8, ident_name_raw, "_")) { | |
| 2279 | return astgen.failTok(name_token, "'_' used as an identifier without @\"_\" syntax", .{}); | |
| 2280 | } | |
| 2269 | 2281 | const ident_name = try astgen.identAsString(name_token); |
| 2270 | 2282 | |
| 2271 | 2283 | // Local variables shadowing detection, including function parameters. |
| ... | ... | @@ -3003,7 +3015,11 @@ fn fnDecl( |
| 3003 | 3015 | var it = fn_proto.iterate(tree.*); |
| 3004 | 3016 | while (it.next()) |param| : (i += 1) { |
| 3005 | 3017 | const name_token = param.name_token orelse { |
| 3006 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); | |
| 3018 | if (param.anytype_ellipsis3) |tok| { | |
| 3019 | return astgen.failTok(tok, "missing parameter name", .{}); | |
| 3020 | } else { | |
| 3021 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); | |
| 3022 | } | |
| 3007 | 3023 | }; |
| 3008 | 3024 | if (param.type_expr != 0) |
| 3009 | 3025 | _ = try typeExpr(&fn_gz, params_scope, param.type_expr); |
| ... | ... | @@ -6197,10 +6213,11 @@ fn identifier( |
| 6197 | 6213 | const main_tokens = tree.nodes.items(.main_token); |
| 6198 | 6214 | |
| 6199 | 6215 | const ident_token = main_tokens[ident]; |
| 6200 | const ident_name = try astgen.identifierTokenString(ident_token); | |
| 6201 | if (mem.eql(u8, ident_name, "_")) { | |
| 6216 | const ident_name_raw = tree.tokenSlice(ident_token); | |
| 6217 | if (mem.eql(u8, ident_name_raw, "_")) { | |
| 6202 | 6218 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); |
| 6203 | 6219 | } |
| 6220 | const ident_name = try astgen.identifierTokenString(ident_token); | |
| 6204 | 6221 | |
| 6205 | 6222 | if (simple_types.get(ident_name)) |zir_const_ref| { |
| 6206 | 6223 | return rvalue(gz, rl, zir_const_ref, ident); |
test/compile_errors.zig+14-7| ... | ... | @@ -2130,8 +2130,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 2130 | 2130 | \\ _ = x; |
| 2131 | 2131 | \\} |
| 2132 | 2132 | , &[_][]const u8{ |
| 2133 | "tmp.zig:3:13: error: structs and unions, not enums, support field alignment", | |
| 2134 | "tmp.zig:1:16: note: consider 'union(enum)' here", | |
| 2133 | "tmp.zig:3:7: error: expected ',', found 'align'", | |
| 2135 | 2134 | }); |
| 2136 | 2135 | |
| 2137 | 2136 | ctx.objErrStage1("bad alignment type", |
| ... | ... | @@ -3765,8 +3764,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 3765 | 3764 | \\ return _; |
| 3766 | 3765 | \\} |
| 3767 | 3766 | , &[_][]const u8{ |
| 3768 | "tmp.zig:2:5: error: '_' used as an identifier without @\"_\" syntax", | |
| 3769 | "tmp.zig:3:12: error: '_' used as an identifier without @\"_\" syntax", | |
| 3767 | "tmp.zig:2:9: error: '_' used as an identifier without @\"_\" syntax", | |
| 3770 | 3768 | }); |
| 3771 | 3769 | |
| 3772 | 3770 | ctx.objErrStage1("`_` should not be usable inside for", |
| ... | ... | @@ -4908,7 +4906,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 4908 | 4906 | \\export fn entry() void { a(); } |
| 4909 | 4907 | , &[_][]const u8{ |
| 4910 | 4908 | "tmp.zig:2:1: error: redeclaration of 'a'", |
| 4911 | "tmp.zig:1:1: error: other declaration here", | |
| 4909 | "tmp.zig:1:1: note: other declaration here", | |
| 4912 | 4910 | }); |
| 4913 | 4911 | |
| 4914 | 4912 | ctx.objErrStage1("unreachable with return", |
| ... | ... | @@ -5218,6 +5216,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 5218 | 5216 | \\ .z = 4, |
| 5219 | 5217 | \\ .y = 2, |
| 5220 | 5218 | \\ }; |
| 5219 | \\ _ = a; | |
| 5221 | 5220 | \\} |
| 5222 | 5221 | , &[_][]const u8{ |
| 5223 | 5222 | "tmp.zig:9:17: error: missing field: 'x'", |
| ... | ... | @@ -7549,13 +7548,15 @@ pub fn addCases(ctx: *TestContext) !void { |
| 7549 | 7548 | \\ }; |
| 7550 | 7549 | \\ |
| 7551 | 7550 | \\ for ([_]Mode { Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast }) |mode| { |
| 7551 | \\ _ = mode; | |
| 7552 | 7552 | \\ inline for (tests) |test_case| { |
| 7553 | 7553 | \\ const foo = test_case.filename ++ ".zig"; |
| 7554 | \\ _ = foo; | |
| 7554 | 7555 | \\ } |
| 7555 | 7556 | \\ } |
| 7556 | 7557 | \\} |
| 7557 | 7558 | , &[_][]const u8{ |
| 7558 | "tmp.zig:37:29: error: cannot store runtime value in compile time variable", | |
| 7559 | "tmp.zig:38:29: error: cannot store runtime value in compile time variable", | |
| 7559 | 7560 | }); |
| 7560 | 7561 | |
| 7561 | 7562 | ctx.objErrStage1("invalid legacy unicode escape", |
| ... | ... | @@ -7980,6 +7981,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 7980 | 7981 | \\}; |
| 7981 | 7982 | \\export fn foo() void { |
| 7982 | 7983 | \\ const fieldOffset = @offsetOf(Empty, "val",); |
| 7984 | \\ _ = fieldOffset; | |
| 7983 | 7985 | \\} |
| 7984 | 7986 | , &[_][]const u8{ |
| 7985 | 7987 | "tmp.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset", |
| ... | ... | @@ -7991,6 +7993,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 7991 | 7993 | \\}; |
| 7992 | 7994 | \\export fn foo() void { |
| 7993 | 7995 | \\ const fieldOffset = @bitOffsetOf(Empty, "val",); |
| 7996 | \\ _ = fieldOffset; | |
| 7994 | 7997 | \\} |
| 7995 | 7998 | , &[_][]const u8{ |
| 7996 | 7999 | "tmp.zig:5:45: error: zero-bit field 'val' in struct 'Empty' has no offset", |
| ... | ... | @@ -8004,6 +8007,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8004 | 8007 | \\comptime { |
| 8005 | 8008 | \\ var foo = Foo {.Baz = {}}; |
| 8006 | 8009 | \\ const bar_val = foo.Bar; |
| 8010 | \\ _ = bar_val; | |
| 8007 | 8011 | \\} |
| 8008 | 8012 | , &[_][]const u8{ |
| 8009 | 8013 | "tmp.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set", |
| ... | ... | @@ -8119,6 +8123,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8119 | 8123 | \\ var x: *const i32 = &w; |
| 8120 | 8124 | \\ var y: *[1]i32 = x; |
| 8121 | 8125 | \\ y[0] += 1; |
| 8126 | \\ _ = byte; | |
| 8122 | 8127 | \\} |
| 8123 | 8128 | , &[_][]const u8{ |
| 8124 | 8129 | "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'", |
| ... | ... | @@ -8145,6 +8150,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8145 | 8150 | \\export fn f2() void { |
| 8146 | 8151 | \\ var x: anyerror!i32 = error.Bad; |
| 8147 | 8152 | \\ for ("hello") |_| returns() else unreachable; |
| 8153 | \\ _ = x; | |
| 8148 | 8154 | \\} |
| 8149 | 8155 | , &[_][]const u8{ |
| 8150 | 8156 | "tmp.zig:5:30: error: expression value is ignored", |
| ... | ... | @@ -8154,6 +8160,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8154 | 8160 | ctx.objErrStage1("aligned variable of zero-bit type", |
| 8155 | 8161 | \\export fn f() void { |
| 8156 | 8162 | \\ var s: struct {} align(4) = undefined; |
| 8163 | \\ _ = s; | |
| 8157 | 8164 | \\} |
| 8158 | 8165 | , &[_][]const u8{ |
| 8159 | 8166 | "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned", |
| ... | ... | @@ -8637,7 +8644,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8637 | 8644 | }); |
| 8638 | 8645 | |
| 8639 | 8646 | ctx.objErrStage1("issue #5221: invalid struct init type referenced by @typeInfo and passed into function", |
| 8640 | \\fn ignore(comptime param: anytype) void {} | |
| 8647 | \\fn ignore(comptime param: anytype) void {_ = param;} | |
| 8641 | 8648 | \\ |
| 8642 | 8649 | \\export fn foo() void { |
| 8643 | 8650 | \\ const MyStruct = struct { |