mirror of
https://github.com/ziglang/zig.git
synced 2024-12-13 06:37:30 +00:00
Sema: further enhance explanation of why expr is evaluated at comptime
This commit is contained in:
parent
c389f8800b
commit
c3b85e4e2f
185
src/Sema.zig
185
src/Sema.zig
@ -151,6 +151,8 @@ pub const Block = struct {
|
||||
runtime_index: Value.RuntimeIndex = .zero,
|
||||
inline_block: Zir.Inst.Index = 0,
|
||||
|
||||
comptime_reason: ?*const ComptimeReason = null,
|
||||
// TODO is_comptime and comptime_reason should probably be merged together.
|
||||
is_comptime: bool,
|
||||
is_typeof: bool = false,
|
||||
is_coerce_result_ptr: bool = false,
|
||||
@ -173,6 +175,49 @@ pub const Block = struct {
|
||||
/// Value for switch_capture in an inline case
|
||||
inline_case_capture: Air.Inst.Ref = .none,
|
||||
|
||||
const ComptimeReason = union(enum) {
|
||||
c_import: struct {
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
},
|
||||
comptime_ret_ty: struct {
|
||||
block: *Block,
|
||||
func: Air.Inst.Ref,
|
||||
func_src: LazySrcLoc,
|
||||
return_ty: Type,
|
||||
},
|
||||
|
||||
fn explain(cr: ComptimeReason, sema: *Sema, msg: ?*Module.ErrorMsg) !void {
|
||||
const parent = msg orelse return;
|
||||
const prefix = "expression is evaluated at comptime because ";
|
||||
switch (cr) {
|
||||
.c_import => |ci| {
|
||||
try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{});
|
||||
},
|
||||
.comptime_ret_ty => |rt| {
|
||||
const src_loc = if (try sema.funcDeclSrc(rt.block, rt.func_src, rt.func)) |capture| blk: {
|
||||
var src_loc = capture;
|
||||
src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };
|
||||
break :blk src_loc;
|
||||
} else blk: {
|
||||
const src_decl = sema.mod.declPtr(rt.block.src_decl);
|
||||
break :blk rt.func_src.toSrcLoc(src_decl);
|
||||
};
|
||||
if (rt.return_ty.tag() == .generic_poison) {
|
||||
return sema.mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});
|
||||
}
|
||||
try sema.mod.errNoteNonLazy(
|
||||
src_loc,
|
||||
parent,
|
||||
prefix ++ "the function returns a comptime-only type '{}'",
|
||||
.{rt.return_ty.fmt(sema.mod)},
|
||||
);
|
||||
try sema.explainWhyTypeIsComptime(rt.block, rt.func_src, parent, src_loc, rt.return_ty);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Param = struct {
|
||||
/// `noreturn` means `anytype`.
|
||||
ty: Type,
|
||||
@ -224,6 +269,7 @@ pub const Block = struct {
|
||||
.label = null,
|
||||
.inlining = parent.inlining,
|
||||
.is_comptime = parent.is_comptime,
|
||||
.comptime_reason = parent.comptime_reason,
|
||||
.is_typeof = parent.is_typeof,
|
||||
.runtime_cond = parent.runtime_cond,
|
||||
.runtime_loop = parent.runtime_loop,
|
||||
@ -1420,7 +1466,10 @@ fn analyzeBodyInner(
|
||||
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
|
||||
const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];
|
||||
const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
|
||||
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime-known");
|
||||
const cond = sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
const inline_body = if (cond.val.toBool()) then_body else else_body;
|
||||
|
||||
try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
|
||||
@ -1438,7 +1487,10 @@ fn analyzeBodyInner(
|
||||
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
|
||||
const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];
|
||||
const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
|
||||
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime-known");
|
||||
const cond = sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
const inline_body = if (cond.val.toBool()) then_body else else_body;
|
||||
const old_runtime_index = block.runtime_index;
|
||||
defer block.runtime_index = old_runtime_index;
|
||||
@ -1460,7 +1512,10 @@ fn analyzeBodyInner(
|
||||
const err_union = try sema.resolveInst(extra.data.operand);
|
||||
const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
|
||||
assert(is_non_err != .none);
|
||||
const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known");
|
||||
const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
if (is_non_err_tv.val.toBool()) {
|
||||
const err_union_ty = sema.typeOf(err_union);
|
||||
break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
|
||||
@ -1516,7 +1571,10 @@ fn analyzeBodyInner(
|
||||
const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
|
||||
const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
|
||||
assert(is_non_err != .none);
|
||||
const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known");
|
||||
const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
if (is_non_err_tv.val.toBool()) {
|
||||
break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
}
|
||||
@ -1675,8 +1733,8 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!block.is_comptime);
|
||||
var err_trace_block = block.makeSubBlock();
|
||||
err_trace_block.is_comptime = false;
|
||||
defer err_trace_block.instructions.deinit(sema.gpa);
|
||||
|
||||
const src: LazySrcLoc = .unneeded;
|
||||
@ -4944,6 +5002,10 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
var c_import_buf = std.ArrayList(u8).init(sema.gpa);
|
||||
defer c_import_buf.deinit();
|
||||
|
||||
var comptime_reason = .{ .c_import = .{
|
||||
.block = parent_block,
|
||||
.src = src,
|
||||
} };
|
||||
var child_block: Block = .{
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
@ -4952,7 +5014,8 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
.wip_capture_scope = parent_block.wip_capture_scope,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.is_comptime = true,
|
||||
.comptime_reason = &comptime_reason,
|
||||
.c_import_buf = &c_import_buf,
|
||||
.runtime_cond = parent_block.runtime_cond,
|
||||
.runtime_loop = parent_block.runtime_loop,
|
||||
@ -5053,6 +5116,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
.label = &label,
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.comptime_reason = parent_block.comptime_reason,
|
||||
.is_typeof = parent_block.is_typeof,
|
||||
.want_safety = parent_block.want_safety,
|
||||
.float_mode = parent_block.float_mode,
|
||||
@ -5926,6 +5990,7 @@ fn zirCall(
|
||||
defer block.is_comptime = parent_comptime;
|
||||
if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
|
||||
block.is_comptime = true;
|
||||
// TODO set comptime_reason
|
||||
}
|
||||
|
||||
const param_ty_inst = try sema.addType(param_ty);
|
||||
@ -6056,37 +6121,6 @@ const GenericCallAdapter = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn addComptimeReturnTypeNote(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
func: Air.Inst.Ref,
|
||||
func_src: LazySrcLoc,
|
||||
return_ty: Type,
|
||||
parent: *Module.ErrorMsg,
|
||||
requires_comptime: bool,
|
||||
) !void {
|
||||
if (!requires_comptime) return;
|
||||
|
||||
const src_loc = if (try sema.funcDeclSrc(block, func_src, func)) |capture| blk: {
|
||||
var src_loc = capture;
|
||||
src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };
|
||||
break :blk src_loc;
|
||||
} else blk: {
|
||||
const src_decl = sema.mod.declPtr(block.src_decl);
|
||||
break :blk func_src.toSrcLoc(src_decl);
|
||||
};
|
||||
if (return_ty.tag() == .generic_poison) {
|
||||
return sema.mod.errNoteNonLazy(src_loc, parent, "generic function is instantiated with a comptime-only return type", .{});
|
||||
}
|
||||
try sema.mod.errNoteNonLazy(
|
||||
src_loc,
|
||||
parent,
|
||||
"function is being called at comptime because it returns a comptime-only type '{}'",
|
||||
.{return_ty.fmt(sema.mod)},
|
||||
);
|
||||
try sema.explainWhyTypeIsComptime(block, func_src, parent, src_loc, return_ty);
|
||||
}
|
||||
|
||||
fn analyzeCall(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@ -6177,11 +6211,21 @@ fn analyzeCall(
|
||||
|
||||
var is_generic_call = func_ty_info.is_generic;
|
||||
var is_comptime_call = block.is_comptime or modifier == .compile_time;
|
||||
var comptime_only_ret_ty = false;
|
||||
var comptime_reason_buf: Block.ComptimeReason = undefined;
|
||||
var comptime_reason: ?*const Block.ComptimeReason = null;
|
||||
if (!is_comptime_call) {
|
||||
if (sema.typeRequiresComptime(func_ty_info.return_type)) |ct| {
|
||||
is_comptime_call = ct;
|
||||
comptime_only_ret_ty = ct;
|
||||
if (ct) {
|
||||
// stage1 can't handle doing this directly
|
||||
comptime_reason_buf = .{ .comptime_ret_ty = .{
|
||||
.block = block,
|
||||
.func = func,
|
||||
.func_src = func_src,
|
||||
.return_ty = func_ty_info.return_type,
|
||||
} };
|
||||
comptime_reason = &comptime_reason_buf;
|
||||
}
|
||||
} else |err| switch (err) {
|
||||
error.GenericPoison => is_generic_call = true,
|
||||
else => |e| return e,
|
||||
@ -6210,7 +6254,14 @@ fn analyzeCall(
|
||||
error.ComptimeReturn => {
|
||||
is_inline_call = true;
|
||||
is_comptime_call = true;
|
||||
comptime_only_ret_ty = true;
|
||||
// stage1 can't handle doing this directly
|
||||
comptime_reason_buf = .{ .comptime_ret_ty = .{
|
||||
.block = block,
|
||||
.func = func,
|
||||
.func_src = func_src,
|
||||
.return_ty = func_ty_info.return_type,
|
||||
} };
|
||||
comptime_reason = &comptime_reason_buf;
|
||||
},
|
||||
else => |e| return e,
|
||||
}
|
||||
@ -6222,9 +6273,7 @@ fn analyzeCall(
|
||||
|
||||
const result: Air.Inst.Ref = if (is_inline_call) res: {
|
||||
const func_val = sema.resolveConstValue(block, func_src, func, "function being called at comptime must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(block, func, func_src, func_ty_info.return_type, sema.err.?, comptime_only_ret_ty);
|
||||
}
|
||||
if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
const module_fn = switch (func_val.tag()) {
|
||||
@ -6292,6 +6341,7 @@ fn analyzeCall(
|
||||
.label = null,
|
||||
.inlining = &inlining,
|
||||
.is_comptime = is_comptime_call,
|
||||
.comptime_reason = comptime_reason,
|
||||
.error_return_trace_index = block.error_return_trace_index,
|
||||
};
|
||||
|
||||
@ -6344,11 +6394,6 @@ fn analyzeCall(
|
||||
is_comptime_call,
|
||||
&should_memoize,
|
||||
memoized_call_key,
|
||||
// last 4 arguments are only used when reporting errors
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
) catch |err| switch (err) {
|
||||
error.NeededSourceLocation => {
|
||||
_ = sema.inst_map.remove(inst);
|
||||
@ -6364,10 +6409,6 @@ fn analyzeCall(
|
||||
is_comptime_call,
|
||||
&should_memoize,
|
||||
memoized_call_key,
|
||||
func,
|
||||
func_src,
|
||||
func_ty_info.return_type,
|
||||
comptime_only_ret_ty,
|
||||
);
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
@ -6604,10 +6645,6 @@ fn analyzeInlineCallArg(
|
||||
is_comptime_call: bool,
|
||||
should_memoize: *bool,
|
||||
memoized_call_key: Module.MemoizedCall.Key,
|
||||
func: Air.Inst.Ref,
|
||||
func_src: LazySrcLoc,
|
||||
ret_ty: Type,
|
||||
comptime_only_ret_ty: bool,
|
||||
) !void {
|
||||
const zir_tags = sema.code.instructions.items(.tag);
|
||||
switch (zir_tags[inst]) {
|
||||
@ -6624,9 +6661,7 @@ fn analyzeInlineCallArg(
|
||||
const uncasted_arg = uncasted_args[arg_i.*];
|
||||
if (try sema.typeRequiresComptime(param_ty)) {
|
||||
_ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
|
||||
}
|
||||
if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
}
|
||||
@ -6635,9 +6670,7 @@ fn analyzeInlineCallArg(
|
||||
if (is_comptime_call) {
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
|
||||
const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
|
||||
}
|
||||
if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
switch (arg_val.tag()) {
|
||||
@ -6679,9 +6712,7 @@ fn analyzeInlineCallArg(
|
||||
if (is_comptime_call) {
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
|
||||
const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
|
||||
}
|
||||
if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
switch (arg_val.tag()) {
|
||||
@ -10223,6 +10254,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
.label = &label,
|
||||
.inlining = block.inlining,
|
||||
.is_comptime = block.is_comptime,
|
||||
.comptime_reason = block.comptime_reason,
|
||||
.is_typeof = block.is_typeof,
|
||||
.switch_else_err_ty = else_error_ty,
|
||||
.runtime_cond = block.runtime_cond,
|
||||
@ -10333,7 +10365,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
if (child_block.is_comptime) {
|
||||
_ = sema.resolveConstValue(&child_block, operand_src, operand, "condition in comptime switch must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and child_block.comptime_reason != null) try child_block.comptime_reason.?.explain(sema, sema.err);
|
||||
return err;
|
||||
};
|
||||
unreachable;
|
||||
}
|
||||
|
||||
const estimated_cases_extra = (scalar_cases_len + multi_cases_len) *
|
||||
@typeInfo(Air.SwitchBr.Case).Struct.fields.len + 2;
|
||||
@ -21469,6 +21507,9 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
|
||||
if (runtime_src) |some| {
|
||||
try sema.errNote(block, some, msg, "operation is runtime due to this operand", .{});
|
||||
}
|
||||
if (block.comptime_reason) |some| {
|
||||
try some.explain(sema, msg);
|
||||
}
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
@ -21940,6 +21981,7 @@ fn addSafetyCheck(
|
||||
panic_id: PanicId,
|
||||
) !void {
|
||||
const gpa = sema.gpa;
|
||||
assert(!parent_block.is_comptime);
|
||||
|
||||
var fail_block: Block = .{
|
||||
.parent = parent_block,
|
||||
@ -21949,7 +21991,7 @@ fn addSafetyCheck(
|
||||
.wip_capture_scope = parent_block.wip_capture_scope,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.is_comptime = false,
|
||||
};
|
||||
|
||||
defer fail_block.instructions.deinit(gpa);
|
||||
@ -22061,6 +22103,7 @@ fn panicUnwrapError(
|
||||
unwrap_err_tag: Air.Inst.Tag,
|
||||
is_non_err_tag: Air.Inst.Tag,
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addUnOp(is_non_err_tag, operand);
|
||||
const gpa = sema.gpa;
|
||||
|
||||
@ -22072,7 +22115,7 @@ fn panicUnwrapError(
|
||||
.wip_capture_scope = parent_block.wip_capture_scope,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.is_comptime = false,
|
||||
};
|
||||
|
||||
defer fail_block.instructions.deinit(gpa);
|
||||
@ -22104,6 +22147,7 @@ fn panicIndexOutOfBounds(
|
||||
len: Air.Inst.Ref,
|
||||
cmp_op: Air.Inst.Tag,
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addBinOp(cmp_op, index, len);
|
||||
const gpa = sema.gpa;
|
||||
|
||||
@ -22115,7 +22159,7 @@ fn panicIndexOutOfBounds(
|
||||
.wip_capture_scope = parent_block.wip_capture_scope,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.is_comptime = false,
|
||||
};
|
||||
|
||||
defer fail_block.instructions.deinit(gpa);
|
||||
@ -22146,6 +22190,7 @@ fn panicSentinelMismatch(
|
||||
ptr: Air.Inst.Ref,
|
||||
sentinel_index: Air.Inst.Ref,
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const expected_sentinel_val = maybe_sentinel orelse return;
|
||||
const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val);
|
||||
|
||||
@ -22186,7 +22231,7 @@ fn panicSentinelMismatch(
|
||||
.wip_capture_scope = parent_block.wip_capture_scope,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.is_comptime = false,
|
||||
};
|
||||
|
||||
defer fail_block.instructions.deinit(gpa);
|
||||
|
@ -0,0 +1,48 @@
|
||||
const S = struct {
|
||||
fnPtr: fn () void,
|
||||
};
|
||||
fn bar() void {}
|
||||
fn baz() void {}
|
||||
var runtime: bool = true;
|
||||
fn ifExpr() S {
|
||||
if (runtime) {
|
||||
return .{
|
||||
.fnPtr = bar,
|
||||
};
|
||||
} else {
|
||||
return .{
|
||||
.fnPtr = baz,
|
||||
};
|
||||
}
|
||||
}
|
||||
pub export fn entry1() void {
|
||||
_ = ifExpr();
|
||||
}
|
||||
fn switchExpr() S {
|
||||
switch (runtime) {
|
||||
true => return .{
|
||||
.fnPtr = bar,
|
||||
},
|
||||
false => return .{
|
||||
.fnPtr = baz,
|
||||
},
|
||||
}
|
||||
}
|
||||
pub export fn entry2() void {
|
||||
_ = switchExpr();
|
||||
}
|
||||
|
||||
// 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'
|
||||
// :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 from here
|
@ -18,6 +18,6 @@ pub export fn entry() void {
|
||||
//
|
||||
// :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: function is being called at comptime because it returns a comptime-only type 'tmp.S'
|
||||
// :7:25: note: expression is evaluated at comptime because the function returns a comptime-only type 'tmp.S'
|
||||
// :2:12: note: struct requires comptime because of this field
|
||||
// :2:12: note: use '*const fn() void' for a function pointer type
|
||||
|
@ -19,4 +19,4 @@ pub export fn entry() void {
|
||||
//
|
||||
// :14:13: error: unable to resolve comptime value
|
||||
// :14:13: note: argument to function being called at comptime must be comptime-known
|
||||
// :9:38: note: generic function is instantiated with a comptime-only return type
|
||||
// :9:38: note: expression is evaluated at comptime because the generic function was instantiated with a comptime-only return type
|
||||
|
@ -0,0 +1,15 @@
|
||||
const c = @cImport({
|
||||
_ = 1 + foo;
|
||||
});
|
||||
extern var foo: i32;
|
||||
export fn entry() void {
|
||||
_ = c;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// :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
|
@ -204,7 +204,7 @@ pub fn addCases(ctx: *TestContext) !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: generic function is instantiated with a comptime-only return type",
|
||||
":2:55: note: expression is evaluated at comptime because the generic function was instantiated with a comptime-only return type",
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user