diff --git a/src/AstGen.zig b/src/AstGen.zig index b2bbb27865..e30913ac76 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -768,12 +768,12 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)), .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)), - .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node)), - .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node)), - .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node)), + .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node), false), + .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node), false), + .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node), false), - .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node)), - .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node)), + .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node), false), + .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node), false), .slice_open => { const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); @@ -1899,6 +1899,17 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, .namespace => break, .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, + .defer_gen => { + const defer_gen = scope.cast(Scope.DeferGen).?; + + return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ + try astgen.errNoteNode( + defer_gen.defer_node, + "defer expression here", + .{}, + ), + }); + }, .top => unreachable, } } @@ -1958,6 +1969,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); }, .defer_error => scope = scope.cast(Scope.Defer).?.parent, + .defer_gen => { + const defer_gen = scope.cast(Scope.DeferGen).?; + + return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ + try astgen.errNoteNode( + defer_gen.defer_node, + "defer expression here", + .{}, + ), + }); + }, .namespace => break, .top => unreachable, } @@ -2022,6 +2044,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke .local_val => scope = scope.cast(Scope.LocalVal).?.parent, .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, + .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, .namespace => break, .top => unreachable, } @@ -2129,6 +2152,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod const astgen = gz.astgen; const tree = astgen.tree; const node_tags = tree.nodes.items(.tag); + const node_data = tree.nodes.items(.data); if (statements.len == 0) return; @@ -2155,8 +2179,10 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod }, ); } - switch (node_tags[statement]) { - // zig fmt: off + var inner_node = statement; + while (true) { + switch (node_tags[inner_node]) { + // zig fmt: off .global_var_decl => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.globalVarDecl(statement)), .local_var_decl => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.localVarDecl(statement)), .simple_var_decl => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.simpleVarDecl(statement)), @@ -2181,9 +2207,23 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap), .assign_mul => try assignOp(gz, scope, statement, .mul), .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap), + + .grouped_expression => { + inner_node = node_data[statement].lhs; + continue; + }, - else => noreturn_src_node = try unusedResultExpr(gz, scope, statement), + .while_simple => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileSimple(inner_node), true), + .while_cont => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileCont(inner_node), true), + .@"while" => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileFull(inner_node), true), + + .for_simple => _ = try forExpr(gz, scope, .discard, inner_node, tree.forSimple(inner_node), true), + .@"for" => _ = try forExpr(gz, scope, .discard, inner_node, tree.forFull(inner_node), true), + + else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node), // zig fmt: on + } + break; } } @@ -2206,7 +2246,13 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc astgen.source_offset = defer_scope.source_offset; astgen.source_line = defer_scope.source_line; astgen.source_column = defer_scope.source_column; - _ = try unusedResultExpr(gz, expr_scope, expr_node); + + var defer_gen: Scope.DeferGen = .{ + .parent = expr_scope, + .defer_node = defer_scope.defer_node, + }; + + _ = try unusedResultExpr(gz, &defer_gen.base, expr_node); } /// Returns AST source node of the thing that is noreturn if the statement is @@ -2216,6 +2262,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner // We need to emit an error if the result is not `noreturn` or `void`, but // we want to avoid adding the ZIR instruction if possible for performance. const maybe_unused_result = try expr(gz, scope, .none, statement); + return addEnsureResult(gz, maybe_unused_result, statement); +} + +fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index { var noreturn_src_node: Ast.Node.Index = 0; const elide_check = if (refToIndex(maybe_unused_result)) |inst| b: { // Note that this array becomes invalid after appending more items to it @@ -2553,6 +2603,7 @@ fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct .gen_zir => scope = scope.cast(GenZir).?.parent, .local_val => scope = scope.cast(Scope.LocalVal).?.parent, .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, + .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, .defer_normal => { const defer_scope = scope.cast(Scope.Defer).?; scope = defer_scope.parent; @@ -2602,6 +2653,7 @@ fn genDefers( .gen_zir => scope = scope.cast(GenZir).?.parent, .local_val => scope = scope.cast(Scope.LocalVal).?.parent, .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, + .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, .defer_normal => { const defer_scope = scope.cast(Scope.Defer).?; scope = defer_scope.parent; @@ -2644,6 +2696,7 @@ fn genDefers( break :blk &local_val_scope.base; }; try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node); + try checkUsed(gz, scope, sub_scope); try gz.addDbgBlockEnd(); }, .normal_only => continue, @@ -2681,6 +2734,7 @@ fn checkUsed( scope = s.parent; }, .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, + .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent, .namespace => unreachable, .top => unreachable, } @@ -4040,6 +4094,7 @@ fn testDecl( .local_val, .local_ptr => unreachable, // a test cannot be in a local scope .gen_zir => s = s.cast(GenZir).?.parent, .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, + .defer_gen => s = s.cast(Scope.DeferGen).?.parent, .namespace => { const ns = s.cast(Scope.Namespace).?; if (ns.decls.get(name_str_index)) |i| { @@ -5330,7 +5385,7 @@ fn ifExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, - .bool_bit = try block_scope.addUnNode(tag, err_union, node), + .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr), }; } else if (if_full.payload_token) |_| { const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; @@ -5338,7 +5393,7 @@ fn ifExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, - .bool_bit = try block_scope.addUnNode(tag, optional, node), + .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr), }; } else { const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr); @@ -5369,7 +5424,7 @@ fn ifExpr( .err_union_payload_unsafe_ptr else .err_union_payload_unsafe; - const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); + const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr); const token_name_index = payload_token + @boolToInt(payload_is_ref); const ident_name = try astgen.identAsString(token_name_index); const token_name_str = tree.tokenSlice(token_name_index); @@ -5398,7 +5453,7 @@ fn ifExpr( const ident_bytes = tree.tokenSlice(ident_token); if (mem.eql(u8, "_", ident_bytes)) break :s &then_scope.base; - const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); + const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr); const ident_name = try astgen.identAsString(ident_token); try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes); payload_val_scope = .{ @@ -5441,7 +5496,7 @@ fn ifExpr( .err_union_code_ptr else .err_union_code; - const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); + const payload_inst = try else_scope.addUnNode(tag, cond.inst, if_full.ast.cond_expr); const ident_name = try astgen.identAsString(error_token); const error_token_str = tree.tokenSlice(error_token); if (mem.eql(u8, "_", error_token_str)) @@ -5615,6 +5670,7 @@ fn whileExpr( rl: ResultLoc, node: Ast.Node.Index, while_full: Ast.full.While, + is_statement: bool, ) InnerError!Zir.Inst.Ref { const astgen = parent_gz.astgen; const tree = astgen.tree; @@ -5654,7 +5710,7 @@ fn whileExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, - .bool_bit = try continue_scope.addUnNode(tag, err_union, node), + .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr), }; } else if (while_full.payload_token) |_| { const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; @@ -5662,7 +5718,7 @@ fn whileExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, - .bool_bit = try continue_scope.addUnNode(tag, optional, node), + .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr), }; } else { const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr); @@ -5700,7 +5756,7 @@ fn whileExpr( else .err_union_payload_unsafe; // will add this instruction to then_scope.instructions below - payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); + payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr); const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; const ident_bytes = tree.tokenSlice(ident_token); if (mem.eql(u8, "_", ident_bytes)) @@ -5729,7 +5785,7 @@ fn whileExpr( else .optional_payload_unsafe; // will add this instruction to then_scope.instructions below - payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); + payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr); const ident_name = try astgen.identAsString(ident_token); const ident_bytes = tree.tokenSlice(ident_token); if (mem.eql(u8, "_", ident_bytes)) @@ -5785,6 +5841,8 @@ fn whileExpr( try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); } const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); + _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); + try checkUsed(parent_gz, &then_scope.base, then_sub_scope); try then_scope.addDbgBlockEnd(); @@ -5803,7 +5861,7 @@ fn whileExpr( .err_union_code_ptr else .err_union_code; - const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, node); + const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, while_full.ast.cond_expr); const ident_name = try astgen.identAsString(error_token); const ident_bytes = tree.tokenSlice(error_token); if (mem.eql(u8, ident_bytes, "_")) @@ -5827,7 +5885,11 @@ fn whileExpr( // control flow apply to outer loops; not this one. loop_scope.continue_block = 0; loop_scope.break_block = 0; - const e = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); + const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); + if (is_statement) { + _ = try addEnsureResult(&else_scope, else_result, else_node); + } + if (!else_scope.endsWithNoReturn()) { loop_scope.break_count += 1; } @@ -5835,7 +5897,7 @@ fn whileExpr( try else_scope.addDbgBlockEnd(); break :blk .{ .src = else_node, - .result = e, + .result = else_result, }; } else .{ .src = while_full.ast.then_expr, @@ -5848,7 +5910,7 @@ fn whileExpr( } } const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; - return finishThenElseBlock( + const result = try finishThenElseBlock( parent_gz, rl, node, @@ -5863,6 +5925,10 @@ fn whileExpr( cond_block, break_tag, ); + if (is_statement) { + _ = try parent_gz.addUnNode(.ensure_result_used, result, node); + } + return result; } fn forExpr( @@ -5871,6 +5937,7 @@ fn forExpr( rl: ResultLoc, node: Ast.Node.Index, for_full: Ast.full.While, + is_statement: bool, ) InnerError!Zir.Inst.Ref { const astgen = parent_gz.astgen; @@ -6014,6 +6081,8 @@ fn forExpr( }; const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); + _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); + try checkUsed(parent_gz, &then_scope.base, then_sub_scope); try then_scope.addDbgBlockEnd(); @@ -6031,6 +6100,10 @@ fn forExpr( loop_scope.continue_block = 0; loop_scope.break_block = 0; const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); + if (is_statement) { + _ = try addEnsureResult(&else_scope, else_result, else_node); + } + if (!else_scope.endsWithNoReturn()) { loop_scope.break_count += 1; } @@ -6049,7 +6122,7 @@ fn forExpr( } } const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; - return finishThenElseBlock( + const result = try finishThenElseBlock( parent_gz, rl, node, @@ -6064,6 +6137,10 @@ fn forExpr( cond_block, break_tag, ); + if (is_statement) { + _ = try parent_gz.addUnNode(.ensure_result_used, result, node); + } + return result; } fn switchExpr( @@ -6730,6 +6807,7 @@ fn localVarRef( }, .gen_zir => s = s.cast(GenZir).?.parent, .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, + .defer_gen => s = s.cast(Scope.DeferGen).?.parent, .namespace => { const ns = s.cast(Scope.Namespace).?; if (ns.decls.get(name_str_index)) |i| { @@ -7351,6 +7429,7 @@ fn builtinCall( }, .gen_zir => s = s.cast(GenZir).?.parent, .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, + .defer_gen => s = s.cast(Scope.DeferGen).?.parent, .namespace => { const ns = s.cast(Scope.Namespace).?; if (ns.decls.get(decl_name)) |i| { @@ -9808,6 +9887,7 @@ const Scope = struct { local_ptr, defer_normal, defer_error, + defer_gen, namespace, top, }; @@ -9905,6 +9985,13 @@ const Scope = struct { const base_tag: Scope.Tag = .top; base: Scope = Scope{ .tag = base_tag }, }; + + const DeferGen = struct { + const base_tag: Scope.Tag = .defer_gen; + base: Scope = Scope{ .tag = base_tag }, + parent: *Scope, + defer_node: Ast.Node.Index, + }; }; /// This is a temporary structure; references to it are valid only @@ -11415,6 +11502,7 @@ fn detectLocalShadowing( }, .gen_zir => s = s.cast(GenZir).?.parent, .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, + .defer_gen => s = s.cast(Scope.DeferGen).?.parent, .top => break, }; } diff --git a/src/Sema.zig b/src/Sema.zig index e41602a037..2721ed5179 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -74,6 +74,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{}, /// Sema must convert comptime control flow to runtime control flow, which means /// breaking from a block. post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, +/// Populated with the last compile error created. +err: ?*Module.ErrorMsg = null, const std = @import("std"); const mem = std.mem; @@ -174,7 +176,6 @@ pub const Block = struct { pub const Inlining = struct { comptime_result: Air.Inst.Ref, merges: Merges, - err: ?*Module.ErrorMsg = null, }; pub const Merges = struct { @@ -1159,7 +1160,7 @@ fn analyzeBodyInner( try sema.errNote(block, runtime_src, msg, "runtime control flow here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } i += 1; @@ -1738,7 +1739,7 @@ fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: [ try sema.errNote(block, src, msg, "{s}", .{reason}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { @@ -1770,7 +1771,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty } break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { @@ -1801,7 +1802,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.fail(block, src, "overflow of integer type '{}' with value '{}'", .{ int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod), @@ -1823,7 +1824,7 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS try sema.errNote(block, default_value_src, msg, "default value set here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } /// We don't return a pointer to the new error note because the pointer @@ -1878,10 +1879,10 @@ pub fn fail( args: anytype, ) CompileError { const err_msg = try sema.errMsg(block, src, format, args); - return sema.failWithOwnedErrorMsg(block, err_msg); + return sema.failWithOwnedErrorMsg(err_msg); } -fn failWithOwnedErrorMsg(sema: *Sema, block: *Block, err_msg: *Module.ErrorMsg) CompileError { +fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { @setCold(true); if (crash_report.is_enabled and sema.mod.comp.debug_compile_errors) { @@ -1894,7 +1895,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: *Block, err_msg: *Module.ErrorMsg) } const mod = sema.mod; - if (block.inlining) |some| some.err = err_msg; + sema.err = err_msg; { errdefer err_msg.destroy(mod.gpa); @@ -2591,7 +2592,7 @@ fn zirEnumDecl( try sema.errNote(block, other_tag_src, msg, "other field here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (has_tag_value) { @@ -2886,7 +2887,7 @@ fn ensureResultUsed( try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, else => { const msg = msg: { @@ -2896,7 +2897,7 @@ fn ensureResultUsed( try sema.errNote(block, src, msg, "this error can be suppressed by assigning the value to '_'", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, } } @@ -2917,7 +2918,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, else => return, } @@ -2957,7 +2958,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE ); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.fieldVal(block, src, object, "len", src); @@ -3615,7 +3616,7 @@ fn validateUnionInit( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if ((is_comptime or block.is_comptime) and @@ -3747,7 +3748,7 @@ fn validateStructInit( try sema.errNote(block, other_field_src, msg, "other field here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } found_fields[field_index] = field_ptr; } @@ -3808,7 +3809,7 @@ fn validateStructInit( .{fqn}, ); } - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return; @@ -3938,7 +3939,7 @@ fn validateStructInit( .{fqn}, ); } - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (struct_is_comptime) { @@ -4000,7 +4001,7 @@ fn zirValidateArrayInit( } if (root_msg) |msg| { - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -4180,7 +4181,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(src_decl), elem_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -4206,7 +4207,7 @@ fn failWithBadMemberAccess( try sema.addDeclaredHereNote(msg, agg_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn failWithBadStructFieldAccess( @@ -4232,7 +4233,7 @@ fn failWithBadStructFieldAccess( try sema.mod.errNoteNonLazy(struct_obj.srcLoc(sema.mod), msg, "struct declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn failWithBadUnionFieldAccess( @@ -4258,7 +4259,7 @@ fn failWithBadUnionFieldAccess( try sema.mod.errNoteNonLazy(union_obj.srcLoc(sema.mod), msg, "union declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { @@ -4747,7 +4748,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len); break :msg msg; }; - return sema.failWithOwnedErrorMsg(parent_block, msg); + return sema.failWithOwnedErrorMsg(msg); } const c_import_pkg = Package.create( sema.gpa, @@ -4921,7 +4922,7 @@ fn analyzeBlockBody( break :msg msg; }; - return sema.failWithOwnedErrorMsg(child_block, msg); + return sema.failWithOwnedErrorMsg(msg); } const ty_inst = try sema.addType(resolved_ty); try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + @@ -5060,7 +5061,7 @@ pub fn analyzeExport( try sema.addDeclaredHereNote(msg, exported_decl.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const gpa = mod.gpa; @@ -5150,7 +5151,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst try sema.errNote(block, gop.value_ptr.src, msg, "other instance here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } gop.value_ptr.* = .{ .alignment = alignment, .src = src }; } @@ -5311,7 +5312,14 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const src = inst_data.src(); const decl_name = inst_data.get(sema.code); const decl_index = try sema.lookupIdentifier(block, src, decl_name); - return sema.analyzeDeclRef(decl_index); + return sema.analyzeDeclRef(decl_index) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.errNote(block, src, msg, "referenced here", .{}); + return err; + }, + else => return err, + }; } fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -5413,7 +5421,7 @@ fn lookupInNamespace( } break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, } } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .mod = mod })) |decl_index| { @@ -5872,9 +5880,8 @@ fn analyzeCall( sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { error.ComptimeReturn => break :result inlining.comptime_result, error.AnalysisFail => { - const err_msg = inlining.err orelse return err; + const err_msg = sema.err orelse return err; try sema.errNote(block, call_src, err_msg, "called from here", .{}); - if (block.inlining) |some| some.err = err_msg; return err; }, else => |e| return e, @@ -6802,7 +6809,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr try sema.errNote(block, src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); @@ -6927,7 +6934,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A try sema.addDeclaredHereNote(msg, dest_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.addConstant(dest_ty, int_val); } @@ -7632,7 +7639,7 @@ fn funcCommon( try sema.addDeclaredHereNote(msg, bare_return_type); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) { const msg = msg: { @@ -7647,7 +7654,7 @@ fn funcCommon( try sema.addDeclaredHereNote(msg, return_type); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const arch = sema.mod.getTarget().cpu.arch; @@ -7812,7 +7819,7 @@ fn analyzeParameter( try sema.errNote(block, param_src, msg, "function is generic because of this parameter", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (this_generic and !Type.fnCallingConventionAllowsZigTypes(cc)) { return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); @@ -7828,7 +7835,7 @@ fn analyzeParameter( try sema.addDeclaredHereNote(msg, param.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) { const msg = msg: { @@ -7843,7 +7850,7 @@ fn analyzeParameter( try sema.addDeclaredHereNote(msg, param.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (requires_comptime and !param.is_comptime) { const msg = msg: { @@ -7855,7 +7862,7 @@ fn analyzeParameter( try sema.addDeclaredHereNote(msg, param.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -8318,7 +8325,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Pointer => { @@ -8333,7 +8340,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { const container = switch (dest_ty.zigTypeTag()) { @@ -8383,7 +8390,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Pointer => { const msg = msg: { @@ -8397,7 +8404,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { const container = switch (operand_ty.zigTypeTag()) { @@ -8663,7 +8670,7 @@ fn zirSwitchCapture( try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(sema.mod)}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -8786,7 +8793,7 @@ fn zirSwitchCond( } break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; return sema.unionToTag(block, enum_ty, operand, src); }, @@ -8875,7 +8882,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError ); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const target = sema.mod.getTarget(); @@ -8979,7 +8986,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError ); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } else if (special_prong == .none and operand_ty.isNonexhaustiveEnum() and !union_originally) { return sema.fail( block, @@ -9079,7 +9086,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (maybe_msg) |msg| { maybe_msg = null; try sema.addDeclaredHereNote(msg, operand_ty); - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) { @@ -9888,7 +9895,7 @@ fn validateSwitchDupe( ); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn validateSwitchItemBool( @@ -9958,7 +9965,7 @@ fn validateSwitchNoRange( ); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -12882,7 +12889,7 @@ fn analyzeCmpUnionTag( try sema.mod.errNoteNonLazy(union_ty.declSrcLoc(sema.mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(sema.mod)}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; // Coerce both the union and the tag to the union's tag type, and then execute the // enum comparison codepath. @@ -13143,6 +13150,36 @@ fn zirClosureGet( scope = scope.parent.?; } else unreachable; + if (tv.val.tag() == .generic_poison and !block.is_typeof and !block.is_comptime and sema.func != null) { + const msg = msg: { + const name = name: { + const file = sema.owner_decl.getFileScope(); + const tree = file.getTree(sema.mod.gpa) catch |err| { + // In this case we emit a warning + a less precise source location. + log.warn("unable to load {s}: {s}", .{ + file.sub_file_path, @errorName(err), + }); + break :name null; + }; + const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node); + const token = tree.nodes.items(.main_token)[node]; + break :name tree.tokenSlice(token); + }; + + const msg = if (name) |some| + try sema.errMsg(block, inst_data.src(), "'{s}' not accessible from inner function", .{some}) + else + try sema.errMsg(block, inst_data.src(), "variable not accessible from inner function", .{}); + errdefer msg.destroy(sema.gpa); + + try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); + + // TODO add "declared here" note + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); + } + return sema.addConstant(tv.ty, tv.val); } @@ -14877,7 +14914,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (elem_ty.zigTypeTag() == .Opaque) { return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{}); @@ -15048,7 +15085,7 @@ fn zirStructInit( try sema.errNote(block, other_field_src, msg, "other field here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } found_fields[field_index] = item.data.field_type; field_inits[field_index] = try sema.resolveInst(item.data.init); @@ -15189,7 +15226,7 @@ fn finishStructInit( .{fqn}, ); } - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const is_comptime = for (field_inits) |field_init| { @@ -15264,7 +15301,7 @@ fn zirStructInitAnon( try sema.errNote(block, prev_source, msg, "other field here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } gop.value_ptr.* = @intCast(u32, i); @@ -15280,7 +15317,7 @@ fn zirStructInitAnon( try sema.addDeclaredHereNote(msg, types[i]); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const init_src = src; // TODO better source location if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { @@ -15478,7 +15515,7 @@ fn zirArrayInitAnon( try sema.addDeclaredHereNote(msg, types[i]); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (try sema.resolveMaybeUndefVal(block, operand_src, elem)) |val| { values[i] = val; @@ -15792,7 +15829,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air try sema.addDeclaredHereNote(msg, operand_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{ operand_ty.fmt(mod), @@ -15811,7 +15848,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air try mod.errNoteNonLazy(enum_decl.srcLoc(), msg, "declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; const field_name = enum_ty.enumFieldName(field_index); return sema.addStrLit(block, field_name); @@ -15961,7 +15998,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (elem_ty.zigTypeTag() == .Opaque) { return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); @@ -16364,7 +16401,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I try sema.addDeclaredHereNote(msg, union_obj.tag_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -16398,7 +16435,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I try sema.addDeclaredHereNote(msg, union_obj.tag_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -16868,7 +16905,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat try sema.addDeclaredHereNote(msg, dest_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (maybe_operand_val) |val| { @@ -16886,7 +16923,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat try sema.addDeclaredHereNote(msg, dest_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -17024,7 +17061,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -17315,7 +17352,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 try sema.addDeclaredHereNote(msg, ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, } @@ -17419,7 +17456,7 @@ fn checkPtrOperand( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Optional => if (ty.isPtrLikeOptional()) return, else => {}, @@ -17449,7 +17486,7 @@ fn checkPtrType( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, .Optional => if (ty.isPtrLikeOptional()) return, else => {}, @@ -17585,7 +17622,7 @@ fn checkComptimeVarStore( try sema.errNote(block, cond_src, msg, "runtime condition here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (block.runtime_loop) |loop_src| { const msg = msg: { @@ -17594,7 +17631,7 @@ fn checkComptimeVarStore( try sema.errNote(block, loop_src, msg, "non-inline loop here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } unreachable; } @@ -17731,7 +17768,7 @@ fn checkVectorizableBinaryOperands( try sema.errNote(block, rhs_src, msg, "length {d} here", .{rhs_len}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } else { const msg = msg: { @@ -17748,7 +17785,7 @@ fn checkVectorizableBinaryOperands( } break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -18148,7 +18185,7 @@ fn analyzeShuffle( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -18744,7 +18781,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr try sema.addDeclaredHereNote(msg, struct_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.addConstant(result_ptr, payload.data.container_ptr); } @@ -19544,7 +19581,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: } break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } try sema.requireFunctionBlock(block, src); } @@ -19573,7 +19610,7 @@ fn validateVarType( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn validateRunTimeType( @@ -20275,7 +20312,7 @@ fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { "use @setEvalBranchQuota() to raise the branch limit from {d}", .{sema.branch_quota}, ); - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -20383,7 +20420,7 @@ fn fieldVal( try sema.addDeclaredHereNote(msg, child_type); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } else (try sema.mod.getErrorValue(field_name)).key; return sema.addConstant( @@ -20438,7 +20475,7 @@ fn fieldVal( if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }, } }, @@ -20776,7 +20813,7 @@ fn fieldCallBind( try sema.addDeclaredHereNote(msg, concrete_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn finishFieldCallBind( @@ -20831,7 +20868,7 @@ fn namespaceLookup( try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } return decl_index; } @@ -20846,7 +20883,14 @@ fn namespaceLookupRef( decl_name: []const u8, ) CompileError!?Air.Inst.Ref { const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null; - return try sema.analyzeDeclRef(decl); + return sema.analyzeDeclRef(decl) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.errNote(block, src, msg, "referenced here", .{}); + return err; + }, + else => return err, + }; } fn namespaceLookupVal( @@ -21164,7 +21208,7 @@ fn unionFieldPtr( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } }, .Packed, .Extern => {}, @@ -21234,7 +21278,7 @@ fn unionFieldVal( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } }, .Packed, .Extern => { @@ -21408,7 +21452,7 @@ fn validateRuntimeElemAccess( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -22184,7 +22228,7 @@ fn coerceExtra( try sema.addDeclaredHereNote(msg, dest_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; return sema.addConstant( dest_ty, @@ -22312,7 +22356,7 @@ fn coerceExtra( try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "'noreturn' declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const msg = msg: { @@ -22353,7 +22397,7 @@ fn coerceExtra( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const InMemoryCoercionResult = union(enum) { @@ -24418,7 +24462,7 @@ fn coerceEnumToUnion( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); @@ -24433,7 +24477,7 @@ fn coerceEnumToUnion( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; const field = union_obj.fields.values()[field_index]; const field_ty = try sema.resolveTypeFields(block, inst_src, field.ty); @@ -24449,7 +24493,7 @@ fn coerceEnumToUnion( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); }; return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ @@ -24469,7 +24513,7 @@ fn coerceEnumToUnion( try sema.addDeclaredHereNote(msg, tag_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } // If the union has all fields 0 bits, the union value is just the enum value. @@ -24498,7 +24542,7 @@ fn coerceEnumToUnion( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } fn coerceAnonStructToUnion( @@ -24527,7 +24571,7 @@ fn coerceAnonStructToUnion( try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const field_name = anon_struct.names[0]; @@ -24587,7 +24631,7 @@ fn coerceArrayLike( try sema.errNote(block, inst_src, msg, "source has length {d}", .{inst_len}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const dest_elem_ty = dest_ty.childType(); @@ -24659,7 +24703,7 @@ fn coerceTupleToArray( try sema.errNote(block, inst_src, msg, "source has length {d}", .{inst_len}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLenIncludingSentinel()); @@ -24822,7 +24866,7 @@ fn coerceTupleToStruct( if (root_msg) |msg| { try sema.addDeclaredHereNote(msg, struct_ty); - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (runtime_src) |rs| { @@ -24926,7 +24970,7 @@ fn coerceTupleToTuple( if (root_msg) |msg| { try sema.addDeclaredHereNote(msg, tuple_ty); - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } if (runtime_src) |rs| { @@ -24949,7 +24993,14 @@ fn analyzeDeclVal( if (sema.decl_val_table.get(decl_index)) |result| { return result; } - const decl_ref = try sema.analyzeDeclRef(decl_index); + const decl_ref = sema.analyzeDeclRef(decl_index) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.errNote(block, src, msg, "referenced here", .{}); + return err; + }, + else => return err, + }; const result = try sema.analyzeLoad(block, src, decl_ref, src); if (Air.refToIndex(result)) |index| { if (sema.air_instructions.items(.tag)[index] == .constant and !block.is_typeof) { @@ -24960,6 +25011,12 @@ fn analyzeDeclVal( } fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { + const decl = sema.mod.declPtr(decl_index); + if (decl.analysis == .in_progress) { + const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(), "dependency loop detected", .{}); + return sema.failWithOwnedErrorMsg(msg); + } + sema.mod.ensureDeclAnalyzed(decl_index) catch |err| { if (sema.owner_func) |owner_func| { owner_func.state = .dependency_failure; @@ -25491,7 +25548,7 @@ fn analyzeSlice( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } } } @@ -26440,7 +26497,7 @@ fn resolvePeerTypes( break :msg msg; }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.failWithOwnedErrorMsg(msg); } const chosen_ty = sema.typeOf(chosen); @@ -26599,21 +26656,41 @@ fn resolveStructLayout( switch (struct_obj.status) { .none, .have_field_types => {}, .field_types_wip, .layout_wip => { - return sema.fail(block, src, "struct '{}' depends on itself", .{ty.fmt(sema.mod)}); + const msg = try Module.ErrorMsg.create( + sema.gpa, + struct_obj.srcLoc(sema.mod), + "struct '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + return sema.failWithOwnedErrorMsg(msg); }, .have_layout, .fully_resolved_wip, .fully_resolved => return, } struct_obj.status = .layout_wip; - for (struct_obj.fields.values()) |field| { - try sema.resolveTypeLayout(block, src, field.ty); + for (struct_obj.fields.values()) |field, i| { + sema.resolveTypeLayout(block, src, field.ty) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{}); + return err; + }, + else => return err, + }; } struct_obj.status = .have_layout; // In case of querying the ABI alignment of this struct, we will ask // for hasRuntimeBits() of each field, so we need "requires comptime" // to be known already before this function returns. - for (struct_obj.fields.values()) |field| { - _ = try sema.typeRequiresComptime(block, src, field.ty); + for (struct_obj.fields.values()) |field, i| { + _ = sema.typeRequiresComptime(block, src, field.ty) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{}); + return err; + }, + else => return err, + }; } } // otherwise it's a tuple; no need to resolve anything @@ -26630,13 +26707,26 @@ fn resolveUnionLayout( switch (union_obj.status) { .none, .have_field_types => {}, .field_types_wip, .layout_wip => { - return sema.fail(block, src, "union '{}' depends on itself", .{ty.fmt(sema.mod)}); + const msg = try Module.ErrorMsg.create( + sema.gpa, + union_obj.srcLoc(sema.mod), + "union '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + return sema.failWithOwnedErrorMsg(msg); }, .have_layout, .fully_resolved_wip, .fully_resolved => return, } union_obj.status = .layout_wip; - for (union_obj.fields.values()) |field| { - try sema.resolveTypeLayout(block, src, field.ty); + for (union_obj.fields.values()) |field, i| { + sema.resolveTypeLayout(block, src, field.ty) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{}); + return err; + }, + else => return err, + }; } union_obj.status = .have_layout; } @@ -26764,12 +26854,12 @@ pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) switch (ty.tag()) { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; - try sema.resolveTypeFieldsStruct(block, src, ty, struct_obj); + try sema.resolveTypeFieldsStruct(ty, struct_obj); return ty; }, .@"union", .union_safety_tagged, .union_tagged => { const union_obj = ty.cast(Type.Payload.Union).?.data; - try sema.resolveTypeFieldsUnion(block, src, ty, union_obj); + try sema.resolveTypeFieldsUnion(ty, union_obj); return ty; }, .type_info => return sema.resolveBuiltinTypeFields(block, src, "Type"), @@ -26790,15 +26880,19 @@ pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) fn resolveTypeFieldsStruct( sema: *Sema, - block: *Block, - src: LazySrcLoc, ty: Type, struct_obj: *Module.Struct, ) CompileError!void { switch (struct_obj.status) { .none => {}, .field_types_wip => { - return sema.fail(block, src, "struct '{}' depends on itself", .{ty.fmt(sema.mod)}); + const msg = try Module.ErrorMsg.create( + sema.gpa, + struct_obj.srcLoc(sema.mod), + "struct '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + return sema.failWithOwnedErrorMsg(msg); }, .have_field_types, .have_layout, @@ -26812,17 +26906,17 @@ fn resolveTypeFieldsStruct( try semaStructFields(sema.mod, struct_obj); } -fn resolveTypeFieldsUnion( - sema: *Sema, - block: *Block, - src: LazySrcLoc, - ty: Type, - union_obj: *Module.Union, -) CompileError!void { +fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) CompileError!void { switch (union_obj.status) { .none => {}, .field_types_wip => { - return sema.fail(block, src, "union '{}' depends on itself", .{ty.fmt(sema.mod)}); + const msg = try Module.ErrorMsg.create( + sema.gpa, + union_obj.srcLoc(sema.mod), + "union '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + return sema.failWithOwnedErrorMsg(msg); }, .have_field_types, .have_layout, @@ -27038,7 +27132,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void try sema.errNote(&block_scope, src, msg, "struct declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } gop.value_ptr.* = .{ .ty = Type.initTag(.noreturn), @@ -27097,7 +27191,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { const msg = msg: { @@ -27111,7 +27205,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void try sema.addDeclaredHereNote(msg, field.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); @@ -27124,7 +27218,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void try sema.addDeclaredHereNote(msg, field.ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } if (zir_field.align_body_len > 0) { @@ -27406,7 +27500,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.errNote(&block_scope, src, msg, "union declared here", .{}); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } if (tag_ty_field_names) |*names| { @@ -27420,7 +27514,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.addDeclaredHereNote(msg, union_obj.tag_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -27434,7 +27528,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) { const msg = msg: { @@ -27448,7 +27542,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); @@ -27461,7 +27555,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } gop.value_ptr.* = .{ @@ -27493,7 +27587,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { try sema.addDeclaredHereNote(msg, union_obj.tag_ty); break :msg msg; }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + return sema.failWithOwnedErrorMsg(msg); } } } @@ -27756,9 +27850,19 @@ pub fn typeHasOnePossibleValue( .@"struct" => { const resolved_ty = try sema.resolveTypeFields(block, src, ty); const s = resolved_ty.castTag(.@"struct").?.data; - for (s.fields.values()) |value| { - if (value.is_comptime) continue; - if ((try sema.typeHasOnePossibleValue(block, src, value.ty)) == null) { + for (s.fields.values()) |field, i| { + if (field.is_comptime) continue; + if (field.ty.eql(resolved_ty, sema.mod)) { + const msg = try Module.ErrorMsg.create( + sema.gpa, + s.srcLoc(sema.mod), + "struct '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + try sema.addFieldErrNote(block, resolved_ty, i, msg, "while checking this field", .{}); + return sema.failWithOwnedErrorMsg(msg); + } + if ((try sema.typeHasOnePossibleValue(block, src, field.ty)) == null) { return null; } } @@ -27824,6 +27928,16 @@ pub fn typeHasOnePossibleValue( const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse return null; const only_field = union_obj.fields.values()[0]; + if (only_field.ty.eql(resolved_ty, sema.mod)) { + const msg = try Module.ErrorMsg.create( + sema.gpa, + union_obj.srcLoc(sema.mod), + "union '{}' depends on itself", + .{ty.fmt(sema.mod)}, + ); + try sema.addFieldErrNote(block, resolved_ty, 0, msg, "while checking this field", .{}); + return sema.failWithOwnedErrorMsg(msg); + } const val_val = (try sema.typeHasOnePossibleValue(block, src, only_field.ty)) orelse return null; // TODO make this not allocate. The function in `Type.onePossibleValue` @@ -28463,7 +28577,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ if (struct_obj.status == .field_types_wip) return false; - try sema.resolveTypeFieldsStruct(block, src, ty, struct_obj); + try sema.resolveTypeFieldsStruct(ty, struct_obj); struct_obj.requires_comptime = .wip; for (struct_obj.fields.values()) |field| { @@ -28488,7 +28602,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ if (union_obj.status == .field_types_wip) return false; - try sema.resolveTypeFieldsUnion(block, src, ty, union_obj); + try sema.resolveTypeFieldsUnion(ty, union_obj); union_obj.requires_comptime = .wip; for (union_obj.fields.values()) |field| { diff --git a/test/cases/compile_errors/stage1/obj/accessing_runtime_parameter_from_outer_function.zig b/test/cases/compile_errors/accessing_runtime_parameter_from_outer_function.zig similarity index 52% rename from test/cases/compile_errors/stage1/obj/accessing_runtime_parameter_from_outer_function.zig rename to test/cases/compile_errors/accessing_runtime_parameter_from_outer_function.zig index 73a9e94d44..49ef3b4d4d 100644 --- a/test/cases/compile_errors/stage1/obj/accessing_runtime_parameter_from_outer_function.zig +++ b/test/cases/compile_errors/accessing_runtime_parameter_from_outer_function.zig @@ -1,4 +1,4 @@ -fn outer(y: u32) fn (u32) u32 { +fn outer(y: u32) *const fn (u32) u32 { const st = struct { fn get(z: u32) u32 { return z + y; @@ -13,9 +13,8 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:24: error: 'y' not accessible from inner function -// tmp.zig:3:28: note: crossed function definition here -// tmp.zig:1:10: note: declared here +// :4:24: error: 'y' not accessible from inner function +// :3:9: note: crossed function definition here diff --git a/test/cases/compile_errors/stage1/obj/cannot_break_out_of_defer_expression.zig b/test/cases/compile_errors/cannot_break_out_of_defer_expression.zig similarity index 53% rename from test/cases/compile_errors/stage1/obj/cannot_break_out_of_defer_expression.zig rename to test/cases/compile_errors/cannot_break_out_of_defer_expression.zig index 3c7ae4fa2f..454309eb89 100644 --- a/test/cases/compile_errors/stage1/obj/cannot_break_out_of_defer_expression.zig +++ b/test/cases/compile_errors/cannot_break_out_of_defer_expression.zig @@ -7,7 +7,8 @@ export fn foo() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:13: error: cannot break out of defer expression +// :4:13: error: cannot break out of defer expression +// :3:9: note: defer expression here diff --git a/test/cases/compile_errors/stage1/obj/cannot_continue_out_of_defer_expression.zig b/test/cases/compile_errors/cannot_continue_out_of_defer_expression.zig similarity index 53% rename from test/cases/compile_errors/stage1/obj/cannot_continue_out_of_defer_expression.zig rename to test/cases/compile_errors/cannot_continue_out_of_defer_expression.zig index 56b8ced05b..74d11528eb 100644 --- a/test/cases/compile_errors/stage1/obj/cannot_continue_out_of_defer_expression.zig +++ b/test/cases/compile_errors/cannot_continue_out_of_defer_expression.zig @@ -7,7 +7,8 @@ export fn foo() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:13: error: cannot continue out of defer expression +// :4:13: error: cannot continue out of defer expression +// :3:9: note: defer expression here diff --git a/test/cases/compile_errors/direct_struct_loop.zig b/test/cases/compile_errors/direct_struct_loop.zig new file mode 100644 index 0000000000..0abc1a4f73 --- /dev/null +++ b/test/cases/compile_errors/direct_struct_loop.zig @@ -0,0 +1,9 @@ +const A = struct { a : A, }; +export fn entry() usize { return @sizeOf(A); } + +// error +// backend=stage2 +// target=native +// +// :1:11: error: struct 'tmp.A' depends on itself +// :1:20: note: while checking this field diff --git a/test/cases/compile_errors/for_loop_body_expression_ignored.zig b/test/cases/compile_errors/for_loop_body_expression_ignored.zig new file mode 100644 index 0000000000..3ce73a9fab --- /dev/null +++ b/test/cases/compile_errors/for_loop_body_expression_ignored.zig @@ -0,0 +1,35 @@ +fn returns() usize { + return 2; +} +export fn f1() void { + for ("hello") |_| returns(); +} +export fn f2() void { + var x: anyerror!i32 = error.Bad; + for ("hello") |_| returns() else unreachable; + _ = x; +} +export fn f3() void { + for ("hello") |_| {} else true; +} +export fn f4() void { + const foo = for ("hello") |_| returns() else true; + _ = foo; +} + +// error +// backend=stage2 +// target=native +// +// :5:30: error: value of type 'usize' ignored +// :5:30: note: all non-void values must be used +// :5:30: note: this error can be suppressed by assigning the value to '_' +// :9:30: error: value of type 'usize' ignored +// :9:30: note: all non-void values must be used +// :9:30: note: this error can be suppressed by assigning the value to '_' +// :13:31: error: value of type 'bool' ignored +// :13:31: note: all non-void values must be used +// :13:31: note: this error can be suppressed by assigning the value to '_' +// :16:42: error: value of type 'usize' ignored +// :16:42: note: all non-void values must be used +// :16:42: note: this error can be suppressed by assigning the value to '_' diff --git a/test/cases/compile_errors/indirect_struct_loop.zig b/test/cases/compile_errors/indirect_struct_loop.zig new file mode 100644 index 0000000000..dca2b9c3f6 --- /dev/null +++ b/test/cases/compile_errors/indirect_struct_loop.zig @@ -0,0 +1,13 @@ +const A = struct { b : B, }; +const B = struct { c : C, }; +const C = struct { a : A, }; +export fn entry() usize { return @sizeOf(A); } + +// error +// backend=stage2 +// target=native +// +// :1:11: error: struct 'tmp.A' depends on itself +// :3:20: note: while checking this field +// :2:20: note: while checking this field +// :1:20: note: while checking this field diff --git a/test/cases/compile_errors/stage1/obj/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig similarity index 58% rename from test/cases/compile_errors/stage1/obj/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig rename to test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig index dd6909b1c2..74cafabe7c 100644 --- a/test/cases/compile_errors/stage1/obj/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig +++ b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig @@ -9,7 +9,8 @@ export fn entry() usize { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:1:13: error: struct 'Foo' depends on itself +// :1:13: error: struct 'tmp.Foo' depends on itself +// :2:5: note: while checking this field diff --git a/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig new file mode 100644 index 0000000000..6030ca4d3e --- /dev/null +++ b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig @@ -0,0 +1,16 @@ +const Foo = union { + x: Foo, +}; + +var foo: Foo = undefined; + +export fn entry() usize { + return @sizeOf(@TypeOf(foo.x)); +} + +// error +// backend=stage2 +// target=native +// +// :1:13: error: union 'tmp.Foo' depends on itself +// :2:5: note: while checking this field diff --git a/test/cases/compile_errors/stage1/obj/packed_union_given_enum_tag_type.zig b/test/cases/compile_errors/packed_union_given_enum_tag_type.zig similarity index 72% rename from test/cases/compile_errors/stage1/obj/packed_union_given_enum_tag_type.zig rename to test/cases/compile_errors/packed_union_given_enum_tag_type.zig index fceb7af65c..03aaef0d8c 100644 --- a/test/cases/compile_errors/stage1/obj/packed_union_given_enum_tag_type.zig +++ b/test/cases/compile_errors/packed_union_given_enum_tag_type.zig @@ -14,7 +14,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:6:30: error: packed union does not support enum tag type +// :6:30: error: packed union does not support enum tag type diff --git a/test/cases/compile_errors/stage1/obj/packed_union_with_automatic_layout_field.zig b/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig similarity index 51% rename from test/cases/compile_errors/stage1/obj/packed_union_with_automatic_layout_field.zig rename to test/cases/compile_errors/packed_union_with_automatic_layout_field.zig index 99ad6ca306..97771e9b78 100644 --- a/test/cases/compile_errors/stage1/obj/packed_union_with_automatic_layout_field.zig +++ b/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig @@ -12,7 +12,9 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:6:5: error: non-packed, non-extern struct 'Foo' not allowed in packed union; no guaranteed in-memory representation +// :6:5: error: packed unions cannot contain fields of type 'tmp.Foo' +// :6:5: note: only packed structs layout are allowed in packed types +// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/stage1/obj/specify_non-integer_enum_tag_type.zig b/test/cases/compile_errors/specify_non-integer_enum_tag_type.zig similarity index 67% rename from test/cases/compile_errors/stage1/obj/specify_non-integer_enum_tag_type.zig rename to test/cases/compile_errors/specify_non-integer_enum_tag_type.zig index 333647e1e3..f2ff3e2cd1 100644 --- a/test/cases/compile_errors/stage1/obj/specify_non-integer_enum_tag_type.zig +++ b/test/cases/compile_errors/specify_non-integer_enum_tag_type.zig @@ -10,7 +10,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:1:21: error: expected integer, found 'f32' +// :1:21: error: expected integer tag type, found 'f32' diff --git a/test/cases/compile_errors/stage1/obj/direct_struct_loop.zig b/test/cases/compile_errors/stage1/obj/direct_struct_loop.zig deleted file mode 100644 index 3062e617d6..0000000000 --- a/test/cases/compile_errors/stage1/obj/direct_struct_loop.zig +++ /dev/null @@ -1,8 +0,0 @@ -const A = struct { a : A, }; -export fn entry() usize { return @sizeOf(A); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:11: error: struct 'A' depends on itself diff --git a/test/cases/compile_errors/stage1/obj/for_loop_body_expression_ignored.zig b/test/cases/compile_errors/stage1/obj/for_loop_body_expression_ignored.zig deleted file mode 100644 index 6281d4b276..0000000000 --- a/test/cases/compile_errors/stage1/obj/for_loop_body_expression_ignored.zig +++ /dev/null @@ -1,18 +0,0 @@ -fn returns() usize { - return 2; -} -export fn f1() void { - for ("hello") |_| returns(); -} -export fn f2() void { - var x: anyerror!i32 = error.Bad; - for ("hello") |_| returns() else unreachable; - _ = x; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:30: error: expression value is ignored -// tmp.zig:9:30: error: expression value is ignored diff --git a/test/cases/compile_errors/stage1/obj/indirect_struct_loop.zig b/test/cases/compile_errors/stage1/obj/indirect_struct_loop.zig deleted file mode 100644 index 12214923d0..0000000000 --- a/test/cases/compile_errors/stage1/obj/indirect_struct_loop.zig +++ /dev/null @@ -1,10 +0,0 @@ -const A = struct { b : B, }; -const B = struct { c : C, }; -const C = struct { a : A, }; -export fn entry() usize { return @sizeOf(A); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:11: error: struct 'A' depends on itself diff --git a/test/cases/compile_errors/stage1/obj/while_loop_body_expression_ignored.zig b/test/cases/compile_errors/stage1/obj/while_loop_body_expression_ignored.zig deleted file mode 100644 index 9542cbc62f..0000000000 --- a/test/cases/compile_errors/stage1/obj/while_loop_body_expression_ignored.zig +++ /dev/null @@ -1,22 +0,0 @@ -fn returns() usize { - return 2; -} -export fn f1() void { - while (true) returns(); -} -export fn f2() void { - var x: ?i32 = null; - while (x) |_| returns(); -} -export fn f3() void { - var x: anyerror!i32 = error.Bad; - while (x) |_| returns() else |_| unreachable; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:25: error: expression value is ignored -// tmp.zig:9:26: error: expression value is ignored -// tmp.zig:13:26: error: expression value is ignored diff --git a/test/cases/compile_errors/stage1/obj/struct_depends_on_itself_via_optional_field.zig b/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig similarity index 61% rename from test/cases/compile_errors/stage1/obj/struct_depends_on_itself_via_optional_field.zig rename to test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig index 46086172f7..cad779e3d7 100644 --- a/test/cases/compile_errors/stage1/obj/struct_depends_on_itself_via_optional_field.zig +++ b/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig @@ -11,9 +11,9 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:1:17: error: struct 'LhsExpr' depends on itself -// tmp.zig:5:5: note: while checking this field -// tmp.zig:2:5: note: while checking this field +// :1:17: error: struct 'tmp.LhsExpr' depends on itself +// :5:5: note: while checking this field +// :2:5: note: while checking this field diff --git a/test/cases/compile_errors/stage1/obj/top_level_decl_dependency_loop.zig b/test/cases/compile_errors/top_level_decl_dependency_loop.zig similarity index 60% rename from test/cases/compile_errors/stage1/obj/top_level_decl_dependency_loop.zig rename to test/cases/compile_errors/top_level_decl_dependency_loop.zig index ac70285c9c..3b0e60ac02 100644 --- a/test/cases/compile_errors/stage1/obj/top_level_decl_dependency_loop.zig +++ b/test/cases/compile_errors/top_level_decl_dependency_loop.zig @@ -6,7 +6,8 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:19: error: dependency loop detected +// :1:1: error: dependency loop detected +// :2:19: note: referenced here diff --git a/test/cases/compile_errors/stage1/obj/unused_variable_error_on_errdefer.zig b/test/cases/compile_errors/unused_variable_error_on_errdefer.zig similarity index 71% rename from test/cases/compile_errors/stage1/obj/unused_variable_error_on_errdefer.zig rename to test/cases/compile_errors/unused_variable_error_on_errdefer.zig index b85d5729dc..4c37af04eb 100644 --- a/test/cases/compile_errors/stage1/obj/unused_variable_error_on_errdefer.zig +++ b/test/cases/compile_errors/unused_variable_error_on_errdefer.zig @@ -7,7 +7,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: unused variable: 'a' +// :2:15: error: unused capture diff --git a/test/cases/compile_errors/stage1/obj/vector_index_out_of_bounds.zig b/test/cases/compile_errors/vector_index_out_of_bounds.zig similarity index 64% rename from test/cases/compile_errors/stage1/obj/vector_index_out_of_bounds.zig rename to test/cases/compile_errors/vector_index_out_of_bounds.zig index fdffd8b455..ed1a25a321 100644 --- a/test/cases/compile_errors/stage1/obj/vector_index_out_of_bounds.zig +++ b/test/cases/compile_errors/vector_index_out_of_bounds.zig @@ -4,7 +4,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:62: error: index 3 outside vector of size 3 +// :2:49: error: expected 3 vector elements; found 4 diff --git a/test/cases/compile_errors/stage1/obj/while_expected_error_union_got_bool.zig b/test/cases/compile_errors/while_expected_error_union_got_bool.zig similarity index 62% rename from test/cases/compile_errors/stage1/obj/while_expected_error_union_got_bool.zig rename to test/cases/compile_errors/while_expected_error_union_got_bool.zig index b8a72e9793..f7960437ec 100644 --- a/test/cases/compile_errors/stage1/obj/while_expected_error_union_got_bool.zig +++ b/test/cases/compile_errors/while_expected_error_union_got_bool.zig @@ -4,7 +4,7 @@ export fn foo() void { fn bar() bool { return true; } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: expected error union type, found 'bool' +// :2:15: error: expected error union type, found 'bool' diff --git a/test/cases/compile_errors/stage1/obj/while_expected_error_union_got_optional.zig b/test/cases/compile_errors/while_expected_error_union_got_optional.zig similarity index 62% rename from test/cases/compile_errors/stage1/obj/while_expected_error_union_got_optional.zig rename to test/cases/compile_errors/while_expected_error_union_got_optional.zig index c933dc9509..5cabd76fce 100644 --- a/test/cases/compile_errors/stage1/obj/while_expected_error_union_got_optional.zig +++ b/test/cases/compile_errors/while_expected_error_union_got_optional.zig @@ -4,7 +4,7 @@ export fn foo() void { fn bar() ?i32 { return 1; } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: expected error union type, found '?i32' +// :2:15: error: expected error union type, found '?i32' diff --git a/test/cases/compile_errors/stage1/obj/while_expected_optional_got_bool.zig b/test/cases/compile_errors/while_expected_optional_got_bool.zig similarity index 59% rename from test/cases/compile_errors/stage1/obj/while_expected_optional_got_bool.zig rename to test/cases/compile_errors/while_expected_optional_got_bool.zig index 0458d1ba01..22b8c1e58c 100644 --- a/test/cases/compile_errors/stage1/obj/while_expected_optional_got_bool.zig +++ b/test/cases/compile_errors/while_expected_optional_got_bool.zig @@ -4,7 +4,7 @@ export fn foo() void { fn bar() bool { return true; } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: expected optional type, found 'bool' +// :2:15: error: expected optional type, found 'bool' diff --git a/test/cases/compile_errors/stage1/obj/while_expected_optional_got_error_union.zig b/test/cases/compile_errors/while_expected_optional_got_error_union.zig similarity index 58% rename from test/cases/compile_errors/stage1/obj/while_expected_optional_got_error_union.zig rename to test/cases/compile_errors/while_expected_optional_got_error_union.zig index 7cdbd2cccf..38a8a0dd20 100644 --- a/test/cases/compile_errors/stage1/obj/while_expected_optional_got_error_union.zig +++ b/test/cases/compile_errors/while_expected_optional_got_error_union.zig @@ -4,7 +4,7 @@ export fn foo() void { fn bar() anyerror!i32 { return 1; } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: expected optional type, found 'anyerror!i32' +// :2:15: error: expected optional type, found 'anyerror!i32' diff --git a/test/cases/compile_errors/while_loop_body_expression_ignored.zig b/test/cases/compile_errors/while_loop_body_expression_ignored.zig new file mode 100644 index 0000000000..e33f48e6a5 --- /dev/null +++ b/test/cases/compile_errors/while_loop_body_expression_ignored.zig @@ -0,0 +1,43 @@ +fn returns() usize { + return 2; +} +export fn f1() void { + while (true) returns(); +} +export fn f2() void { + var x: ?i32 = null; + while (x) |_| returns(); +} +export fn f3() void { + var x: anyerror!i32 = error.Bad; + while (x) |_| returns() else |_| unreachable; +} +export fn f4() void { + var a = true; + while (a) {} else true; +} +export fn f5() void { + var a = true; + const foo = while (a) returns() else true; + _ = foo; +} + +// error +// backend=stage2 +// target=native +// +// :5:25: error: value of type 'usize' ignored +// :5:25: note: all non-void values must be used +// :5:25: note: this error can be suppressed by assigning the value to '_' +// :9:26: error: value of type 'usize' ignored +// :9:26: note: all non-void values must be used +// :9:26: note: this error can be suppressed by assigning the value to '_' +// :13:26: error: value of type 'usize' ignored +// :13:26: note: all non-void values must be used +// :13:26: note: this error can be suppressed by assigning the value to '_' +// :17:23: error: value of type 'bool' ignored +// :17:23: note: all non-void values must be used +// :17:23: note: this error can be suppressed by assigning the value to '_' +// :21:34: error: value of type 'usize' ignored +// :21:34: note: all non-void values must be used +// :21:34: note: this error can be suppressed by assigning the value to '_'