mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 01:53:16 +00:00
Merge pull request #12318 from Vexu/stage2-compile-errors
Stage2: misc compile error improvements
This commit is contained in:
commit
e483336ba4
134
src/AstGen.zig
134
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,
|
||||
};
|
||||
}
|
||||
|
||||
388
src/Sema.zig
388
src/Sema.zig
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
9
test/cases/compile_errors/direct_struct_loop.zig
Normal file
9
test/cases/compile_errors/direct_struct_loop.zig
Normal file
@ -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
|
||||
@ -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 '_'
|
||||
13
test/cases/compile_errors/indirect_struct_loop.zig
Normal file
13
test/cases/compile_errors/indirect_struct_loop.zig
Normal file
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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'
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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'
|
||||
@ -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'
|
||||
@ -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'
|
||||
@ -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'
|
||||
@ -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 '_'
|
||||
Loading…
x
Reference in New Issue
Block a user