mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 03:25:01 +00:00
Sema: add source location to coerce result ptr, fix negation error
This commit is contained in:
parent
979910dc38
commit
cc3336c784
@ -1476,7 +1476,7 @@ fn arrayInitExprRlPtr(
|
||||
return arrayInitExprRlPtrInner(gz, scope, node, base_ptr, elements);
|
||||
}
|
||||
|
||||
var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr);
|
||||
var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr, node);
|
||||
defer as_scope.unstack();
|
||||
|
||||
const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);
|
||||
@ -1697,7 +1697,7 @@ fn structInitExprRlPtr(
|
||||
const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
|
||||
_ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
|
||||
|
||||
var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr);
|
||||
var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr, node);
|
||||
defer as_scope.unstack();
|
||||
|
||||
const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);
|
||||
@ -7046,7 +7046,7 @@ fn asRlPtr(
|
||||
operand_node: Ast.Node.Index,
|
||||
dest_type: Zir.Inst.Ref,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr);
|
||||
var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node);
|
||||
defer as_scope.unstack();
|
||||
|
||||
const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);
|
||||
@ -9903,13 +9903,14 @@ const GenZir = struct {
|
||||
scope: *Scope,
|
||||
dest_type: Zir.Inst.Ref,
|
||||
result_ptr: Zir.Inst.Ref,
|
||||
src_node: Ast.Node.Index,
|
||||
) !GenZir {
|
||||
// Detect whether this expr() call goes into rvalue() to store the result into the
|
||||
// result location. If it does, elide the coerce_result_ptr instruction
|
||||
// as well as the store instruction, instead passing the result as an rvalue.
|
||||
var as_scope = parent_gz.makeSubBlock(scope);
|
||||
errdefer as_scope.unstack();
|
||||
as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
|
||||
as_scope.rl_ptr = try as_scope.addPlNode(.coerce_result_ptr, src_node, Zir.Inst.Bin{ .lhs = dest_type, .rhs = result_ptr });
|
||||
|
||||
// `rl_ty_inst` needs to be set in case the stores to `rl_ptr` are eliminated.
|
||||
as_scope.rl_ty_inst = dest_type;
|
||||
|
||||
43
src/Sema.zig
43
src/Sema.zig
@ -1913,10 +1913,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const src: LazySrcLoc = sema.src;
|
||||
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
|
||||
const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
|
||||
const ptr = try sema.resolveInst(bin_inst.rhs);
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const pointee_ty = try sema.resolveType(block, src, extra.lhs);
|
||||
const ptr = try sema.resolveInst(extra.rhs);
|
||||
const target = sema.mod.getTarget();
|
||||
const addr_space = target_util.defaultAddressSpace(target, .local);
|
||||
|
||||
@ -10143,7 +10144,10 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||
const rhs_ty = sema.typeOf(rhs);
|
||||
const rhs_scalar_ty = rhs_ty.scalarType();
|
||||
|
||||
if (rhs_scalar_ty.isUnsignedInt()) {
|
||||
if (rhs_scalar_ty.isUnsignedInt() or switch (rhs_scalar_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt, .Float, .ComptimeFloat => false,
|
||||
else => true,
|
||||
}) {
|
||||
return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)});
|
||||
}
|
||||
|
||||
@ -10172,6 +10176,12 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||
|
||||
const rhs = try sema.resolveInst(inst_data.operand);
|
||||
const rhs_ty = sema.typeOf(rhs);
|
||||
const rhs_scalar_ty = rhs_ty.scalarType();
|
||||
|
||||
switch (rhs_scalar_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt, .Float, .ComptimeFloat => {},
|
||||
else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),
|
||||
}
|
||||
|
||||
const lhs = if (rhs_ty.zigTypeTag() == .Vector)
|
||||
try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
|
||||
@ -17886,7 +17896,8 @@ fn validateRunTimeType(
|
||||
.Pointer => {
|
||||
const elem_ty = ty.childType();
|
||||
switch (elem_ty.zigTypeTag()) {
|
||||
.Opaque, .Fn => return true,
|
||||
.Opaque => return true,
|
||||
.Fn => return elem_ty.isFnOrHasRuntimeBits(),
|
||||
else => ty = elem_ty,
|
||||
}
|
||||
},
|
||||
@ -17950,7 +17961,25 @@ fn explainWhyTypeIsComptime(
|
||||
.Optional,
|
||||
=> return,
|
||||
|
||||
.Pointer, .Array, .Vector => {
|
||||
.Array, .Vector => {
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
|
||||
},
|
||||
.Pointer => {
|
||||
const elem_ty = ty.elemType2();
|
||||
if (elem_ty.zigTypeTag() == .Fn) {
|
||||
const fn_info = elem_ty.fnInfo();
|
||||
if (fn_info.is_generic) {
|
||||
try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});
|
||||
}
|
||||
switch (fn_info.cc) {
|
||||
.Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),
|
||||
else => {},
|
||||
}
|
||||
if (fn_info.return_type.comptimeOnly()) {
|
||||
try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});
|
||||
}
|
||||
return;
|
||||
}
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
|
||||
},
|
||||
|
||||
|
||||
@ -308,7 +308,7 @@ pub const Inst = struct {
|
||||
cmp_neq,
|
||||
/// Coerces a result location pointer to a new element type. It is evaluated "backwards"-
|
||||
/// as type coercion from the new element type to the old element type.
|
||||
/// Uses the `bin` union field.
|
||||
/// Uses the `pl_node` union field. Payload is `Bin`.
|
||||
/// LHS is destination element type, RHS is result pointer.
|
||||
coerce_result_ptr,
|
||||
/// Conditional branch. Splits control flow based on a boolean condition value.
|
||||
@ -1603,7 +1603,7 @@ pub const Inst = struct {
|
||||
.cmp_gte = .pl_node,
|
||||
.cmp_gt = .pl_node,
|
||||
.cmp_neq = .pl_node,
|
||||
.coerce_result_ptr = .bin,
|
||||
.coerce_result_ptr = .pl_node,
|
||||
.condbr = .pl_node,
|
||||
.condbr_inline = .pl_node,
|
||||
.@"try" = .pl_node,
|
||||
|
||||
@ -144,7 +144,6 @@ const Writer = struct {
|
||||
switch (tag) {
|
||||
.array_type,
|
||||
.as,
|
||||
.coerce_result_ptr,
|
||||
.elem_ptr,
|
||||
.elem_val,
|
||||
.store,
|
||||
@ -355,6 +354,7 @@ const Writer = struct {
|
||||
.minimum,
|
||||
.elem_ptr_node,
|
||||
.elem_val_node,
|
||||
.coerce_result_ptr,
|
||||
=> try self.writePlNodeBin(stream, inst),
|
||||
|
||||
.elem_ptr_imm => try self.writeElemPtrImm(stream, inst),
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
export fn entry() void {
|
||||
var a = &b;
|
||||
_ = a;
|
||||
}
|
||||
fn b() callconv(.Inline) void { }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:9: error: variable of type '*const fn() callconv(.Inline) void' must be const or comptime
|
||||
// :2:9: note: function has inline calling convention
|
||||
@ -8,7 +8,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:15: error: negation of type 'anyerror!u32'
|
||||
// :6:15: error: negation of type 'anyerror!u32'
|
||||
@ -6,8 +6,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:2:15: error: cannot assign to constant
|
||||
// :2:15: error: cannot assign to constant
|
||||
@ -9,8 +9,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:5:10: error: cannot assign to constant
|
||||
// :5:10: error: cannot assign to constant
|
||||
@ -1,12 +0,0 @@
|
||||
export fn entry() void {
|
||||
var a = b;
|
||||
_ = a;
|
||||
}
|
||||
fn b() callconv(.Inline) void { }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:5: error: functions marked inline must be stored in const or comptime var
|
||||
// tmp.zig:5:1: note: declared here
|
||||
Loading…
x
Reference in New Issue
Block a user