authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-12 03:39:01-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-01-12 03:39:01-05:00
log2a92b04b9dc21356f383b12af9040ca79f268267
tree830ecfe5f91d60ad32754163ef87adbe9c6dfa25
parentc2d37224c843feb84f4522ec35d192968b786e08
parentd8128c272a087bbfc0b33a786c18267f49cd4982
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14257 from Vexu/compile-errors

compile error improvements and bug fixes

13 files changed, 216 insertions(+), 40 deletions(-)

lib/std/zig/Ast.zig+4
......@@ -362,6 +362,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
362362 .wrong_equal_var_decl => {
363363 return stream.writeAll("variable initialized with '==' instead of '='");
364364 },
365 .var_const_decl => {
366 return stream.writeAll("use 'var' or 'const' to declare variable");
367 },
365368
366369 .expected_token => {
367370 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
......@@ -2743,6 +2746,7 @@ pub const Error = struct {
27432746 c_style_container,
27442747 expected_var_const,
27452748 wrong_equal_var_decl,
2749 var_const_decl,
27462750
27472751 zig_style_container,
27482752 previous_field,
lib/std/zig/parse.zig+7
......@@ -471,6 +471,13 @@ const Parser = struct {
471471 // There is not allowed to be a decl after a field with no comma.
472472 // Report error but recover parser.
473473 try p.warn(.expected_comma_after_field);
474 if (p.token_tags[p.tok_i] == .semicolon and p.token_tags[identifier] == .identifier) {
475 try p.warnMsg(.{
476 .tag = .var_const_decl,
477 .is_note = true,
478 .token = identifier,
479 });
480 }
474481 p.findNextContainerMember();
475482 continue;
476483 },
lib/std/zig/parser_test.zig+12
......@@ -5238,6 +5238,18 @@ test "zig fmt: missing const/var before local variable" {
52385238 });
52395239}
52405240
5241test "zig fmt: missing const/var before local variable" {
5242 try testError(
5243 \\std = foo,
5244 \\std = foo;
5245 \\*u32 = foo;
5246 , &.{
5247 .expected_comma_after_field,
5248 .var_const_decl,
5249 .expected_comma_after_field,
5250 });
5251}
5252
52415253test "zig fmt: while continue expr" {
52425254 try testCanonical(
52435255 \\test {
src/AstGen.zig+18-2
......@@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
24632463 .is_non_null_ptr,
24642464 .is_non_err,
24652465 .is_non_err_ptr,
2466 .ret_is_non_err,
24662467 .mod_rem,
24672468 .mul,
24682469 .mulwrap,
......@@ -4486,9 +4487,24 @@ fn structDeclInner(
44864487 .container_field_align,
44874488 .container_field,
44884489 .@"comptime",
4490 .test_decl,
44894491 => continue,
44904492 else => {
4491 return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{});
4493 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {
4494 .container_field_init,
4495 .container_field_align,
4496 .container_field,
4497 => break maybe_tuple,
4498 else => {},
4499 } else unreachable;
4500 return astgen.failNodeNotes(
4501 member_node,
4502 "tuple declarations cannot contain declarations",
4503 .{},
4504 &[_]u32{
4505 try astgen.errNoteNode(tuple_member, "tuple field here", .{}),
4506 },
4507 );
44924508 },
44934509 }
44944510 };
......@@ -7012,7 +7028,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
70127028
70137029 // Emit conditional branch for generating errdefers.
70147030 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
7015 const is_non_err = try gz.addUnNode(.is_non_err, result, node);
7031 const is_non_err = try gz.addUnNode(.ret_is_non_err, result, node);
70167032 const condbr = try gz.addCondBr(.condbr, node);
70177033
70187034 var then_scope = gz.makeSubBlock(scope);
src/Module.zig+22-9
......@@ -528,10 +528,10 @@ pub const Decl = struct {
528528 /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
529529 /// deletes the Decl on the spot.
530530 alive: bool,
531 /// Whether the Decl is a `usingnamespace` declaration.
532 is_usingnamespace: bool,
533531 /// If true `name` is already fully qualified.
534532 name_fully_qualified: bool = false,
533 /// What kind of a declaration is this.
534 kind: Kind,
535535
536536 /// Represents the position of the code in the output file.
537537 /// This is populated regardless of semantic analysis and code generation.
......@@ -551,6 +551,14 @@ pub const Decl = struct {
551551 /// typed_value may need to be regenerated.
552552 dependencies: DepsTable = .{},
553553
554 pub const Kind = enum {
555 @"usingnamespace",
556 @"test",
557 @"comptime",
558 named,
559 anon,
560 };
561
554562 pub const Index = enum(u32) {
555563 _,
556564
......@@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
44384446 // not the struct itself.
44394447 try sema.resolveTypeLayout(decl_tv.ty);
44404448
4441 if (decl.is_usingnamespace) {
4449 if (decl.kind == .@"usingnamespace") {
44424450 if (!decl_tv.ty.eql(Type.type, mod)) {
44434451 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
44444452 decl_tv.ty.fmt(mod),
......@@ -4964,26 +4972,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
49644972
49654973 // Every Decl needs a name.
49664974 var is_named_test = false;
4975 var kind: Decl.Kind = .named;
49674976 const decl_name: [:0]const u8 = switch (decl_name_index) {
49684977 0 => name: {
49694978 if (export_bit) {
49704979 const i = iter.usingnamespace_index;
49714980 iter.usingnamespace_index += 1;
4981 kind = .@"usingnamespace";
49724982 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
49734983 } else {
49744984 const i = iter.comptime_index;
49754985 iter.comptime_index += 1;
4986 kind = .@"comptime";
49764987 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
49774988 }
49784989 },
49794990 1 => name: {
49804991 const i = iter.unnamed_test_index;
49814992 iter.unnamed_test_index += 1;
4993 kind = .@"test";
49824994 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
49834995 },
49844996 2 => name: {
49854997 is_named_test = true;
49864998 const test_name = zir.nullTerminatedString(decl_doccomment_index);
4999 kind = .@"test";
49875000 break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});
49885001 },
49895002 else => name: {
......@@ -4991,6 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
49915004 if (raw_name.len == 0) {
49925005 is_named_test = true;
49935006 const test_name = zir.nullTerminatedString(decl_name_index + 1);
5007 kind = .@"test";
49945008 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
49955009 } else {
49965010 break :name try gpa.dupeZ(u8, raw_name);
......@@ -4998,8 +5012,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
49985012 },
49995013 };
50005014 const is_exported = export_bit and decl_name_index != 0;
5001 const is_usingnamespace = export_bit and decl_name_index == 0;
5002 if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
5015 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
50035016
50045017 // We create a Decl for it regardless of analysis status.
50055018 const gop = try namespace.decls.getOrPutContextAdapted(
......@@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50125025 if (!gop.found_existing) {
50135026 const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);
50145027 const new_decl = mod.declPtr(new_decl_index);
5028 new_decl.kind = kind;
50155029 new_decl.name = decl_name;
5016 if (is_usingnamespace) {
5030 if (kind == .@"usingnamespace") {
50175031 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
50185032 }
50195033 log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
......@@ -5058,7 +5072,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50585072 }
50595073 new_decl.is_pub = is_pub;
50605074 new_decl.is_exported = is_exported;
5061 new_decl.is_usingnamespace = is_usingnamespace;
50625075 new_decl.has_align = has_align;
50635076 new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
50645077 new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
......@@ -5076,7 +5089,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50765089
50775090 decl.is_pub = is_pub;
50785091 decl.is_exported = is_exported;
5079 decl.is_usingnamespace = is_usingnamespace;
5092 decl.kind = kind;
50805093 decl.has_align = has_align;
50815094 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
50825095 decl.zir_decl_index = @intCast(u32, decl_sub_index);
......@@ -5635,7 +5648,7 @@ pub fn allocateNewDecl(
56355648 .has_linksection_or_addrspace = false,
56365649 .has_align = false,
56375650 .alive = false,
5638 .is_usingnamespace = false,
5651 .kind = .anon,
56395652 };
56405653
56415654 return decl_and_index.decl_index;
src/Sema.zig+76-27
......@@ -953,6 +953,7 @@ fn analyzeBodyInner(
953953 .int_type => try sema.zirIntType(block, inst),
954954 .is_non_err => try sema.zirIsNonErr(block, inst),
955955 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
956 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
956957 .is_non_null => try sema.zirIsNonNull(block, inst),
957958 .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),
958959 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),
......@@ -9004,7 +9005,7 @@ fn zirParam(
90049005 else => |e| return e,
90059006 } or comptime_syntax;
90069007 if (sema.inst_map.get(inst)) |arg| {
9007 if (is_comptime) {
9008 if (is_comptime and sema.preallocated_new_func != null) {
90089009 // We have a comptime value for this parameter so it should be elided from the
90099010 // function type of the function instruction in this block.
90109011 const coerced_arg = try sema.coerce(block, param_ty, arg, src);
......@@ -10288,6 +10289,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1028810289 .ret_err_value_code,
1028910290 .restore_err_ret_index,
1029010291 .is_non_err,
10292 .ret_is_non_err,
1029110293 .condbr,
1029210294 => {},
1029310295 else => break,
......@@ -16215,11 +16217,54 @@ fn typeInfoDecls(
1621516217 };
1621616218 try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena));
1621716219
16218 const decls_len = if (opt_namespace) |ns| ns.decls.count() else 0;
16219 const decls_vals = try decls_anon_decl.arena().alloc(Value, decls_len);
16220 for (decls_vals) |*decls_val, i| {
16221 const decl_index = opt_namespace.?.decls.keys()[i];
16220 var decl_vals = std.ArrayList(Value).init(sema.gpa);
16221 defer decl_vals.deinit();
16222
16223 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
16224 defer seen_namespaces.deinit();
16225
16226 if (opt_namespace) |some| {
16227 try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), some, &decl_vals, &seen_namespaces);
16228 }
16229
16230 const new_decl = try decls_anon_decl.finish(
16231 try Type.Tag.array.create(decls_anon_decl.arena(), .{
16232 .len = decl_vals.items.len,
16233 .elem_type = declaration_ty,
16234 }),
16235 try Value.Tag.aggregate.create(
16236 decls_anon_decl.arena(),
16237 try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16238 ),
16239 0, // default alignment
16240 );
16241 return try Value.Tag.slice.create(sema.arena, .{
16242 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16243 .len = try Value.Tag.int_u64.create(sema.arena, decl_vals.items.len),
16244 });
16245}
16246
16247fn typeInfoNamespaceDecls(
16248 sema: *Sema,
16249 block: *Block,
16250 decls_anon_decl: Allocator,
16251 namespace: *Namespace,
16252 decl_vals: *std.ArrayList(Value),
16253 seen_namespaces: *std.AutoHashMap(*Namespace, void),
16254) !void {
16255 const gop = try seen_namespaces.getOrPut(namespace);
16256 if (gop.found_existing) return;
16257 const decls = namespace.decls.keys();
16258 for (decls) |decl_index| {
1622216259 const decl = sema.mod.declPtr(decl_index);
16260 if (decl.kind == .@"usingnamespace") {
16261 try sema.mod.ensureDeclAnalyzed(decl_index);
16262 var buf: Value.ToTypeBuffer = undefined;
16263 const new_ns = decl.val.toType(&buf).getNamespace().?;
16264 try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
16265 continue;
16266 }
16267 if (decl.kind != .named) continue;
1622316268 const name_val = v: {
1622416269 var anon_decl = try block.startAnonDecl();
1622516270 defer anon_decl.deinit();
......@@ -16229,37 +16274,21 @@ fn typeInfoDecls(
1622916274 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1623016275 0, // default alignment
1623116276 );
16232 break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{
16233 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),
16234 .len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),
16277 break :v try Value.Tag.slice.create(decls_anon_decl, .{
16278 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
16279 .len = try Value.Tag.int_u64.create(decls_anon_decl, bytes.len),
1623516280 });
1623616281 };
1623716282
16238 const fields = try decls_anon_decl.arena().create([2]Value);
16283 const fields = try decls_anon_decl.create([2]Value);
1623916284 fields.* = .{
1624016285 //name: []const u8,
1624116286 name_val,
1624216287 //is_pub: bool,
1624316288 Value.makeBool(decl.is_pub),
1624416289 };
16245 decls_val.* = try Value.Tag.aggregate.create(decls_anon_decl.arena(), fields);
16290 try decl_vals.append(try Value.Tag.aggregate.create(decls_anon_decl, fields));
1624616291 }
16247
16248 const new_decl = try decls_anon_decl.finish(
16249 try Type.Tag.array.create(decls_anon_decl.arena(), .{
16250 .len = decls_vals.len,
16251 .elem_type = declaration_ty,
16252 }),
16253 try Value.Tag.aggregate.create(
16254 decls_anon_decl.arena(),
16255 try decls_anon_decl.arena().dupe(Value, decls_vals),
16256 ),
16257 0, // default alignment
16258 );
16259 return try Value.Tag.slice.create(sema.arena, .{
16260 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16261 .len = try Value.Tag.int_u64.create(sema.arena, decls_vals.len),
16262 });
1626316292}
1626416293
1626516294fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -16577,7 +16606,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1657716606 const src = inst_data.src();
1657816607 const operand = try sema.resolveInst(inst_data.operand);
1657916608 try sema.checkErrorType(block, src, sema.typeOf(operand));
16580 return sema.analyzeIsNonErr(block, inst_data.src(), operand);
16609 return sema.analyzeIsNonErr(block, src, operand);
1658116610}
1658216611
1658316612fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -16592,6 +16621,16 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1659216621 return sema.analyzeIsNonErr(block, src, loaded);
1659316622}
1659416623
16624fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16625 const tracy = trace(@src());
16626 defer tracy.end();
16627
16628 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16629 const src = inst_data.src();
16630 const operand = try sema.resolveInst(inst_data.operand);
16631 return sema.analyzeIsNonErr(block, src, operand);
16632}
16633
1659516634fn zirCondbr(
1659616635 sema: *Sema,
1659716636 parent_block: *Block,
......@@ -29847,6 +29886,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
2984729886 },
2984829887 .have_layout, .fully_resolved_wip, .fully_resolved => return,
2984929888 }
29889 const prev_status = struct_obj.status;
29890 errdefer if (struct_obj.status == .layout_wip) {
29891 struct_obj.status = prev_status;
29892 };
29893
2985029894 struct_obj.status = .layout_wip;
2985129895 for (struct_obj.fields.values()) |field, i| {
2985229896 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
......@@ -30026,6 +30070,11 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3002630070 },
3002730071 .have_layout, .fully_resolved_wip, .fully_resolved => return,
3002830072 }
30073 const prev_status = union_obj.status;
30074 errdefer if (union_obj.status == .layout_wip) {
30075 union_obj.status = prev_status;
30076 };
30077
3002930078 union_obj.status = .layout_wip;
3003030079 for (union_obj.fields.values()) |field, i| {
3003130080 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
src/Zir.zig+6
......@@ -481,6 +481,9 @@ pub const Inst = struct {
481481 /// Return a boolean false if dereferenced pointer is an error
482482 /// Uses the `un_node` field.
483483 is_non_err_ptr,
484 /// Same as `is_non_er` but doesn't validate that the type can be an error.
485 /// Uses the `un_node` field.
486 ret_is_non_err,
484487 /// A labeled block of code that loops forever. At the end of the body will have either
485488 /// a `repeat` instruction or a `repeat_inline` instruction.
486489 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
......@@ -1083,6 +1086,7 @@ pub const Inst = struct {
10831086 .is_non_null_ptr,
10841087 .is_non_err,
10851088 .is_non_err_ptr,
1089 .ret_is_non_err,
10861090 .mod_rem,
10871091 .mul,
10881092 .mulwrap,
......@@ -1386,6 +1390,7 @@ pub const Inst = struct {
13861390 .is_non_null_ptr,
13871391 .is_non_err,
13881392 .is_non_err_ptr,
1393 .ret_is_non_err,
13891394 .mod_rem,
13901395 .mul,
13911396 .mulwrap,
......@@ -1640,6 +1645,7 @@ pub const Inst = struct {
16401645 .is_non_null_ptr = .un_node,
16411646 .is_non_err = .un_node,
16421647 .is_non_err_ptr = .un_node,
1648 .ret_is_non_err = .un_node,
16431649 .loop = .pl_node,
16441650 .repeat = .node,
16451651 .repeat_inline = .node,
src/print_zir.zig+1
......@@ -179,6 +179,7 @@ const Writer = struct {
179179 .is_non_null_ptr,
180180 .is_non_err,
181181 .is_non_err_ptr,
182 .ret_is_non_err,
182183 .typeof,
183184 .struct_init_empty,
184185 .type_info,
src/value.zig+10-2
......@@ -2193,8 +2193,16 @@ pub const Value = extern union {
21932193 const payload_ty = ty.errorUnionPayload();
21942194 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
21952195 },
2196 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
2197 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
2196 .eu_payload_ptr => {
2197 const a_payload = a.castTag(.eu_payload_ptr).?.data;
2198 const b_payload = b.castTag(.eu_payload_ptr).?.data;
2199 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
2200 },
2201 .opt_payload_ptr => {
2202 const a_payload = a.castTag(.opt_payload_ptr).?.data;
2203 const b_payload = b.castTag(.opt_payload_ptr).?.data;
2204 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
2205 },
21982206 .function => {
21992207 const a_payload = a.castTag(.function).?.data;
22002208 const b_payload = b.castTag(.function).?.data;
test/behavior/defer.zig+11
......@@ -148,3 +148,14 @@ test "simple else prong doesn't emit an error for unreachable else prong" {
148148 };
149149 try expect(a == 1);
150150}
151
152test "errdefer used in function that doesn't return an error" {
153 const S = struct {
154 fn foo() u8 {
155 var a: u8 = 5;
156 errdefer a += 1;
157 return a;
158 }
159 };
160 try expect(S.foo() == 5);
161}
test/behavior/type_info.zig+24
......@@ -566,3 +566,27 @@ test "value from struct @typeInfo default_value can be loaded at comptime" {
566566 try expect(@ptrCast(*const u8, a).* == 1);
567567 }
568568}
569
570test "@typeInfo decls and usingnamespace" {
571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
573 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
574
575 const A = struct {
576 const x = 5;
577 const y = 34;
578
579 comptime {}
580 };
581 const B = struct {
582 usingnamespace A;
583 const z = 56;
584
585 test {}
586 };
587 const decls = @typeInfo(B).Struct.decls;
588 try expect(decls.len == 3);
589 try expectEqualStrings(decls[0].name, "x");
590 try expectEqualStrings(decls[1].name, "y");
591 try expectEqualStrings(decls[2].name, "z");
592}
test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig created+24
......@@ -0,0 +1,24 @@
1pub fn sort(
2 comptime T: type,
3 items: []T,
4 context: anytype,
5 lessThan: *const fn (context: @TypeOf(context), lhs: T, rhs: T) u32,
6) void {
7 _ = items;
8 _ = lessThan;
9}
10fn foo(_: void, _: u8, _: u8) u32 {
11 return 0;
12}
13pub export fn entry() void {
14 var items = [_]u8{ 3, 5, 7, 2, 6, 9, 4 };
15 sort(u8, &items, void, foo);
16}
17
18// error
19// backend=llvm
20// target=native
21//
22// :15:28: error: expected type '*const fn(comptime type, u8, u8) u32', found '*const fn(void, u8, u8) u32'
23// :15:28: note: pointer type child 'fn(void, u8, u8) u32' cannot cast into pointer type child 'fn(comptime type, u8, u8) u32'
24// :15:28: note: non-generic function cannot cast into a generic function
test/cases/compile_errors/tuple_declarations.zig+1
......@@ -23,3 +23,4 @@ const T = struct {
2323// :5:5: error: union field missing name
2424// :8:5: error: tuple field has a name
2525// :15:5: error: tuple declarations cannot contain declarations
26// :12:5: note: tuple field here