Commit 9a70eeeac5
Changed files (4)
lib
std
lib/std/zig/AstGen.zig
@@ -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
lib/std/zig/Zir.zig
@@ -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,
src/print_zir.zig
@@ -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,
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,