mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
frontend: make fn calls byval; fix false positive isNonErr
This commit does two things which seem unrelated at first, but, together, solve a miscompilation, and potentially slightly speed up compiler perf, at the expense of making #2765 trickier to implement in the future. Sema: avoid returning a false positive for whether an inferred error set is comptime-known to be empty. AstGen: mark function calls as not being interested in a result location. This prevents the test case "ret_ptr doesn't cause own inferred error set to be resolved" from being regressed. If we want to accept and implement #2765 in the future, it will require solving this problem a different way, but the principle of YAGNI tells us to go ahead with this change. Old ZIR looks like this: %97 = ret_ptr() %101 = store_node(%97, %100) %102 = load(%97) %103 = ret_is_non_err(%102) New ZIR looks like this: %97 = ret_type() %101 = as_node(%97, %100) %102 = ret_is_non_err(%101) closes #15669
This commit is contained in:
parent
9a3adeea6e
commit
e66190025f
3 changed files with 40 additions and 28 deletions
|
|
@ -9536,16 +9536,19 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_
|
||||||
.@"for", // This variant always has an else expression.
|
.@"for", // This variant always has an else expression.
|
||||||
.@"switch",
|
.@"switch",
|
||||||
.switch_comma,
|
.switch_comma,
|
||||||
.call_one,
|
|
||||||
.call_one_comma,
|
|
||||||
.async_call_one,
|
.async_call_one,
|
||||||
.async_call_one_comma,
|
.async_call_one_comma,
|
||||||
.call,
|
|
||||||
.call_comma,
|
|
||||||
.async_call,
|
.async_call,
|
||||||
.async_call_comma,
|
.async_call_comma,
|
||||||
=> return true,
|
=> return true,
|
||||||
|
|
||||||
|
// https://github.com/ziglang/zig/issues/2765 would change this.
|
||||||
|
.call_one,
|
||||||
|
.call_one_comma,
|
||||||
|
.call,
|
||||||
|
.call_comma,
|
||||||
|
=> return false,
|
||||||
|
|
||||||
.block_two,
|
.block_two,
|
||||||
.block_two_semicolon,
|
.block_two_semicolon,
|
||||||
.block,
|
.block,
|
||||||
|
|
|
||||||
32
src/Sema.zig
32
src/Sema.zig
|
|
@ -30732,18 +30732,10 @@ fn analyzeIsNonErrComptimeOnly(
|
||||||
else => return .none,
|
else => return .none,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for (ies.inferred_error_sets.keys()) |other_ies_index| {
|
// We do not have a comptime answer because this inferred error
|
||||||
if (set_ty == other_ies_index) continue;
|
// set is not resolved, and an instruction later in this function
|
||||||
const other_resolved =
|
// body may or may not cause an error to be added to this set.
|
||||||
try sema.resolveInferredErrorSet(block, src, other_ies_index);
|
return .none;
|
||||||
if (other_resolved == .anyerror_type) {
|
|
||||||
ies.resolved = .anyerror_type;
|
|
||||||
return .none;
|
|
||||||
}
|
|
||||||
if (ip.indexToKey(other_resolved).error_set_type.names.len != 0)
|
|
||||||
return .none;
|
|
||||||
}
|
|
||||||
return .bool_true;
|
|
||||||
},
|
},
|
||||||
else => switch (ip.indexToKey(set_ty)) {
|
else => switch (ip.indexToKey(set_ty)) {
|
||||||
.error_set_type => |error_set_type| {
|
.error_set_type => |error_set_type| {
|
||||||
|
|
@ -30771,18 +30763,10 @@ fn analyzeIsNonErrComptimeOnly(
|
||||||
else => return .none,
|
else => return .none,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for (ies.inferred_error_sets.keys()) |other_ies_index| {
|
// We do not have a comptime answer because this inferred error
|
||||||
if (set_ty == other_ies_index) continue;
|
// set is not resolved, and an instruction later in this function
|
||||||
const other_resolved =
|
// body may or may not cause an error to be added to this set.
|
||||||
try sema.resolveInferredErrorSet(block, src, other_ies_index);
|
return .none;
|
||||||
if (other_resolved == .anyerror_type) {
|
|
||||||
ies.resolved = .anyerror_type;
|
|
||||||
return .none;
|
|
||||||
}
|
|
||||||
if (ip.indexToKey(other_resolved).error_set_type.names.len != 0)
|
|
||||||
return .none;
|
|
||||||
}
|
|
||||||
return .bool_true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
|
const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
|
||||||
|
|
|
||||||
|
|
@ -938,3 +938,28 @@ test "returning an error union containing a type with no runtime bits" {
|
||||||
var zero_byte: ZeroByteType = undefined;
|
var zero_byte: ZeroByteType = undefined;
|
||||||
(&zero_byte).* = try ZeroByteType.init();
|
(&zero_byte).* = try ZeroByteType.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "try used in recursive function with inferred error set" {
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
const Value = union(enum) {
|
||||||
|
values: []const @This(),
|
||||||
|
b,
|
||||||
|
|
||||||
|
fn x(value: @This()) !void {
|
||||||
|
switch (value.values[0]) {
|
||||||
|
.values => return try x(value.values[0]),
|
||||||
|
.b => return error.a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const a = Value{
|
||||||
|
.values = &[1]Value{
|
||||||
|
.{
|
||||||
|
.values = &[1]Value{.{ .b = {} }},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
try expectError(error.a, Value.x(a));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue