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 {...@@ -362,6 +362,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
362 .wrong_equal_var_decl => {362 .wrong_equal_var_decl => {
363 return stream.writeAll("variable initialized with '==' instead of '='");363 return stream.writeAll("variable initialized with '==' instead of '='");
364 },364 },
365 .var_const_decl => {
366 return stream.writeAll("use 'var' or 'const' to declare variable");
367 },
365368
366 .expected_token => {369 .expected_token => {
367 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];370 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
...@@ -2743,6 +2746,7 @@ pub const Error = struct {...@@ -2743,6 +2746,7 @@ pub const Error = struct {
2743 c_style_container,2746 c_style_container,
2744 expected_var_const,2747 expected_var_const,
2745 wrong_equal_var_decl,2748 wrong_equal_var_decl,
2749 var_const_decl,
27462750
2747 zig_style_container,2751 zig_style_container,
2748 previous_field,2752 previous_field,
lib/std/zig/parse.zig+7
...@@ -471,6 +471,13 @@ const Parser = struct {...@@ -471,6 +471,13 @@ const Parser = struct {
471 // There is not allowed to be a decl after a field with no comma.471 // There is not allowed to be a decl after a field with no comma.
472 // Report error but recover parser.472 // Report error but recover parser.
473 try p.warn(.expected_comma_after_field);473 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 }
474 p.findNextContainerMember();481 p.findNextContainerMember();
475 continue;482 continue;
476 },483 },
lib/std/zig/parser_test.zig+12
...@@ -5238,6 +5238,18 @@ test "zig fmt: missing const/var before local variable" {...@@ -5238,6 +5238,18 @@ test "zig fmt: missing const/var before local variable" {
5238 });5238 });
5239}5239}
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
5241test "zig fmt: while continue expr" {5253test "zig fmt: while continue expr" {
5242 try testCanonical(5254 try testCanonical(
5243 \\test {5255 \\test {
src/AstGen.zig+18-2
...@@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2463 .is_non_null_ptr,2463 .is_non_null_ptr,
2464 .is_non_err,2464 .is_non_err,
2465 .is_non_err_ptr,2465 .is_non_err_ptr,
2466 .ret_is_non_err,
2466 .mod_rem,2467 .mod_rem,
2467 .mul,2468 .mul,
2468 .mulwrap,2469 .mulwrap,
...@@ -4486,9 +4487,24 @@ fn structDeclInner(...@@ -4486,9 +4487,24 @@ fn structDeclInner(
4486 .container_field_align,4487 .container_field_align,
4487 .container_field,4488 .container_field,
4488 .@"comptime",4489 .@"comptime",
4490 .test_decl,
4489 => continue,4491 => continue,
4490 else => {4492 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 );
4492 },4508 },
4493 }4509 }
4494 };4510 };
...@@ -7012,7 +7028,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -7012,7 +7028,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
70127028
7013 // Emit conditional branch for generating errdefers.7029 // Emit conditional branch for generating errdefers.
7014 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;7030 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);
7016 const condbr = try gz.addCondBr(.condbr, node);7032 const condbr = try gz.addCondBr(.condbr, node);
70177033
7018 var then_scope = gz.makeSubBlock(scope);7034 var then_scope = gz.makeSubBlock(scope);
src/Module.zig+22-9
...@@ -528,10 +528,10 @@ pub const Decl = struct {...@@ -528,10 +528,10 @@ pub const Decl = struct {
528 /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it528 /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
529 /// deletes the Decl on the spot.529 /// deletes the Decl on the spot.
530 alive: bool,530 alive: bool,
531 /// Whether the Decl is a `usingnamespace` declaration.
532 is_usingnamespace: bool,
533 /// If true `name` is already fully qualified.531 /// If true `name` is already fully qualified.
534 name_fully_qualified: bool = false,532 name_fully_qualified: bool = false,
533 /// What kind of a declaration is this.
534 kind: Kind,
535535
536 /// Represents the position of the code in the output file.536 /// Represents the position of the code in the output file.
537 /// This is populated regardless of semantic analysis and code generation.537 /// This is populated regardless of semantic analysis and code generation.
...@@ -551,6 +551,14 @@ pub const Decl = struct {...@@ -551,6 +551,14 @@ pub const Decl = struct {
551 /// typed_value may need to be regenerated.551 /// typed_value may need to be regenerated.
552 dependencies: DepsTable = .{},552 dependencies: DepsTable = .{},
553553
554 pub const Kind = enum {
555 @"usingnamespace",
556 @"test",
557 @"comptime",
558 named,
559 anon,
560 };
561
554 pub const Index = enum(u32) {562 pub const Index = enum(u32) {
555 _,563 _,
556564
...@@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4438 // not the struct itself.4446 // not the struct itself.
4439 try sema.resolveTypeLayout(decl_tv.ty);4447 try sema.resolveTypeLayout(decl_tv.ty);
44404448
4441 if (decl.is_usingnamespace) {4449 if (decl.kind == .@"usingnamespace") {
4442 if (!decl_tv.ty.eql(Type.type, mod)) {4450 if (!decl_tv.ty.eql(Type.type, mod)) {
4443 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{4451 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
4444 decl_tv.ty.fmt(mod),4452 decl_tv.ty.fmt(mod),
...@@ -4964,26 +4972,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -4964,26 +4972,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
49644972
4965 // Every Decl needs a name.4973 // Every Decl needs a name.
4966 var is_named_test = false;4974 var is_named_test = false;
4975 var kind: Decl.Kind = .named;
4967 const decl_name: [:0]const u8 = switch (decl_name_index) {4976 const decl_name: [:0]const u8 = switch (decl_name_index) {
4968 0 => name: {4977 0 => name: {
4969 if (export_bit) {4978 if (export_bit) {
4970 const i = iter.usingnamespace_index;4979 const i = iter.usingnamespace_index;
4971 iter.usingnamespace_index += 1;4980 iter.usingnamespace_index += 1;
4981 kind = .@"usingnamespace";
4972 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});4982 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
4973 } else {4983 } else {
4974 const i = iter.comptime_index;4984 const i = iter.comptime_index;
4975 iter.comptime_index += 1;4985 iter.comptime_index += 1;
4986 kind = .@"comptime";
4976 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});4987 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
4977 }4988 }
4978 },4989 },
4979 1 => name: {4990 1 => name: {
4980 const i = iter.unnamed_test_index;4991 const i = iter.unnamed_test_index;
4981 iter.unnamed_test_index += 1;4992 iter.unnamed_test_index += 1;
4993 kind = .@"test";
4982 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});4994 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
4983 },4995 },
4984 2 => name: {4996 2 => name: {
4985 is_named_test = true;4997 is_named_test = true;
4986 const test_name = zir.nullTerminatedString(decl_doccomment_index);4998 const test_name = zir.nullTerminatedString(decl_doccomment_index);
4999 kind = .@"test";
4987 break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});5000 break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});
4988 },5001 },
4989 else => name: {5002 else => name: {
...@@ -4991,6 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -4991,6 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
4991 if (raw_name.len == 0) {5004 if (raw_name.len == 0) {
4992 is_named_test = true;5005 is_named_test = true;
4993 const test_name = zir.nullTerminatedString(decl_name_index + 1);5006 const test_name = zir.nullTerminatedString(decl_name_index + 1);
5007 kind = .@"test";
4994 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});5008 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
4995 } else {5009 } else {
4996 break :name try gpa.dupeZ(u8, raw_name);5010 break :name try gpa.dupeZ(u8, raw_name);
...@@ -4998,8 +5012,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -4998,8 +5012,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
4998 },5012 },
4999 };5013 };
5000 const is_exported = export_bit and decl_name_index != 0;5014 const is_exported = export_bit and decl_name_index != 0;
5001 const is_usingnamespace = export_bit and decl_name_index == 0;5015 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
5002 if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
50035016
5004 // We create a Decl for it regardless of analysis status.5017 // We create a Decl for it regardless of analysis status.
5005 const gop = try namespace.decls.getOrPutContextAdapted(5018 const gop = try namespace.decls.getOrPutContextAdapted(
...@@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5012 if (!gop.found_existing) {5025 if (!gop.found_existing) {
5013 const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);5026 const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);
5014 const new_decl = mod.declPtr(new_decl_index);5027 const new_decl = mod.declPtr(new_decl_index);
5028 new_decl.kind = kind;
5015 new_decl.name = decl_name;5029 new_decl.name = decl_name;
5016 if (is_usingnamespace) {5030 if (kind == .@"usingnamespace") {
5017 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);5031 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
5018 }5032 }
5019 log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });5033 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...@@ -5058,7 +5072,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5058 }5072 }
5059 new_decl.is_pub = is_pub;5073 new_decl.is_pub = is_pub;
5060 new_decl.is_exported = is_exported;5074 new_decl.is_exported = is_exported;
5061 new_decl.is_usingnamespace = is_usingnamespace;
5062 new_decl.has_align = has_align;5075 new_decl.has_align = has_align;
5063 new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5076 new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5064 new_decl.zir_decl_index = @intCast(u32, decl_sub_index);5077 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...@@ -5076,7 +5089,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50765089
5077 decl.is_pub = is_pub;5090 decl.is_pub = is_pub;
5078 decl.is_exported = is_exported;5091 decl.is_exported = is_exported;
5079 decl.is_usingnamespace = is_usingnamespace;5092 decl.kind = kind;
5080 decl.has_align = has_align;5093 decl.has_align = has_align;
5081 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5094 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5082 decl.zir_decl_index = @intCast(u32, decl_sub_index);5095 decl.zir_decl_index = @intCast(u32, decl_sub_index);
...@@ -5635,7 +5648,7 @@ pub fn allocateNewDecl(...@@ -5635,7 +5648,7 @@ pub fn allocateNewDecl(
5635 .has_linksection_or_addrspace = false,5648 .has_linksection_or_addrspace = false,
5636 .has_align = false,5649 .has_align = false,
5637 .alive = false,5650 .alive = false,
5638 .is_usingnamespace = false,5651 .kind = .anon,
5639 };5652 };
56405653
5641 return decl_and_index.decl_index;5654 return decl_and_index.decl_index;
src/Sema.zig+76-27
...@@ -953,6 +953,7 @@ fn analyzeBodyInner(...@@ -953,6 +953,7 @@ fn analyzeBodyInner(
953 .int_type => try sema.zirIntType(block, inst),953 .int_type => try sema.zirIntType(block, inst),
954 .is_non_err => try sema.zirIsNonErr(block, inst),954 .is_non_err => try sema.zirIsNonErr(block, inst),
955 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),955 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
956 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
956 .is_non_null => try sema.zirIsNonNull(block, inst),957 .is_non_null => try sema.zirIsNonNull(block, inst),
957 .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),958 .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),
958 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),959 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),
...@@ -9004,7 +9005,7 @@ fn zirParam(...@@ -9004,7 +9005,7 @@ fn zirParam(
9004 else => |e| return e,9005 else => |e| return e,
9005 } or comptime_syntax;9006 } or comptime_syntax;
9006 if (sema.inst_map.get(inst)) |arg| {9007 if (sema.inst_map.get(inst)) |arg| {
9007 if (is_comptime) {9008 if (is_comptime and sema.preallocated_new_func != null) {
9008 // We have a comptime value for this parameter so it should be elided from the9009 // We have a comptime value for this parameter so it should be elided from the
9009 // function type of the function instruction in this block.9010 // function type of the function instruction in this block.
9010 const coerced_arg = try sema.coerce(block, param_ty, arg, src);9011 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...@@ -10288,6 +10289,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10288 .ret_err_value_code,10289 .ret_err_value_code,
10289 .restore_err_ret_index,10290 .restore_err_ret_index,
10290 .is_non_err,10291 .is_non_err,
10292 .ret_is_non_err,
10291 .condbr,10293 .condbr,
10292 => {},10294 => {},
10293 else => break,10295 else => break,
...@@ -16215,11 +16217,54 @@ fn typeInfoDecls(...@@ -16215,11 +16217,54 @@ fn typeInfoDecls(
16215 };16217 };
16216 try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena));16218 try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena));
1621716219
16218 const decls_len = if (opt_namespace) |ns| ns.decls.count() else 0;16220 var decl_vals = std.ArrayList(Value).init(sema.gpa);
16219 const decls_vals = try decls_anon_decl.arena().alloc(Value, decls_len);16221 defer decl_vals.deinit();
16220 for (decls_vals) |*decls_val, i| {16222
16221 const decl_index = opt_namespace.?.decls.keys()[i];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| {
16222 const decl = sema.mod.declPtr(decl_index);16259 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;
16223 const name_val = v: {16268 const name_val = v: {
16224 var anon_decl = try block.startAnonDecl();16269 var anon_decl = try block.startAnonDecl();
16225 defer anon_decl.deinit();16270 defer anon_decl.deinit();
...@@ -16229,37 +16274,21 @@ fn typeInfoDecls(...@@ -16229,37 +16274,21 @@ fn typeInfoDecls(
16229 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16274 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16230 0, // default alignment16275 0, // default alignment
16231 );16276 );
16232 break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{16277 break :v try Value.Tag.slice.create(decls_anon_decl, .{
16233 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),16278 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
16234 .len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),16279 .len = try Value.Tag.int_u64.create(decls_anon_decl, bytes.len),
16235 });16280 });
16236 };16281 };
1623716282
16238 const fields = try decls_anon_decl.arena().create([2]Value);16283 const fields = try decls_anon_decl.create([2]Value);
16239 fields.* = .{16284 fields.* = .{
16240 //name: []const u8,16285 //name: []const u8,
16241 name_val,16286 name_val,
16242 //is_pub: bool,16287 //is_pub: bool,
16243 Value.makeBool(decl.is_pub),16288 Value.makeBool(decl.is_pub),
16244 };16289 };
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));
16246 }16291 }
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 });
16263}16292}
1626416293
16265fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {16294fn 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...@@ -16577,7 +16606,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16577 const src = inst_data.src();16606 const src = inst_data.src();
16578 const operand = try sema.resolveInst(inst_data.operand);16607 const operand = try sema.resolveInst(inst_data.operand);
16579 try sema.checkErrorType(block, src, sema.typeOf(operand));16608 try sema.checkErrorType(block, src, sema.typeOf(operand));
16580 return sema.analyzeIsNonErr(block, inst_data.src(), operand);16609 return sema.analyzeIsNonErr(block, src, operand);
16581}16610}
1658216611
16583fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {16612fn 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...@@ -16592,6 +16621,16 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
16592 return sema.analyzeIsNonErr(block, src, loaded);16621 return sema.analyzeIsNonErr(block, src, loaded);
16593}16622}
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
16595fn zirCondbr(16634fn zirCondbr(
16596 sema: *Sema,16635 sema: *Sema,
16597 parent_block: *Block,16636 parent_block: *Block,
...@@ -29847,6 +29886,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -29847,6 +29886,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
29847 },29886 },
29848 .have_layout, .fully_resolved_wip, .fully_resolved => return,29887 .have_layout, .fully_resolved_wip, .fully_resolved => return,
29849 }29888 }
29889 const prev_status = struct_obj.status;
29890 errdefer if (struct_obj.status == .layout_wip) {
29891 struct_obj.status = prev_status;
29892 };
29893
29850 struct_obj.status = .layout_wip;29894 struct_obj.status = .layout_wip;
29851 for (struct_obj.fields.values()) |field, i| {29895 for (struct_obj.fields.values()) |field, i| {
29852 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {29896 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
...@@ -30026,6 +30070,11 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -30026,6 +30070,11 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
30026 },30070 },
30027 .have_layout, .fully_resolved_wip, .fully_resolved => return,30071 .have_layout, .fully_resolved_wip, .fully_resolved => return,
30028 }30072 }
30073 const prev_status = union_obj.status;
30074 errdefer if (union_obj.status == .layout_wip) {
30075 union_obj.status = prev_status;
30076 };
30077
30029 union_obj.status = .layout_wip;30078 union_obj.status = .layout_wip;
30030 for (union_obj.fields.values()) |field, i| {30079 for (union_obj.fields.values()) |field, i| {
30031 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {30080 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
src/Zir.zig+6
...@@ -481,6 +481,9 @@ pub const Inst = struct {...@@ -481,6 +481,9 @@ pub const Inst = struct {
481 /// Return a boolean false if dereferenced pointer is an error481 /// Return a boolean false if dereferenced pointer is an error
482 /// Uses the `un_node` field.482 /// Uses the `un_node` field.
483 is_non_err_ptr,483 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,
484 /// A labeled block of code that loops forever. At the end of the body will have either487 /// A labeled block of code that loops forever. At the end of the body will have either
485 /// a `repeat` instruction or a `repeat_inline` instruction.488 /// a `repeat` instruction or a `repeat_inline` instruction.
486 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.489 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
...@@ -1083,6 +1086,7 @@ pub const Inst = struct {...@@ -1083,6 +1086,7 @@ pub const Inst = struct {
1083 .is_non_null_ptr,1086 .is_non_null_ptr,
1084 .is_non_err,1087 .is_non_err,
1085 .is_non_err_ptr,1088 .is_non_err_ptr,
1089 .ret_is_non_err,
1086 .mod_rem,1090 .mod_rem,
1087 .mul,1091 .mul,
1088 .mulwrap,1092 .mulwrap,
...@@ -1386,6 +1390,7 @@ pub const Inst = struct {...@@ -1386,6 +1390,7 @@ pub const Inst = struct {
1386 .is_non_null_ptr,1390 .is_non_null_ptr,
1387 .is_non_err,1391 .is_non_err,
1388 .is_non_err_ptr,1392 .is_non_err_ptr,
1393 .ret_is_non_err,
1389 .mod_rem,1394 .mod_rem,
1390 .mul,1395 .mul,
1391 .mulwrap,1396 .mulwrap,
...@@ -1640,6 +1645,7 @@ pub const Inst = struct {...@@ -1640,6 +1645,7 @@ pub const Inst = struct {
1640 .is_non_null_ptr = .un_node,1645 .is_non_null_ptr = .un_node,
1641 .is_non_err = .un_node,1646 .is_non_err = .un_node,
1642 .is_non_err_ptr = .un_node,1647 .is_non_err_ptr = .un_node,
1648 .ret_is_non_err = .un_node,
1643 .loop = .pl_node,1649 .loop = .pl_node,
1644 .repeat = .node,1650 .repeat = .node,
1645 .repeat_inline = .node,1651 .repeat_inline = .node,
src/print_zir.zig+1
...@@ -179,6 +179,7 @@ const Writer = struct {...@@ -179,6 +179,7 @@ const Writer = struct {
179 .is_non_null_ptr,179 .is_non_null_ptr,
180 .is_non_err,180 .is_non_err,
181 .is_non_err_ptr,181 .is_non_err_ptr,
182 .ret_is_non_err,
182 .typeof,183 .typeof,
183 .struct_init_empty,184 .struct_init_empty,
184 .type_info,185 .type_info,
src/value.zig+10-2
...@@ -2193,8 +2193,16 @@ pub const Value = extern union {...@@ -2193,8 +2193,16 @@ pub const Value = extern union {
2193 const payload_ty = ty.errorUnionPayload();2193 const payload_ty = ty.errorUnionPayload();
2194 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);2194 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
2195 },2195 },
2196 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),2196 .eu_payload_ptr => {
2197 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),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 },
2198 .function => {2206 .function => {
2199 const a_payload = a.castTag(.function).?.data;2207 const a_payload = a.castTag(.function).?.data;
2200 const b_payload = b.castTag(.function).?.data;2208 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" {...@@ -148,3 +148,14 @@ test "simple else prong doesn't emit an error for unreachable else prong" {
148 };148 };
149 try expect(a == 1);149 try expect(a == 1);
150}150}
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" {...@@ -566,3 +566,27 @@ test "value from struct @typeInfo default_value can be loaded at comptime" {
566 try expect(@ptrCast(*const u8, a).* == 1);566 try expect(@ptrCast(*const u8, a).* == 1);
567 }567 }
568}568}
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 {...@@ -23,3 +23,4 @@ const T = struct {
23// :5:5: error: union field missing name23// :5:5: error: union field missing name
24// :8:5: error: tuple field has a name24// :8:5: error: tuple field has a name
25// :15:5: error: tuple declarations cannot contain declarations25// :15:5: error: tuple declarations cannot contain declarations
26// :12:5: note: tuple field here