mirror of
https://github.com/ziglang/zig.git
synced 2026-02-17 14:59:14 +00:00
compiler: ensure local consts in comptime scope are comptime-known
This fixes a bug which exposed a compiler implementation detail (ZIR alloc elision). Previously, `const` declarations with a runtime-known value in a comptime scope were permitted only if AstGen was able to elide the alloc in ZIR, since the error was reported by storing to the comptime alloc. This just adds a new instruction to also emit this error when the alloc is elided.
This commit is contained in:
parent
6026a5f217
commit
9a70eeeac5
@ -2963,6 +2963,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.validate_array_init_result_ty,
|
||||
.validate_ptr_array_init,
|
||||
.validate_ref_ty,
|
||||
.validate_const,
|
||||
.try_operand_ty,
|
||||
.try_ref_operand_ty,
|
||||
=> break :b true,
|
||||
@ -3280,6 +3281,7 @@ fn varDecl(
|
||||
const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
|
||||
gz.anon_name_strategy = prev_anon_name_strategy;
|
||||
|
||||
_ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node);
|
||||
try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
|
||||
|
||||
// The const init expression may have modified the error return trace, so signal
|
||||
|
||||
@ -711,6 +711,12 @@ pub const Inst = struct {
|
||||
/// operator. Emit a compile error if not.
|
||||
/// Uses the `un_tok` union field. Token is the `&` operator. Operand is the type.
|
||||
validate_ref_ty,
|
||||
/// Given a value, check whether it is a valid local constant in this scope.
|
||||
/// In a runtime scope, this is always a nop.
|
||||
/// In a comptime scope, raises a compile error if the value is runtime-known.
|
||||
/// Result is always void.
|
||||
/// Uses the `un_node` union field. Node is the initializer. Operand is the initializer value.
|
||||
validate_const,
|
||||
/// Given a type `T`, construct the type `E!T`, where `E` is this function's error set, to be used
|
||||
/// as the result type of a `try` operand. Generic poison is propagated.
|
||||
/// Uses the `un_node` union field. Node is the `try` expression. Operand is the type `T`.
|
||||
@ -1293,6 +1299,7 @@ pub const Inst = struct {
|
||||
.array_init_elem_type,
|
||||
.array_init_elem_ptr,
|
||||
.validate_ref_ty,
|
||||
.validate_const,
|
||||
.try_operand_ty,
|
||||
.try_ref_operand_ty,
|
||||
.restore_err_ret_index_unconditional,
|
||||
@ -1353,6 +1360,7 @@ pub const Inst = struct {
|
||||
.validate_array_init_result_ty,
|
||||
.validate_ptr_array_init,
|
||||
.validate_ref_ty,
|
||||
.validate_const,
|
||||
.try_operand_ty,
|
||||
.try_ref_operand_ty,
|
||||
=> true,
|
||||
@ -1736,6 +1744,7 @@ pub const Inst = struct {
|
||||
.opt_eu_base_ptr_init = .un_node,
|
||||
.coerce_ptr_elem_ty = .pl_node,
|
||||
.validate_ref_ty = .un_tok,
|
||||
.validate_const = .un_node,
|
||||
.try_operand_ty = .un_node,
|
||||
.try_ref_operand_ty = .un_node,
|
||||
|
||||
@ -4143,6 +4152,7 @@ fn findTrackableInner(
|
||||
.opt_eu_base_ptr_init,
|
||||
.coerce_ptr_elem_ty,
|
||||
.validate_ref_ty,
|
||||
.validate_const,
|
||||
.try_operand_ty,
|
||||
.try_ref_operand_ty,
|
||||
.struct_init_empty,
|
||||
|
||||
16
src/Sema.zig
16
src/Sema.zig
@ -1502,6 +1502,11 @@ fn analyzeBodyInner(
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.validate_const => {
|
||||
try sema.zirValidateConst(block, inst);
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.@"export" => {
|
||||
try sema.zirExport(block, inst);
|
||||
i += 1;
|
||||
@ -4614,6 +4619,17 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
|
||||
}
|
||||
}
|
||||
|
||||
fn zirValidateConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
if (!block.isComptime()) return;
|
||||
|
||||
const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(un_node.src_node);
|
||||
const init_ref = try sema.resolveInst(un_node.operand);
|
||||
if (!try sema.isComptimeKnown(init_ref)) {
|
||||
return sema.failWithNeededComptime(block, src, null);
|
||||
}
|
||||
}
|
||||
|
||||
fn zirValidateArrayInitRefTy(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
|
||||
@ -273,6 +273,7 @@ const Writer = struct {
|
||||
.@"await",
|
||||
.make_ptr_const,
|
||||
.validate_deref,
|
||||
.validate_const,
|
||||
.check_comptime_control_flow,
|
||||
.opt_eu_base_ptr_init,
|
||||
.restore_err_ret_index_unconditional,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user