mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Merge pull request #22352 from mlugg/zir-comptime-reason
Zir: attach reason to `block_comptime` and improve corresponding error reporting
This commit is contained in:
commit
0df1f3df2f
159
lib/std/zig.zig
159
lib/std/zig.zig
@ -718,6 +718,165 @@ pub const EnvVar = enum {
|
||||
}
|
||||
};
|
||||
|
||||
pub const SimpleComptimeReason = enum(u32) {
|
||||
// Evaluating at comptime because a builtin operand must be comptime-known.
|
||||
// These messages all mention a specific builtin.
|
||||
operand_Type,
|
||||
operand_setEvalBranchQuota,
|
||||
operand_setFloatMode,
|
||||
operand_branchHint,
|
||||
operand_setRuntimeSafety,
|
||||
operand_embedFile,
|
||||
operand_cImport,
|
||||
operand_cDefine_macro_name,
|
||||
operand_cDefine_macro_value,
|
||||
operand_cInclude_file_name,
|
||||
operand_cUndef_macro_name,
|
||||
operand_shuffle_mask,
|
||||
operand_atomicRmw_operation,
|
||||
operand_reduce_operation,
|
||||
|
||||
// Evaluating at comptime because an operand must be comptime-known.
|
||||
// These messages do not mention a specific builtin (and may not be about a builtin at all).
|
||||
export_target,
|
||||
export_options,
|
||||
extern_options,
|
||||
prefetch_options,
|
||||
call_modifier,
|
||||
compile_error_string,
|
||||
inline_assembly_code,
|
||||
atomic_order,
|
||||
array_mul_factor,
|
||||
slice_cat_operand,
|
||||
comptime_call_target,
|
||||
wasm_memory_index,
|
||||
work_group_dim_index,
|
||||
|
||||
// Evaluating at comptime because types must be comptime-known.
|
||||
// Reasons other than `.type` are just more specific messages.
|
||||
type,
|
||||
array_sentinel,
|
||||
pointer_sentinel,
|
||||
slice_sentinel,
|
||||
array_length,
|
||||
vector_length,
|
||||
error_set_contents,
|
||||
struct_fields,
|
||||
enum_fields,
|
||||
union_fields,
|
||||
function_ret_ty,
|
||||
function_parameters,
|
||||
|
||||
// Evaluating at comptime because decl/field name must be comptime-known.
|
||||
decl_name,
|
||||
field_name,
|
||||
struct_field_name,
|
||||
enum_field_name,
|
||||
union_field_name,
|
||||
tuple_field_name,
|
||||
tuple_field_index,
|
||||
|
||||
// Evaluating at comptime because it is an attribute of a global declaration.
|
||||
container_var_init,
|
||||
@"callconv",
|
||||
@"align",
|
||||
@"addrspace",
|
||||
@"linksection",
|
||||
|
||||
// Miscellaneous reasons.
|
||||
comptime_keyword,
|
||||
comptime_call_modifier,
|
||||
switch_item,
|
||||
tuple_field_default_value,
|
||||
struct_field_default_value,
|
||||
enum_field_tag_value,
|
||||
slice_single_item_ptr_bounds,
|
||||
comptime_param_arg,
|
||||
stored_to_comptime_field,
|
||||
stored_to_comptime_var,
|
||||
casted_to_comptime_enum,
|
||||
casted_to_comptime_int,
|
||||
casted_to_comptime_float,
|
||||
panic_handler,
|
||||
|
||||
pub fn message(r: SimpleComptimeReason) []const u8 {
|
||||
return switch (r) {
|
||||
// zig fmt: off
|
||||
.operand_Type => "operand to '@Type' must be comptime-known",
|
||||
.operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
|
||||
.operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
|
||||
.operand_branchHint => "operand to '@branchHint' must be comptime-known",
|
||||
.operand_setRuntimeSafety => "operand to '@setRuntimeSafety' must be comptime-known",
|
||||
.operand_embedFile => "operand to '@embedFile' must be comptime-known",
|
||||
.operand_cImport => "operand to '@cImport' is evaluated at comptime",
|
||||
.operand_cDefine_macro_name => "'@cDefine' macro name must be comptime-known",
|
||||
.operand_cDefine_macro_value => "'@cDefine' macro value must be comptime-known",
|
||||
.operand_cInclude_file_name => "'@cInclude' file name must be comptime-known",
|
||||
.operand_cUndef_macro_name => "'@cUndef' macro name must be comptime-known",
|
||||
.operand_shuffle_mask => "'@shuffle' mask must be comptime-known",
|
||||
.operand_atomicRmw_operation => "'@atomicRmw' operation must be comptime-known",
|
||||
.operand_reduce_operation => "'@reduce' operation must be comptime-known",
|
||||
|
||||
.export_target => "export target must be comptime-known",
|
||||
.export_options => "export options must be comptime-known",
|
||||
.extern_options => "extern options must be comptime-known",
|
||||
.prefetch_options => "prefetch options must be comptime-known",
|
||||
.call_modifier => "call modifier must be comptime-known",
|
||||
.compile_error_string => "compile error string must be comptime-known",
|
||||
.inline_assembly_code => "inline assembly code must be comptime-known",
|
||||
.atomic_order => "atomic order must be comptime-known",
|
||||
.array_mul_factor => "array multiplication factor must be comptime-known",
|
||||
.slice_cat_operand => "slice being concatenated must be comptime-known",
|
||||
.comptime_call_target => "function being called at comptime must be comptime-known",
|
||||
.wasm_memory_index => "wasm memory index must be comptime-known",
|
||||
.work_group_dim_index => "work group dimension index must be comptime-known",
|
||||
|
||||
.type => "types must be comptime-known",
|
||||
.array_sentinel => "array sentinel value must be comptime-known",
|
||||
.pointer_sentinel => "pointer sentinel value must be comptime-known",
|
||||
.slice_sentinel => "slice sentinel value must be comptime-known",
|
||||
.array_length => "array length must be comptime-known",
|
||||
.vector_length => "vector length must be comptime-known",
|
||||
.error_set_contents => "error set contents must be comptime-known",
|
||||
.struct_fields => "struct fields must be comptime-known",
|
||||
.enum_fields => "enum fields must be comptime-known",
|
||||
.union_fields => "union fields must be comptime-known",
|
||||
.function_ret_ty => "function return type must be comptime-known",
|
||||
.function_parameters => "function parameters must be comptime-known",
|
||||
|
||||
.decl_name => "declaration name must be comptime-known",
|
||||
.field_name => "field name must be comptime-known",
|
||||
.struct_field_name => "struct field name must be comptime-known",
|
||||
.enum_field_name => "enum field name must be comptime-known",
|
||||
.union_field_name => "union field name must be comptime-known",
|
||||
.tuple_field_name => "tuple field name must be comptime-known",
|
||||
.tuple_field_index => "tuple field index must be comptime-known",
|
||||
|
||||
.container_var_init => "initializer of container-level variable must be comptime-known",
|
||||
.@"callconv" => "calling convention must be comptime-known",
|
||||
.@"align" => "alignment must be comptime-known",
|
||||
.@"addrspace" => "address space must be comptime-known",
|
||||
.@"linksection" => "linksection must be comptime-known",
|
||||
|
||||
.comptime_keyword => "'comptime' keyword forces comptime evaluation",
|
||||
.comptime_call_modifier => "'.compile_time' call modifier forces comptime evaluation",
|
||||
.switch_item => "switch prong values must be comptime-known",
|
||||
.tuple_field_default_value => "tuple field default value must be comptime-known",
|
||||
.struct_field_default_value => "struct field default value must be comptime-known",
|
||||
.enum_field_tag_value => "enum field tag value must be comptime-known",
|
||||
.slice_single_item_ptr_bounds => "slice of single-item pointer must have comptime-known bounds",
|
||||
.comptime_param_arg => "argument to comptime parameter must be comptime-known",
|
||||
.stored_to_comptime_field => "value stored to a comptime field must be comptime-known",
|
||||
.stored_to_comptime_var => "value stored to a comptime variable must be comptime-known",
|
||||
.casted_to_comptime_enum => "value casted to enum with 'comptime_int' tag type must be comptime-known",
|
||||
.casted_to_comptime_int => "value casted to 'comptime_int' must be comptime-known",
|
||||
.casted_to_comptime_float => "value casted to 'comptime_float' must be comptime-known",
|
||||
.panic_handler => "panic handler must be comptime-known",
|
||||
// zig fmt: on
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
test {
|
||||
_ = Ast;
|
||||
_ = AstRlAnnotate;
|
||||
|
||||
@ -97,6 +97,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
|
||||
Zir.Inst.Ref,
|
||||
Zir.Inst.Index,
|
||||
Zir.Inst.Declaration.Name,
|
||||
std.zig.SimpleComptimeReason,
|
||||
Zir.NullTerminatedString,
|
||||
=> @intFromEnum(@field(extra, field.name)),
|
||||
|
||||
@ -379,7 +380,7 @@ const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
|
||||
const coerced_bool_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .bool_type } };
|
||||
|
||||
fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
|
||||
return comptimeExpr(gz, scope, coerced_type_ri, type_node);
|
||||
return comptimeExpr(gz, scope, coerced_type_ri, type_node, .type);
|
||||
}
|
||||
|
||||
fn reachableTypeExpr(
|
||||
@ -388,7 +389,7 @@ fn reachableTypeExpr(
|
||||
type_node: Ast.Node.Index,
|
||||
reachable_node: Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
return reachableExprComptime(gz, scope, coerced_type_ri, type_node, reachable_node, true);
|
||||
return reachableExprComptime(gz, scope, coerced_type_ri, type_node, reachable_node, .type);
|
||||
}
|
||||
|
||||
/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
|
||||
@ -399,7 +400,7 @@ fn reachableExpr(
|
||||
node: Ast.Node.Index,
|
||||
reachable_node: Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
return reachableExprComptime(gz, scope, ri, node, reachable_node, false);
|
||||
return reachableExprComptime(gz, scope, ri, node, reachable_node, null);
|
||||
}
|
||||
|
||||
fn reachableExprComptime(
|
||||
@ -408,10 +409,11 @@ fn reachableExprComptime(
|
||||
ri: ResultInfo,
|
||||
node: Ast.Node.Index,
|
||||
reachable_node: Ast.Node.Index,
|
||||
force_comptime: bool,
|
||||
/// If `null`, the expression is not evaluated in a comptime context.
|
||||
comptime_reason: ?std.zig.SimpleComptimeReason,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const result_inst = if (force_comptime)
|
||||
try comptimeExpr(gz, scope, ri, node)
|
||||
const result_inst = if (comptime_reason) |r|
|
||||
try comptimeExpr(gz, scope, ri, node, r)
|
||||
else
|
||||
try expr(gz, scope, ri, node);
|
||||
|
||||
@ -782,13 +784,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
||||
const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{
|
||||
.res_ty = if (try ri.rl.resultType(gz, node)) |t| t else .none,
|
||||
.lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
|
||||
.rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs),
|
||||
.rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs, .array_mul_factor),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
|
||||
.error_union => return simpleBinOp(gz, scope, ri, node, .error_union_type),
|
||||
.merge_error_sets => return simpleBinOp(gz, scope, ri, node, .merge_error_sets),
|
||||
.error_union, .merge_error_sets => |tag| {
|
||||
const inst_tag: Zir.Inst.Tag = switch (tag) {
|
||||
.error_union => .error_union_type,
|
||||
.merge_error_sets => .merge_error_sets,
|
||||
else => unreachable,
|
||||
};
|
||||
const lhs = try reachableTypeExpr(gz, scope, node_datas[node].lhs, node);
|
||||
const rhs = try reachableTypeExpr(gz, scope, node_datas[node].rhs, node);
|
||||
const result = try gz.addPlNode(inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
|
||||
.bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),
|
||||
.bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or),
|
||||
@ -799,7 +810,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
||||
.negation => return negation(gz, scope, ri, node),
|
||||
.negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .negate_wrap),
|
||||
|
||||
.identifier => return identifier(gz, scope, ri, node),
|
||||
.identifier => return identifier(gz, scope, ri, node, null),
|
||||
|
||||
.asm_simple,
|
||||
.@"asm",
|
||||
@ -1364,6 +1375,7 @@ fn fnProtoExprInner(
|
||||
assert(param_type_node != 0);
|
||||
var param_gz = block_scope.makeSubBlock(scope);
|
||||
defer param_gz.unstack();
|
||||
param_gz.is_comptime = true;
|
||||
const param_type = try fullBodyExpr(¶m_gz, scope, coerced_type_ri, param_type_node, .normal);
|
||||
const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
|
||||
_ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
|
||||
@ -1380,18 +1392,19 @@ fn fnProtoExprInner(
|
||||
};
|
||||
|
||||
const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
|
||||
try expr(
|
||||
try comptimeExpr(
|
||||
&block_scope,
|
||||
scope,
|
||||
.{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
|
||||
fn_proto.ast.callconv_expr,
|
||||
.@"callconv",
|
||||
)
|
||||
else if (implicit_ccc)
|
||||
try block_scope.addBuiltinValue(node, .calling_convention_c)
|
||||
else
|
||||
.none;
|
||||
|
||||
const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
|
||||
const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty);
|
||||
|
||||
const result = try block_scope.addFunc(.{
|
||||
.src_node = fn_proto.ast.proto_node,
|
||||
@ -1453,7 +1466,7 @@ fn arrayInitExpr(
|
||||
});
|
||||
break :inst .{ array_type_inst, elem_type };
|
||||
} else {
|
||||
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
|
||||
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
|
||||
const array_type_inst = try gz.addPlNode(
|
||||
.array_type_sentinel,
|
||||
array_init.ast.type_expr,
|
||||
@ -1721,7 +1734,7 @@ fn structInitExpr(
|
||||
.rhs = elem_type,
|
||||
});
|
||||
} else blk: {
|
||||
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
|
||||
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
|
||||
break :blk try gz.addPlNode(
|
||||
.array_type_sentinel,
|
||||
struct_init.ast.type_expr,
|
||||
@ -1966,6 +1979,20 @@ fn comptimeExpr(
|
||||
scope: *Scope,
|
||||
ri: ResultInfo,
|
||||
node: Ast.Node.Index,
|
||||
reason: std.zig.SimpleComptimeReason,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
return comptimeExpr2(gz, scope, ri, node, node, reason);
|
||||
}
|
||||
|
||||
/// Like `comptimeExpr`, but draws a distinction between `node`, the expression to evaluate at comptime,
|
||||
/// and `src_node`, the node to attach to the `block_comptime`.
|
||||
fn comptimeExpr2(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
ri: ResultInfo,
|
||||
node: Ast.Node.Index,
|
||||
src_node: Ast.Node.Index,
|
||||
reason: std.zig.SimpleComptimeReason,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
if (gz.is_comptime) {
|
||||
// No need to change anything!
|
||||
@ -1979,19 +2006,50 @@ fn comptimeExpr(
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
switch (node_tags[node]) {
|
||||
// Any identifier in `primitive_instrs` is trivially comptime. In particular, this includes
|
||||
// some common types, so we can elide `block_comptime` for a few common type annotations.
|
||||
.identifier => {
|
||||
const ident_token = main_tokens[node];
|
||||
const ident_name_raw = tree.tokenSlice(ident_token);
|
||||
if (primitive_instrs.get(ident_name_raw)) |zir_const_ref| {
|
||||
// No need to worry about result location here, we're not creating a comptime block!
|
||||
return rvalue(gz, ri, zir_const_ref, node);
|
||||
}
|
||||
// Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has
|
||||
// special handling for this case.
|
||||
return identifier(gz, scope, ri, node, .{ .src_node = src_node, .reason = reason });
|
||||
},
|
||||
|
||||
// We can also avoid the block for a few trivial AST tags which are always comptime-known.
|
||||
.number_literal, .string_literal, .multiline_string_literal, .enum_literal, .error_value => {
|
||||
// These are leaf nodes which are always comptime-known.
|
||||
.number_literal,
|
||||
.char_literal,
|
||||
.string_literal,
|
||||
.multiline_string_literal,
|
||||
.enum_literal,
|
||||
.error_value,
|
||||
.anyframe_literal,
|
||||
.error_set_decl,
|
||||
// These nodes are not leaves, but will force comptime evaluation of all sub-expressions, and
|
||||
// hence behave the same regardless of whether they're in a comptime scope.
|
||||
.error_union,
|
||||
.merge_error_sets,
|
||||
.optional_type,
|
||||
.anyframe_type,
|
||||
.ptr_type_aligned,
|
||||
.ptr_type_sentinel,
|
||||
.ptr_type,
|
||||
.ptr_type_bit_range,
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.fn_proto_simple,
|
||||
.fn_proto_multi,
|
||||
.fn_proto_one,
|
||||
.fn_proto,
|
||||
.container_decl,
|
||||
.container_decl_trailing,
|
||||
.container_decl_arg,
|
||||
.container_decl_arg_trailing,
|
||||
.container_decl_two,
|
||||
.container_decl_two_trailing,
|
||||
.tagged_union,
|
||||
.tagged_union_trailing,
|
||||
.tagged_union_enum_tag,
|
||||
.tagged_union_enum_tag_trailing,
|
||||
.tagged_union_two,
|
||||
.tagged_union_two_trailing,
|
||||
=> {
|
||||
// No need to worry about result location here, we're not creating a comptime block!
|
||||
return expr(gz, scope, ri, node);
|
||||
},
|
||||
@ -2049,23 +2107,23 @@ fn comptimeExpr(
|
||||
block_scope.is_comptime = true;
|
||||
defer block_scope.unstack();
|
||||
|
||||
const block_inst = try gz.makeBlockInst(.block_comptime, node);
|
||||
const block_inst = try gz.makeBlockInst(.block_comptime, src_node);
|
||||
// Replace result location and copy back later - see above.
|
||||
const ty_only_ri: ResultInfo = .{
|
||||
.ctx = ri.ctx,
|
||||
.rl = if (try ri.rl.resultType(gz, node)) |res_ty|
|
||||
.rl = if (try ri.rl.resultType(gz, src_node)) |res_ty|
|
||||
.{ .coerced_ty = res_ty }
|
||||
else
|
||||
.none,
|
||||
};
|
||||
const block_result = try fullBodyExpr(&block_scope, scope, ty_only_ri, node, .normal);
|
||||
if (!gz.refIsNoReturn(block_result)) {
|
||||
_ = try block_scope.addBreak(.@"break", block_inst, block_result);
|
||||
_ = try block_scope.addBreak(.break_inline, block_inst, block_result);
|
||||
}
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
try block_scope.setBlockComptimeBody(block_inst, reason);
|
||||
try gz.instructions.append(gz.astgen.gpa, block_inst);
|
||||
|
||||
return rvalue(gz, ri, block_inst.toRef(), node);
|
||||
return rvalue(gz, ri, block_inst.toRef(), src_node);
|
||||
}
|
||||
|
||||
/// This one is for an actual `comptime` syntax, and will emit a compile error if
|
||||
@ -2084,7 +2142,7 @@ fn comptimeExprAst(
|
||||
const tree = astgen.tree;
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const body_node = node_datas[node].lhs;
|
||||
return comptimeExpr(gz, scope, ri, body_node);
|
||||
return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
|
||||
}
|
||||
|
||||
/// Restore the error return trace index. Performs the restore only if the result is a non-error or
|
||||
@ -2494,10 +2552,10 @@ fn labeledBlockExpr(
|
||||
|
||||
// Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
|
||||
// so that break statements can reference it.
|
||||
const block_tag: Zir.Inst.Tag = if (force_comptime) .block_comptime else .block;
|
||||
const block_inst = try gz.makeBlockInst(block_tag, block_node);
|
||||
const block_inst = try gz.makeBlockInst(if (force_comptime) .block_comptime else .block, block_node);
|
||||
try gz.instructions.append(astgen.gpa, block_inst);
|
||||
var block_scope = gz.makeSubBlock(parent_scope);
|
||||
block_scope.is_inline = force_comptime;
|
||||
block_scope.label = GenZir.Label{
|
||||
.token = label_token,
|
||||
.block_inst = block_inst,
|
||||
@ -2511,14 +2569,20 @@ fn labeledBlockExpr(
|
||||
// As our last action before the return, "pop" the error trace if needed
|
||||
_ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, block_node);
|
||||
const result = try rvalue(gz, block_scope.break_result_info, .void_value, block_node);
|
||||
_ = try block_scope.addBreak(.@"break", block_inst, result);
|
||||
const break_tag: Zir.Inst.Tag = if (force_comptime) .break_inline else .@"break";
|
||||
_ = try block_scope.addBreak(break_tag, block_inst, result);
|
||||
}
|
||||
|
||||
if (!block_scope.label.?.used) {
|
||||
try astgen.appendErrorTok(label_token, "unused block label", .{});
|
||||
}
|
||||
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
if (force_comptime) {
|
||||
try block_scope.setBlockComptimeBody(block_inst, .comptime_keyword);
|
||||
} else {
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
}
|
||||
|
||||
if (need_result_rvalue) {
|
||||
return rvalue(gz, ri, block_inst.toRef(), block_node);
|
||||
} else {
|
||||
@ -2941,6 +3005,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,
|
||||
@ -3255,9 +3320,10 @@ fn varDecl(
|
||||
} else .{ .rl = .none, .ctx = .const_init };
|
||||
const prev_anon_name_strategy = gz.anon_name_strategy;
|
||||
gz.anon_name_strategy = .dbg_var;
|
||||
const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, force_comptime);
|
||||
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
|
||||
@ -3321,7 +3387,7 @@ fn varDecl(
|
||||
const prev_anon_name_strategy = gz.anon_name_strategy;
|
||||
gz.anon_name_strategy = .dbg_var;
|
||||
defer gz.anon_name_strategy = prev_anon_name_strategy;
|
||||
const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, force_comptime);
|
||||
const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
|
||||
|
||||
// The const init expression may have modified the error return trace, so signal
|
||||
// to Sema that it should save the new index for restoring later.
|
||||
@ -3393,7 +3459,14 @@ fn varDecl(
|
||||
};
|
||||
const prev_anon_name_strategy = gz.anon_name_strategy;
|
||||
gz.anon_name_strategy = .dbg_var;
|
||||
_ = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, is_comptime);
|
||||
_ = try reachableExprComptime(
|
||||
gz,
|
||||
scope,
|
||||
result_info,
|
||||
var_decl.ast.init_node,
|
||||
node,
|
||||
if (var_decl.comptime_token != null) .comptime_keyword else null,
|
||||
);
|
||||
gz.anon_name_strategy = prev_anon_name_strategy;
|
||||
const final_ptr: Zir.Inst.Ref = if (resolve_inferred) ptr: {
|
||||
break :ptr try gz.addUnNode(.resolve_inferred_alloc, alloc, node);
|
||||
@ -3501,8 +3574,8 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
|
||||
|
||||
if (full.comptime_token) |_| {
|
||||
const comptime_block_inst = try gz.makeBlockInst(.block_comptime, node);
|
||||
_ = try inner_gz.addBreak(.@"break", comptime_block_inst, .void_value);
|
||||
try inner_gz.setBlockBody(comptime_block_inst);
|
||||
_ = try inner_gz.addBreak(.break_inline, comptime_block_inst, .void_value);
|
||||
try inner_gz.setBlockComptimeBody(comptime_block_inst, .comptime_keyword);
|
||||
try gz.instructions.append(gz.astgen.gpa, comptime_block_inst);
|
||||
}
|
||||
}
|
||||
@ -3673,8 +3746,8 @@ fn assignDestructureMaybeDecls(
|
||||
// Finish the block_comptime. Inferred alloc resolution etc will occur
|
||||
// in the parent block.
|
||||
const comptime_block_inst = try gz.makeBlockInst(.block_comptime, node);
|
||||
_ = try inner_gz.addBreak(.@"break", comptime_block_inst, .void_value);
|
||||
try inner_gz.setBlockBody(comptime_block_inst);
|
||||
_ = try inner_gz.addBreak(.break_inline, comptime_block_inst, .void_value);
|
||||
try inner_gz.setBlockComptimeBody(comptime_block_inst, .comptime_keyword);
|
||||
try gz.instructions.append(gz.astgen.gpa, comptime_block_inst);
|
||||
}
|
||||
|
||||
@ -3867,7 +3940,16 @@ fn ptrType(
|
||||
gz.astgen.source_line = source_line;
|
||||
gz.astgen.source_column = source_column;
|
||||
|
||||
sentinel_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel);
|
||||
sentinel_ref = try comptimeExpr(
|
||||
gz,
|
||||
scope,
|
||||
.{ .rl = .{ .ty = elem_type } },
|
||||
ptr_info.ast.sentinel,
|
||||
switch (ptr_info.size) {
|
||||
.Slice => .slice_sentinel,
|
||||
else => .pointer_sentinel,
|
||||
},
|
||||
);
|
||||
trailing_count += 1;
|
||||
}
|
||||
if (ptr_info.ast.addrspace_node != 0) {
|
||||
@ -3876,7 +3958,7 @@ fn ptrType(
|
||||
gz.astgen.source_column = source_column;
|
||||
|
||||
const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space);
|
||||
addrspace_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node);
|
||||
addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node, .@"addrspace");
|
||||
trailing_count += 1;
|
||||
}
|
||||
if (ptr_info.ast.align_node != 0) {
|
||||
@ -3884,13 +3966,13 @@ fn ptrType(
|
||||
gz.astgen.source_line = source_line;
|
||||
gz.astgen.source_column = source_column;
|
||||
|
||||
align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node);
|
||||
align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align");
|
||||
trailing_count += 1;
|
||||
}
|
||||
if (ptr_info.ast.bit_range_start != 0) {
|
||||
assert(ptr_info.ast.bit_range_end != 0);
|
||||
bit_start_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start);
|
||||
bit_end_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end);
|
||||
bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type);
|
||||
bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end, .type);
|
||||
trailing_count += 2;
|
||||
}
|
||||
|
||||
@ -3953,7 +4035,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
|
||||
{
|
||||
return astgen.failNode(len_node, "unable to infer array size", .{});
|
||||
}
|
||||
const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node);
|
||||
const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);
|
||||
const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
|
||||
|
||||
const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
|
||||
@ -3977,9 +4059,9 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.
|
||||
{
|
||||
return astgen.failNode(len_node, "unable to infer array size", .{});
|
||||
}
|
||||
const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node);
|
||||
const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .array_length);
|
||||
const elem_type = try typeExpr(gz, scope, extra.elem_type);
|
||||
const sentinel = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node, true);
|
||||
const sentinel = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node, .array_sentinel);
|
||||
|
||||
const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{
|
||||
.len = len,
|
||||
@ -5321,7 +5403,7 @@ fn tupleDecl(
|
||||
astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
|
||||
|
||||
if (field.ast.value_expr != 0) {
|
||||
const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr);
|
||||
const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value);
|
||||
astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
|
||||
} else {
|
||||
astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
|
||||
@ -5693,7 +5775,7 @@ fn containerDecl(
|
||||
namespace.base.tag = .namespace;
|
||||
|
||||
const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
|
||||
try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg)
|
||||
try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type)
|
||||
else
|
||||
.none;
|
||||
|
||||
@ -7573,7 +7655,7 @@ fn switchExprErrUnion(
|
||||
if (node_tags[item_node] == .switch_range) continue;
|
||||
items_len += 1;
|
||||
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
|
||||
try payloads.append(gpa, @intFromEnum(item_inst));
|
||||
}
|
||||
|
||||
@ -7583,8 +7665,8 @@ fn switchExprErrUnion(
|
||||
if (node_tags[range] != .switch_range) continue;
|
||||
ranges_len += 1;
|
||||
|
||||
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
|
||||
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
|
||||
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
|
||||
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
|
||||
try payloads.appendSlice(gpa, &[_]u32{
|
||||
@intFromEnum(first), @intFromEnum(last),
|
||||
});
|
||||
@ -7602,7 +7684,7 @@ fn switchExprErrUnion(
|
||||
scalar_case_index += 1;
|
||||
try payloads.resize(gpa, header_index + 2); // item, body_len
|
||||
const item_node = case.ast.values[0];
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
|
||||
payloads.items[header_index] = @intFromEnum(item_inst);
|
||||
break :blk header_index + 1;
|
||||
};
|
||||
@ -8046,7 +8128,7 @@ fn switchExpr(
|
||||
if (node_tags[item_node] == .switch_range) continue;
|
||||
items_len += 1;
|
||||
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
|
||||
try payloads.append(gpa, @intFromEnum(item_inst));
|
||||
}
|
||||
|
||||
@ -8056,8 +8138,8 @@ fn switchExpr(
|
||||
if (node_tags[range] != .switch_range) continue;
|
||||
ranges_len += 1;
|
||||
|
||||
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
|
||||
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
|
||||
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
|
||||
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
|
||||
try payloads.appendSlice(gpa, &[_]u32{
|
||||
@intFromEnum(first), @intFromEnum(last),
|
||||
});
|
||||
@ -8075,7 +8157,7 @@ fn switchExpr(
|
||||
scalar_case_index += 1;
|
||||
try payloads.resize(gpa, header_index + 2); // item, body_len
|
||||
const item_node = case.ast.values[0];
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
|
||||
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
|
||||
payloads.items[header_index] = @intFromEnum(item_inst);
|
||||
break :blk header_index + 1;
|
||||
};
|
||||
@ -8339,11 +8421,17 @@ fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 {
|
||||
return x;
|
||||
}
|
||||
|
||||
const ComptimeBlockInfo = struct {
|
||||
src_node: Ast.Node.Index,
|
||||
reason: std.zig.SimpleComptimeReason,
|
||||
};
|
||||
|
||||
fn identifier(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
ri: ResultInfo,
|
||||
ident: Ast.Node.Index,
|
||||
force_comptime: ?ComptimeBlockInfo,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
@ -8362,6 +8450,7 @@ fn identifier(
|
||||
}
|
||||
|
||||
if (ident_name_raw.len >= 2) integer: {
|
||||
// Keep in sync with logic in `comptimeExpr2`.
|
||||
const first_c = ident_name_raw[0];
|
||||
if (first_c == 'i' or first_c == 'u') {
|
||||
const signedness: std.builtin.Signedness = switch (first_c == 'i') {
|
||||
@ -8396,8 +8485,31 @@ fn identifier(
|
||||
}
|
||||
}
|
||||
|
||||
// Local variables, including function parameters.
|
||||
return localVarRef(gz, scope, ri, ident, ident_token);
|
||||
// Local variables, including function parameters, and container-level declarations.
|
||||
|
||||
if (force_comptime) |fc| {
|
||||
// Mirrors the logic at the end of `comptimeExpr2`.
|
||||
const block_inst = try gz.makeBlockInst(.block_comptime, fc.src_node);
|
||||
|
||||
var comptime_gz = gz.makeSubBlock(scope);
|
||||
comptime_gz.is_comptime = true;
|
||||
defer comptime_gz.unstack();
|
||||
|
||||
const sub_ri: ResultInfo = .{
|
||||
.ctx = ri.ctx,
|
||||
.rl = .none, // no point providing a result type, it won't change anything
|
||||
};
|
||||
const block_result = try localVarRef(&comptime_gz, scope, sub_ri, ident, ident_token);
|
||||
assert(!comptime_gz.endsWithNoReturn());
|
||||
_ = try comptime_gz.addBreak(.break_inline, block_inst, block_result);
|
||||
|
||||
try comptime_gz.setBlockComptimeBody(block_inst, fc.reason);
|
||||
try gz.instructions.append(astgen.gpa, block_inst);
|
||||
|
||||
return rvalue(gz, ri, block_inst.toRef(), fc.src_node);
|
||||
} else {
|
||||
return localVarRef(gz, scope, ri, ident, ident_token);
|
||||
}
|
||||
}
|
||||
|
||||
fn localVarRef(
|
||||
@ -8836,7 +8948,7 @@ fn asmExpr(
|
||||
},
|
||||
else => .{
|
||||
.tag = .asm_expr,
|
||||
.tmpl = @enumFromInt(@intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template))),
|
||||
.tmpl = @enumFromInt(@intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template, .inline_assembly_code))),
|
||||
},
|
||||
};
|
||||
|
||||
@ -8973,7 +9085,7 @@ fn unionInit(
|
||||
params: []const Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const union_type = try typeExpr(gz, scope, params[0]);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_name);
|
||||
const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
|
||||
.container_type = union_type,
|
||||
.field_name = field_name,
|
||||
@ -9078,7 +9190,7 @@ fn ptrCast(
|
||||
const flags_int: FlagsInt = @bitCast(flags);
|
||||
const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
|
||||
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs, .field_name);
|
||||
const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);
|
||||
try emitDbgStmt(gz, cursor);
|
||||
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
|
||||
@ -9279,7 +9391,7 @@ fn builtinCall(
|
||||
return astgen.failNode(node, "'@branchHint' must appear as the first statement in a function or conditional branch", .{});
|
||||
}
|
||||
const hint_ty = try gz.addBuiltinValue(node, .branch_hint);
|
||||
const hint_val = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = hint_ty } }, params[0]);
|
||||
const hint_val = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = hint_ty } }, params[0], .operand_branchHint);
|
||||
_ = try gz.addExtendedPayload(.branch_hint, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = hint_val,
|
||||
@ -9326,18 +9438,18 @@ fn builtinCall(
|
||||
if (ri.rl == .ref or ri.rl == .ref_coerced_ty) {
|
||||
return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
|
||||
.lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
|
||||
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
|
||||
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name),
|
||||
});
|
||||
}
|
||||
const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
|
||||
.lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
|
||||
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
|
||||
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.FieldType => {
|
||||
const ty_inst = try typeExpr(gz, scope, params[0]);
|
||||
const name_inst = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
|
||||
const name_inst = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name);
|
||||
const result = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
|
||||
.container_type = ty_inst,
|
||||
.field_name = name_inst,
|
||||
@ -9358,7 +9470,7 @@ fn builtinCall(
|
||||
.@"export" => {
|
||||
const exported = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
const export_options_ty = try gz.addBuiltinValue(node, .export_options);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1], .export_options);
|
||||
_ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
|
||||
.exported = exported,
|
||||
.options = options,
|
||||
@ -9368,7 +9480,7 @@ fn builtinCall(
|
||||
.@"extern" => {
|
||||
const type_inst = try typeExpr(gz, scope, params[0]);
|
||||
const extern_options_ty = try gz.addBuiltinValue(node, .extern_options);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = extern_options_ty } }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = extern_options_ty } }, params[1], .extern_options);
|
||||
const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = type_inst,
|
||||
@ -9560,7 +9672,7 @@ fn builtinCall(
|
||||
// zig fmt: on
|
||||
|
||||
.wasm_memory_size => {
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .wasm_memory_index);
|
||||
const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
@ -9568,7 +9680,7 @@ fn builtinCall(
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.wasm_memory_grow => {
|
||||
const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .wasm_memory_index);
|
||||
const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[1]);
|
||||
const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
@ -9579,8 +9691,8 @@ fn builtinCall(
|
||||
},
|
||||
.c_define => {
|
||||
if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
|
||||
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
|
||||
const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .operand_cDefine_macro_name);
|
||||
const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1], .operand_cDefine_macro_value);
|
||||
const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = name,
|
||||
@ -9666,7 +9778,7 @@ fn builtinCall(
|
||||
},
|
||||
.call => {
|
||||
const call_modifier_ty = try gz.addBuiltinValue(node, .call_modifier);
|
||||
const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = call_modifier_ty } }, params[0]);
|
||||
const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = call_modifier_ty } }, params[0], .call_modifier);
|
||||
const callee = try expr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const args = try expr(gz, scope, .{ .rl = .none }, params[2]);
|
||||
const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
|
||||
@ -9682,7 +9794,7 @@ fn builtinCall(
|
||||
},
|
||||
.field_parent_ptr => {
|
||||
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .field_name);
|
||||
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{
|
||||
.src_node = gz.nodeIndexToRelative(node),
|
||||
.parent_ptr_type = parent_ptr_type,
|
||||
@ -9713,7 +9825,7 @@ fn builtinCall(
|
||||
.elem_type = try typeExpr(gz, scope, params[0]),
|
||||
.a = try expr(gz, scope, .{ .rl = .none }, params[1]),
|
||||
.b = try expr(gz, scope, .{ .rl = .none }, params[2]),
|
||||
.mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]),
|
||||
.mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3], .operand_shuffle_mask),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
@ -9739,7 +9851,7 @@ fn builtinCall(
|
||||
},
|
||||
.Vector => {
|
||||
const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
|
||||
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]),
|
||||
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),
|
||||
.rhs = try typeExpr(gz, scope, params[1]),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
@ -9747,7 +9859,7 @@ fn builtinCall(
|
||||
.prefetch => {
|
||||
const prefetch_options_ty = try gz.addBuiltinValue(node, .prefetch_options);
|
||||
const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = prefetch_options_ty } }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = prefetch_options_ty } }, params[1], .prefetch_options);
|
||||
_ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = ptr,
|
||||
@ -9785,7 +9897,7 @@ fn builtinCall(
|
||||
},
|
||||
|
||||
.work_item_id => {
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
|
||||
const result = try gz.addExtendedPayload(.work_item_id, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
@ -9793,7 +9905,7 @@ fn builtinCall(
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.work_group_size => {
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
|
||||
const result = try gz.addExtendedPayload(.work_group_size, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
@ -9801,7 +9913,7 @@ fn builtinCall(
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.work_group_id => {
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
|
||||
const result = try gz.addExtendedPayload(.work_group_id, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
@ -9821,7 +9933,13 @@ fn hasDeclOrField(
|
||||
tag: Zir.Inst.Tag,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const container_type = try typeExpr(gz, scope, lhs_node);
|
||||
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node);
|
||||
const name = try comptimeExpr(
|
||||
gz,
|
||||
scope,
|
||||
.{ .rl = .{ .coerced_ty = .slice_const_u8_type } },
|
||||
rhs_node,
|
||||
if (tag == .has_decl) .decl_name else .field_name,
|
||||
);
|
||||
const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
|
||||
.lhs = container_type,
|
||||
.rhs = name,
|
||||
@ -9874,7 +9992,7 @@ fn simpleUnOp(
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
|
||||
const operand = if (tag == .compile_error)
|
||||
try comptimeExpr(gz, scope, operand_ri, operand_node)
|
||||
try comptimeExpr(gz, scope, operand_ri, operand_node, .compile_error_string)
|
||||
else
|
||||
try expr(gz, scope, operand_ri, operand_node);
|
||||
switch (tag) {
|
||||
@ -9972,7 +10090,13 @@ fn simpleCBuiltin(
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
|
||||
if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
|
||||
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, operand_node);
|
||||
const operand = try comptimeExpr(
|
||||
gz,
|
||||
scope,
|
||||
.{ .rl = .{ .coerced_ty = .slice_const_u8_type } },
|
||||
operand_node,
|
||||
if (tag == .c_undef) .operand_cUndef_macro_name else .operand_cInclude_file_name,
|
||||
);
|
||||
_ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
@ -9990,7 +10114,7 @@ fn offsetOf(
|
||||
tag: Zir.Inst.Tag,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const type_inst = try typeExpr(gz, scope, lhs_node);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node, .field_name);
|
||||
const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
|
||||
.lhs = type_inst,
|
||||
.rhs = field_name,
|
||||
@ -11996,11 +12120,16 @@ const GenZir = struct {
|
||||
}
|
||||
|
||||
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
|
||||
/// Asserts `inst` is not a `block_comptime`.
|
||||
fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
const body = gz.instructionsSlice();
|
||||
const body_len = astgen.countBodyLenAfterFixups(body);
|
||||
|
||||
const zir_tags = astgen.instructions.items(.tag);
|
||||
assert(zir_tags[@intFromEnum(inst)] != .block_comptime); // use `setComptimeBlockBody` instead
|
||||
|
||||
try astgen.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@typeInfo(Zir.Inst.Block).@"struct".fields.len + body_len,
|
||||
@ -12013,6 +12142,32 @@ const GenZir = struct {
|
||||
gz.unstack();
|
||||
}
|
||||
|
||||
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
|
||||
/// Asserts `inst` is a `block_comptime`.
|
||||
fn setBlockComptimeBody(gz: *GenZir, inst: Zir.Inst.Index, comptime_reason: std.zig.SimpleComptimeReason) !void {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
const body = gz.instructionsSlice();
|
||||
const body_len = astgen.countBodyLenAfterFixups(body);
|
||||
|
||||
const zir_tags = astgen.instructions.items(.tag);
|
||||
assert(zir_tags[@intFromEnum(inst)] == .block_comptime); // use `setBlockBody` instead
|
||||
|
||||
try astgen.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@typeInfo(Zir.Inst.BlockComptime).@"struct".fields.len + body_len,
|
||||
);
|
||||
const zir_datas = astgen.instructions.items(.data);
|
||||
zir_datas[@intFromEnum(inst)].pl_node.payload_index = astgen.addExtraAssumeCapacity(
|
||||
Zir.Inst.BlockComptime{
|
||||
.reason = comptime_reason,
|
||||
.body_len = body_len,
|
||||
},
|
||||
);
|
||||
astgen.appendBodyWithFixups(body);
|
||||
gz.unstack();
|
||||
}
|
||||
|
||||
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
|
||||
fn setTryBody(gz: *GenZir, inst: Zir.Inst.Index, operand: Zir.Inst.Ref) !void {
|
||||
const astgen = gz.astgen;
|
||||
|
||||
@ -78,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
|
||||
Inst.Ref,
|
||||
Inst.Index,
|
||||
Inst.Declaration.Name,
|
||||
std.zig.SimpleComptimeReason,
|
||||
NullTerminatedString,
|
||||
=> @enumFromInt(code.extra[i]),
|
||||
|
||||
@ -291,7 +292,8 @@ pub const Inst = struct {
|
||||
/// Uses the `pl_node` union field. Payload is `Block`.
|
||||
block,
|
||||
/// Like `block`, but forces full evaluation of its contents at compile-time.
|
||||
/// Uses the `pl_node` union field. Payload is `Block`.
|
||||
/// Exited with `break_inline`.
|
||||
/// Uses the `pl_node` union field. Payload is `BlockComptime`.
|
||||
block_comptime,
|
||||
/// A list of instructions which are analyzed in the parent context, without
|
||||
/// generating a runtime block. Must terminate with an "inline" variant of
|
||||
@ -709,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`.
|
||||
@ -1291,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,
|
||||
@ -1351,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,
|
||||
@ -1734,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,
|
||||
|
||||
@ -2547,6 +2558,13 @@ pub const Inst = struct {
|
||||
body_len: u32,
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// * inst: Index // for each `body_len`
|
||||
pub const BlockComptime = struct {
|
||||
reason: std.zig.SimpleComptimeReason,
|
||||
body_len: u32,
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// * inst: Index // for each `body_len`
|
||||
pub const BoolBr = struct {
|
||||
@ -4134,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,
|
||||
@ -4517,7 +4536,6 @@ fn findTrackableInner(
|
||||
// Block instructions, recurse over the bodies.
|
||||
|
||||
.block,
|
||||
.block_comptime,
|
||||
.block_inline,
|
||||
.c_import,
|
||||
.typeof_builtin,
|
||||
@ -4528,6 +4546,12 @@ fn findTrackableInner(
|
||||
const body = zir.bodySlice(extra.end, extra.data.body_len);
|
||||
return zir.findTrackableBody(gpa, contents, defers, body);
|
||||
},
|
||||
.block_comptime => {
|
||||
const inst_data = datas[@intFromEnum(inst)].pl_node;
|
||||
const extra = zir.extraData(Inst.BlockComptime, inst_data.payload_index);
|
||||
const body = zir.bodySlice(extra.end, extra.data.body_len);
|
||||
return zir.findTrackableBody(gpa, contents, defers, body);
|
||||
},
|
||||
.condbr, .condbr_inline => {
|
||||
const inst_data = datas[@intFromEnum(inst)].pl_node;
|
||||
const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);
|
||||
|
||||
@ -3435,6 +3435,7 @@ pub fn addModuleErrorMsg(
|
||||
var notes: std.ArrayHashMapUnmanaged(ErrorBundle.ErrorMessage, void, ErrorNoteHashContext, true) = .empty;
|
||||
defer notes.deinit(gpa);
|
||||
|
||||
var last_note_loc: ?std.zig.Loc = null;
|
||||
for (module_err_msg.notes) |module_note| {
|
||||
const note_src_loc = module_note.src_loc.upgrade(zcu);
|
||||
const source = try note_src_loc.file_scope.getSource(gpa);
|
||||
@ -3443,6 +3444,9 @@ pub fn addModuleErrorMsg(
|
||||
const note_file_path = try note_src_loc.file_scope.fullPath(gpa);
|
||||
defer gpa.free(note_file_path);
|
||||
|
||||
const omit_source_line = loc.eql(err_loc) or (last_note_loc != null and loc.eql(last_note_loc.?));
|
||||
last_note_loc = loc;
|
||||
|
||||
const gop = try notes.getOrPutContext(gpa, .{
|
||||
.msg = try eb.addString(module_note.msg),
|
||||
.src_loc = try eb.addSourceLocation(.{
|
||||
@ -3452,7 +3456,7 @@ pub fn addModuleErrorMsg(
|
||||
.span_end = span.end,
|
||||
.line = @intCast(loc.line),
|
||||
.column = @intCast(loc.column),
|
||||
.source_line = if (err_loc.eql(loc)) 0 else try eb.addString(loc.source_line),
|
||||
.source_line = if (omit_source_line) 0 else try eb.addString(loc.source_line),
|
||||
}),
|
||||
}, .{ .eb = eb });
|
||||
if (gop.found_existing) {
|
||||
|
||||
1141
src/Sema.zig
1141
src/Sema.zig
File diff suppressed because it is too large
Load Diff
@ -682,7 +682,13 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
|
||||
.namespace = comptime_unit.namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.is_comptime = true,
|
||||
.comptime_reason = .{ .reason = .{
|
||||
.src = .{
|
||||
.base_node_inst = comptime_unit.zir_index,
|
||||
.offset = .{ .token_offset = 0 },
|
||||
},
|
||||
.r = .{ .simple = .comptime_keyword },
|
||||
} },
|
||||
.src_base_inst = comptime_unit.zir_index,
|
||||
.type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
|
||||
Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
|
||||
@ -878,7 +884,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
.namespace = old_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.is_comptime = true,
|
||||
.comptime_reason = undefined, // set below
|
||||
.src_base_inst = old_nav.analysis.?.zir_index,
|
||||
.type_name_ctx = old_nav.fqn,
|
||||
};
|
||||
@ -893,6 +899,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
|
||||
const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
|
||||
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = init_src,
|
||||
.r = .{ .simple = .container_var_init },
|
||||
} };
|
||||
|
||||
const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {
|
||||
// Since we have a type body, the type is resolved separately!
|
||||
// Of course, we need to make sure we depend on it properly.
|
||||
@ -1253,7 +1264,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
.namespace = old_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.is_comptime = true,
|
||||
.comptime_reason = undefined, // set below
|
||||
.src_base_inst = old_nav.analysis.?.zir_index,
|
||||
.type_name_ctx = old_nav.fqn,
|
||||
};
|
||||
@ -1262,6 +1273,13 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
const zir_decl = zir.getDeclaration(inst_resolved.inst);
|
||||
assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
|
||||
|
||||
const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
|
||||
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = ty_src,
|
||||
.r = .{ .simple = .type },
|
||||
} };
|
||||
|
||||
const type_body = zir_decl.type_body orelse {
|
||||
// The type of this `Nav` is inferred from the value.
|
||||
// In other words, this `nav_ty` depends on the corresponding `nav_val`.
|
||||
@ -1279,8 +1297,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
return .{ .type_changed = true };
|
||||
};
|
||||
|
||||
const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
|
||||
|
||||
const resolved_ty: Type = ty: {
|
||||
const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_resolved.inst);
|
||||
const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
|
||||
@ -2442,7 +2458,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
|
||||
.namespace = decl_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.is_comptime = false,
|
||||
.comptime_reason = null,
|
||||
.src_base_inst = decl_nav.analysis.?.zir_index,
|
||||
.type_name_ctx = func_nav.fqn,
|
||||
};
|
||||
|
||||
@ -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,
|
||||
@ -437,7 +438,6 @@ const Writer = struct {
|
||||
.field_call => try self.writeCall(stream, inst, .field),
|
||||
|
||||
.block,
|
||||
.block_comptime,
|
||||
.block_inline,
|
||||
.suspend_block,
|
||||
.loop,
|
||||
@ -445,6 +445,8 @@ const Writer = struct {
|
||||
.typeof_builtin,
|
||||
=> try self.writeBlock(stream, inst),
|
||||
|
||||
.block_comptime => try self.writeBlockComptime(stream, inst),
|
||||
|
||||
.condbr,
|
||||
.condbr_inline,
|
||||
=> try self.writeCondBr(stream, inst),
|
||||
@ -1342,17 +1344,22 @@ const Writer = struct {
|
||||
}
|
||||
|
||||
fn writeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
||||
try self.writePlNodeBlockWithoutSrc(stream, inst);
|
||||
try self.writeSrcNode(stream, inst_data.src_node);
|
||||
}
|
||||
|
||||
fn writePlNodeBlockWithoutSrc(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
||||
const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
|
||||
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
||||
try self.writeBracedBody(stream, body);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrcNode(stream, inst_data.src_node);
|
||||
}
|
||||
|
||||
fn writeBlockComptime(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
||||
const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
|
||||
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
||||
try stream.print("reason={s}, ", .{@tagName(extra.data.reason)});
|
||||
try self.writeBracedBody(stream, body);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrcNode(stream, inst_data.src_node);
|
||||
}
|
||||
|
||||
fn writeCondBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
|
||||
@ -10,5 +10,5 @@ pub export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :2:36: error: unable to resolve comptime value
|
||||
// :2:36: note: global variable initializer must be comptime-known
|
||||
// :2:36: note: thread local and dll imported variables have runtime-known addresses
|
||||
// :2:36: note: initializer of container-level variable must be comptime-known
|
||||
// :2:36: note: threadlocal and dll imported variables have runtime-known addresses
|
||||
|
||||
@ -13,8 +13,8 @@ pub export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:25: error: unable to resolve comptime value
|
||||
// :7:25: note: initializer of comptime only struct must be comptime-known
|
||||
// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_166.C' must be comptime-known
|
||||
// :4:16: note: struct requires comptime because of this field
|
||||
// :4:16: note: types are not available at runtime
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
export fn entry(base: f32, exponent: f32) f32 {
|
||||
const exponent: f32 = 1.0;
|
||||
export fn entry(base: f32) f32 {
|
||||
return base ** exponent;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:12: error: expected indexable; found 'f32'
|
||||
// :2:17: note: this operator multiplies arrays; use std.math.pow for exponentiation
|
||||
// :3:12: error: expected indexable; found 'f32'
|
||||
// :3:17: note: this operator multiplies arrays; use std.math.pow for exponentiation
|
||||
|
||||
@ -15,4 +15,5 @@ fn doSomeAsm() void {
|
||||
// target=native
|
||||
//
|
||||
// :6:5: error: unable to evaluate comptime expression
|
||||
// :2:14: note: called from here
|
||||
// :2:14: note: called at comptime from here
|
||||
// :1:1: note: 'comptime' keyword forces comptime evaluation
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
export fn entry(a: bool, b: bool) i32 {
|
||||
if (a || b) {
|
||||
export fn entry() i32 {
|
||||
if (true || false) {
|
||||
return 1234;
|
||||
}
|
||||
return 5678;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:9: error: expected error set type, found 'bool'
|
||||
// :2:11: note: '||' merges error sets; 'or' performs boolean OR
|
||||
// :2:14: note: '||' merges error sets; 'or' performs boolean OR
|
||||
|
||||
@ -20,4 +20,6 @@ pub export fn entry2() void {
|
||||
//
|
||||
// :5:15: error: unable to evaluate comptime expression
|
||||
// :5:13: note: operation is runtime due to this operand
|
||||
// :4:72: note: '@shuffle' mask must be comptime-known
|
||||
// :13:11: error: unable to evaluate comptime expression
|
||||
// :12:72: note: '@shuffle' mask must be comptime-known
|
||||
|
||||
@ -11,8 +11,8 @@ pub export fn entry2() void {
|
||||
// target=native
|
||||
//
|
||||
// :1:16: error: unable to resolve comptime value
|
||||
// :1:16: note: global variable initializer must be comptime-known
|
||||
// :1:16: note: thread local and dll imported variables have runtime-known addresses
|
||||
// :1:16: note: initializer of container-level variable must be comptime-known
|
||||
// :1:16: note: threadlocal and dll imported variables have runtime-known addresses
|
||||
// :2:17: error: unable to resolve comptime value
|
||||
// :2:17: note: global variable initializer must be comptime-known
|
||||
// :2:17: note: thread local and dll imported variables have runtime-known addresses
|
||||
// :2:17: note: initializer of container-level variable must be comptime-known
|
||||
// :2:17: note: threadlocal and dll imported variables have runtime-known addresses
|
||||
|
||||
@ -4,16 +4,15 @@ const S = struct {
|
||||
};
|
||||
|
||||
export fn a() void {
|
||||
var value: u32 = 3;
|
||||
const comptimeStruct = S {
|
||||
.normal_ptr = &value,
|
||||
};
|
||||
_ = comptimeStruct;
|
||||
var value: u32 = 3;
|
||||
const comptimeStruct = S{
|
||||
.normal_ptr = &value,
|
||||
};
|
||||
_ = comptimeStruct;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// 9:6: error: unable to resolve comptime value
|
||||
// 9:6: note: initializer of comptime only struct must be comptime-known
|
||||
// :9:10: error: unable to resolve comptime value
|
||||
// :9:10: note: initializer of comptime-only struct 'tmp.S' must be comptime-known
|
||||
// :2:21: note: struct requires comptime because of this field
|
||||
|
||||
@ -33,18 +33,14 @@ pub export fn entry2() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:9: error: unable to resolve comptime value
|
||||
// :8:9: note: condition in comptime branch must be comptime-known
|
||||
// :7:13: note: expression is evaluated at comptime because the function returns a comptime-only type 'tmp.S'
|
||||
// :19:15: note: called at comptime from here
|
||||
// :7:13: note: function with comptime-only return type 'tmp.S' is evaluated at comptime
|
||||
// :2:12: note: struct requires comptime because of this field
|
||||
// :2:12: note: use '*const fn () void' for a function pointer type
|
||||
// :19:15: note: called from here
|
||||
// :22:13: error: unable to resolve comptime value
|
||||
// :22:13: note: condition in comptime switch must be comptime-known
|
||||
// :21:17: note: expression is evaluated at comptime because the function returns a comptime-only type 'tmp.S'
|
||||
// :32:19: note: called at comptime from here
|
||||
// :21:17: note: function with comptime-only return type 'tmp.S' is evaluated at comptime
|
||||
// :2:12: note: struct requires comptime because of this field
|
||||
// :2:12: note: use '*const fn () void' for a function pointer type
|
||||
// :32:19: note: called from here
|
||||
|
||||
@ -11,4 +11,4 @@ export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :6:31: error: unable to resolve comptime value
|
||||
// :6:31: note: value being casted to enum with 'comptime_int' tag type must be comptime-known
|
||||
// :6:31: note: value casted to enum with 'comptime_int' tag type must be comptime-known
|
||||
|
||||
@ -11,4 +11,4 @@ pub export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :6:31: error: unable to resolve comptime value
|
||||
// :6:31: note: value being casted to 'comptime_int' must be comptime-known
|
||||
// :6:31: note: value casted to 'comptime_int' must be comptime-known
|
||||
|
||||
@ -4,7 +4,7 @@ const S = struct {
|
||||
};
|
||||
fn bar() void {}
|
||||
|
||||
fn foo(comptime a: *u8) S {
|
||||
fn foo(a: *u8) S {
|
||||
return .{ .fnPtr = bar, .a = a.* };
|
||||
}
|
||||
pub export fn entry() void {
|
||||
@ -13,11 +13,8 @@ pub export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :12:13: error: unable to resolve comptime value
|
||||
// :12:13: note: argument to function being called at comptime must be comptime-known
|
||||
// :7:25: note: expression is evaluated at comptime because the function returns a comptime-only type 'tmp.S'
|
||||
// :7:16: note: function with comptime-only return type 'tmp.S' is evaluated at comptime
|
||||
// :2:12: note: struct requires comptime because of this field
|
||||
// :2:12: note: use '*const fn () void' for a function pointer type
|
||||
|
||||
@ -15,9 +15,8 @@ pub export fn entry() void {
|
||||
_ = foo(a, fn () void);
|
||||
}
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :15:13: error: unable to resolve comptime value
|
||||
// :15:13: note: argument to function being called at comptime must be comptime-known
|
||||
// :9:38: note: expression is evaluated at comptime because the generic function was instantiated with a comptime-only return type
|
||||
// :9:38: note: generic function instantiated with comptime-only return type 'tmp.S(fn () void)' is evaluated at comptime
|
||||
// :3:16: note: struct requires comptime because of this field
|
||||
// :3:16: note: use '*const fn () void' for a function pointer type
|
||||
|
||||
@ -12,3 +12,4 @@ comptime {
|
||||
//
|
||||
// :6:17: error: unable to evaluate comptime expression
|
||||
// :6:17: note: operation is runtime due to this operand
|
||||
// :5:1: note: 'comptime' keyword forces comptime evaluation
|
||||
@ -5,8 +5,6 @@ pub export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:11: error: unable to resolve comptime value
|
||||
// :2:11: note: global variable initializer must be comptime-known
|
||||
// :2:11: note: initializer of container-level variable must be comptime-known
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
pub export fn entry() void {
|
||||
var a: *u32 = undefined;
|
||||
const a: *u32 = undefined;
|
||||
_ = *a;
|
||||
_ = &a;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:10: error: expected type 'type', found '*u32'
|
||||
// :3:10: note: use '.*' to dereference pointer
|
||||
|
||||
@ -14,4 +14,4 @@ pub export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :5:18: error: unable to resolve comptime value
|
||||
// :5:18: note: parameter is comptime
|
||||
// :5:18: note: argument to comptime parameter must be comptime-known
|
||||
|
||||
@ -10,10 +10,8 @@ export fn bar() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:41: error: unable to resolve comptime value
|
||||
// :4:41: note: value being casted to 'comptime_int' must be comptime-known
|
||||
// :4:41: note: value casted to 'comptime_int' must be comptime-known
|
||||
// :9:43: error: unable to resolve comptime value
|
||||
// :9:43: note: value being casted to 'comptime_float' must be comptime-known
|
||||
// :9:43: note: value casted to 'comptime_float' must be comptime-known
|
||||
|
||||
@ -13,9 +13,8 @@ export fn entry() usize {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:24: error: unable to evaluate comptime expression
|
||||
// :6:5: note: operation is runtime due to this operand
|
||||
// :4:17: note: called from here
|
||||
// :4:17: note: called at comptime from here
|
||||
// :4:17: note: initializer of container-level variable must be comptime-known
|
||||
|
||||
@ -23,4 +23,5 @@ export fn function_with_return_type_type() void {
|
||||
//
|
||||
// :3:7: error: unable to evaluate comptime expression
|
||||
// :3:5: note: operation is runtime due to this operand
|
||||
// :16:19: note: called from here
|
||||
// :16:19: note: called at comptime from here
|
||||
// :16:19: note: types must be comptime-known
|
||||
|
||||
@ -9,10 +9,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:11: error: unable to resolve comptime value
|
||||
// :8:11: note: argument to function being called at comptime must be comptime-known
|
||||
// :1:20: note: expression is evaluated at comptime because the function returns a comptime-only type 'type'
|
||||
// :1:20: note: function with comptime-only return type 'type' is evaluated at comptime
|
||||
// :1:20: note: types are not available at runtime
|
||||
|
||||
@ -15,5 +15,5 @@ export fn entry() usize {
|
||||
// target=native
|
||||
//
|
||||
// :6:12: error: unable to resolve comptime value
|
||||
// :6:12: note: value being returned at comptime must be comptime-known
|
||||
// :2:12: note: called from here
|
||||
// :2:12: note: called at comptime from here
|
||||
// :1:13: note: struct fields must be comptime-known
|
||||
|
||||
@ -10,8 +10,8 @@ export fn f() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:23: error: unable to resolve comptime value
|
||||
// :7:23: note: initializer of comptime only struct must be comptime-known
|
||||
// :7:23: note: initializer of comptime-only struct 'tmp.Foo' must be comptime-known
|
||||
// :3:10: note: struct requires comptime because of this field
|
||||
// :3:10: note: types are not available at runtime
|
||||
|
||||
@ -10,8 +10,8 @@ export fn f() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:23: error: unable to resolve comptime value
|
||||
// :8:23: note: initializer of comptime only union must be comptime-known
|
||||
// :8:23: note: initializer of comptime-only union 'tmp.Foo' must be comptime-known
|
||||
// :3:10: note: union requires comptime because of this field
|
||||
// :3:10: note: types are not available at runtime
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
export fn entry1() void {
|
||||
foo();
|
||||
}
|
||||
|
||||
comptime {
|
||||
qux();
|
||||
}
|
||||
|
||||
inline fn foo() void {
|
||||
_ = bar();
|
||||
}
|
||||
|
||||
fn bar() type {
|
||||
qux();
|
||||
return u8;
|
||||
}
|
||||
|
||||
fn qux() void {
|
||||
rt = 123;
|
||||
}
|
||||
|
||||
var rt: u32 = undefined;
|
||||
|
||||
// error
|
||||
//
|
||||
// :19:8: error: unable to evaluate comptime expression
|
||||
// :19:5: note: operation is runtime due to this operand
|
||||
// :14:8: note: called at comptime from here
|
||||
// :10:12: note: called at comptime from here
|
||||
// :13:10: note: function with comptime-only return type 'type' is evaluated at comptime
|
||||
// :13:10: note: types are not available at runtime
|
||||
// :2:8: note: called from here
|
||||
// :19:8: error: unable to evaluate comptime expression
|
||||
// :19:5: note: operation is runtime due to this operand
|
||||
// :6:8: note: called at comptime from here
|
||||
// :5:1: note: 'comptime' keyword forces comptime evaluation
|
||||
@ -26,10 +26,10 @@ pub export fn entry4() void {
|
||||
// target=native
|
||||
//
|
||||
// :4:27: error: unable to resolve comptime value
|
||||
// :4:27: note: value being casted to 'comptime_int' must be comptime-known
|
||||
// :4:27: note: value casted to 'comptime_int' must be comptime-known
|
||||
// :9:29: error: unable to resolve comptime value
|
||||
// :9:29: note: value being casted to 'comptime_float' must be comptime-known
|
||||
// :9:29: note: value casted to 'comptime_float' must be comptime-known
|
||||
// :15:10: error: unable to resolve comptime value
|
||||
// :15:10: note: value being casted to 'comptime_float' must be comptime-known
|
||||
// :15:10: note: value casted to 'comptime_float' must be comptime-known
|
||||
// :21:10: error: unable to resolve comptime value
|
||||
// :21:10: note: value being casted to 'comptime_int' must be comptime-known
|
||||
// :21:10: note: value casted to 'comptime_int' must be comptime-known
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
var rt_val: [5]u32 = .{ 1, 2, 3, 4, 5 };
|
||||
|
||||
comptime {
|
||||
_ = rt_val; // fine
|
||||
}
|
||||
|
||||
comptime {
|
||||
const a = rt_val; // error
|
||||
_ = a;
|
||||
}
|
||||
|
||||
comptime {
|
||||
const l = rt_val.len; // fine
|
||||
@compileLog(l);
|
||||
}
|
||||
|
||||
export fn foo() void {
|
||||
_ = comptime rt_val; // error
|
||||
}
|
||||
|
||||
export fn bar() void {
|
||||
const l = comptime rt_val.len; // fine
|
||||
@compileLog(l);
|
||||
}
|
||||
|
||||
export fn baz() void {
|
||||
const S = struct {
|
||||
fn inner() void {
|
||||
_ = comptime rt_val;
|
||||
}
|
||||
};
|
||||
comptime S.inner(); // fine; inner comptime is a nop
|
||||
S.inner(); // error
|
||||
}
|
||||
|
||||
export fn qux() void {
|
||||
const S = struct {
|
||||
fn inner() void {
|
||||
const a = rt_val;
|
||||
_ = a;
|
||||
}
|
||||
};
|
||||
S.inner(); // fine; everything is runtime
|
||||
comptime S.inner(); // error
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :8:15: error: unable to resolve comptime value
|
||||
// :7:1: note: 'comptime' keyword forces comptime evaluation
|
||||
// :18:9: error: unable to resolve comptime value
|
||||
// :18:9: note: 'comptime' keyword forces comptime evaluation
|
||||
// :29:17: error: unable to resolve comptime value
|
||||
// :29:17: note: 'comptime' keyword forces comptime evaluation
|
||||
// :39:23: error: unable to resolve comptime value
|
||||
// :44:21: note: called at comptime from here
|
||||
// :44:5: note: 'comptime' keyword forces comptime evaluation
|
||||
//
|
||||
// Compile Log Output:
|
||||
// @as(usize, 5)
|
||||
// @as(usize, 5)
|
||||
@ -31,13 +31,13 @@ export fn entry2() void {
|
||||
|
||||
// error
|
||||
//
|
||||
// :5:12: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
|
||||
// :9:13: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
|
||||
// :5:12: error: slice of single-item pointer must be bounded
|
||||
// :9:13: error: slice of single-item pointer must have bounds [0..0], [0..1], or [1..1]
|
||||
// :9:13: note: expected '0', found '1'
|
||||
// :13:16: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
|
||||
// :13:16: error: slice of single-item pointer must have bounds [0..0], [0..1], or [1..1]
|
||||
// :13:16: note: expected '1', found '2'
|
||||
// :17:16: error: end index 2 out of bounds for slice of single-item pointer
|
||||
// :23:13: error: unable to resolve comptime value
|
||||
// :23:13: note: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
|
||||
// :23:13: note: slice of single-item pointer must have comptime-known bounds
|
||||
// :29:16: error: unable to resolve comptime value
|
||||
// :29:16: note: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
|
||||
// :29:16: note: slice of single-item pointer must have comptime-known bounds
|
||||
|
||||
@ -33,12 +33,13 @@ pub export fn entry3() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:13: error: unable to evaluate comptime expression
|
||||
// :7:16: note: operation is runtime due to this operand
|
||||
// :7:13: note: initializer of container-level variable must be comptime-known
|
||||
// :13:13: error: unable to evaluate comptime expression
|
||||
// :13:16: note: operation is runtime due to this operand
|
||||
// :13:13: note: initializer of container-level variable must be comptime-known
|
||||
// :22:9: error: unable to evaluate comptime expression
|
||||
// :22:21: note: operation is runtime due to this operand
|
||||
// :21:13: note: enum fields must be comptime-known
|
||||
|
||||
@ -12,4 +12,4 @@ export fn entry() void {
|
||||
//
|
||||
// :2:11: error: unable to evaluate comptime expression
|
||||
// :2:13: note: operation is runtime due to this operand
|
||||
// :1:11: note: expression is evaluated at comptime because it is inside a @cImport
|
||||
// :1:11: note: operand to '@cImport' is evaluated at comptime
|
||||
|
||||
@ -57,8 +57,8 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
":3:12: error: unable to resolve comptime value",
|
||||
":3:12: note: argument to function being called at comptime must be comptime-known",
|
||||
":2:55: note: expression is evaluated at comptime because the generic function was instantiated with a comptime-only return type",
|
||||
":2:55: note: generic function instantiated with comptime-only return type '?fn () void' is evaluated at comptime",
|
||||
":2:55: note: use '*const fn () void' for a function pointer type",
|
||||
});
|
||||
case.addSourceFile("b.zig",
|
||||
\\pub const ElfDynLib = struct {
|
||||
@ -198,7 +198,9 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
|
||||
":8:36: error: runtime-known argument passed to comptime parameter",
|
||||
":2:41: note: declared comptime here",
|
||||
":13:32: error: unable to resolve comptime value",
|
||||
":13:32: note: initializer of comptime only struct must be comptime-known",
|
||||
":13:32: note: initializer of comptime-only struct 'tmp.callAnytypeFunctionWithRuntimeComptimeOnlyType.S' must be comptime-known",
|
||||
":12:35: note: struct requires comptime because of this field",
|
||||
":12:35: note: types are not available at runtime",
|
||||
});
|
||||
|
||||
case.addSourceFile("import.zig",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user