authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-12 16:03:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-13 05:59:25-04:00
logdd75e7bcb1fe142f4d60dc2d83e6feee53e580f3
tree86c19b62a998de0a7f110c28df4b7a523552c29b
parentdcdb4422b801f2d184107fdd7b9493f7840a0244

Sema: add missing error and test for bool not on vector of ints


3 files changed, 63 insertions(+), 31 deletions(-)

src/Sema.zig+52-30
...@@ -1171,11 +1171,11 @@ fn analyzeBodyInner(...@@ -1171,11 +1171,11 @@ fn analyzeBodyInner(
1171 .as_node => try sema.zirAsNode(block, inst),1171 .as_node => try sema.zirAsNode(block, inst),
1172 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),1172 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),
1173 .bit_and => try sema.zirBitwise(block, inst, .bit_and),1173 .bit_and => try sema.zirBitwise(block, inst, .bit_and),
1174 .bit_not => try sema.zirBitNot(block, inst, false),1174 .bit_not => try sema.zirBitNot(block, inst),
1175 .bit_or => try sema.zirBitwise(block, inst, .bit_or),1175 .bit_or => try sema.zirBitwise(block, inst, .bit_or),
1176 .bitcast => try sema.zirBitcast(block, inst),1176 .bitcast => try sema.zirBitcast(block, inst),
1177 .suspend_block => try sema.zirSuspendBlock(block, inst),1177 .suspend_block => try sema.zirSuspendBlock(block, inst),
1178 .bool_not => try sema.zirBitNot(block, inst, true),1178 .bool_not => try sema.zirBoolNot(block, inst),
1179 .bool_br_and => try sema.zirBoolBr(block, inst, false),1179 .bool_br_and => try sema.zirBoolBr(block, inst, false),
1180 .bool_br_or => try sema.zirBoolBr(block, inst, true),1180 .bool_br_or => try sema.zirBoolBr(block, inst, true),
1181 .c_import => try sema.zirCImport(block, inst),1181 .c_import => try sema.zirCImport(block, inst),
...@@ -14464,57 +14464,55 @@ fn zirBitwise(...@@ -14464,57 +14464,55 @@ fn zirBitwise(
14464 return block.addBinOp(air_tag, casted_lhs, casted_rhs);14464 return block.addBinOp(air_tag, casted_lhs, casted_rhs);
14465}14465}
1446614466
14467fn zirBitNot(14467fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14468 sema: *Sema,
14469 block: *Block,
14470 inst: Zir.Inst.Index,
14471 is_bool_not: bool,
14472) CompileError!Air.Inst.Ref {
14473 const tracy = trace(@src());
14474 defer tracy.end();
14475
14476 const pt = sema.pt;14468 const pt = sema.pt;
14477 const zcu = pt.zcu;14469 const zcu = pt.zcu;
14478 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;14470 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
14479 const src = block.nodeOffset(inst_data.src_node);
14480 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });14471 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
1448114472 const src = block.nodeOffset(inst_data.src_node);
14482 const operand = try sema.resolveInst(inst_data.operand);14473 const operand = try sema.resolveInst(inst_data.operand);
14483 const operand_type = sema.typeOf(operand);14474 const operand_ty = sema.typeOf(operand);
14484 const scalar_type = operand_type.scalarType(zcu);14475 const scalar_ty = operand_ty.scalarType(zcu);
14485 const scalar_tag = scalar_type.zigTypeTag(zcu);14476 const scalar_tag = scalar_ty.zigTypeTag(zcu);
1448614477
14487 const is_finite_int_or_bool = scalar_tag == .int or scalar_tag == .bool;14478 if (scalar_tag != .int and scalar_tag != .bool)
14488 const is_allowed_type = if (is_bool_not) scalar_tag == .bool else is_finite_int_or_bool;14479 return sema.fail(block, operand_src, "bitwise not operation on type '{}'", .{operand_ty.fmt(pt)});
1448914480
14490 if (!is_allowed_type) {14481 return analyzeBitNot(sema, block, operand, src);
14491 return sema.fail(block, src, "unable to perform {s} not operation on type '{}'", .{14482}
14492 if (is_bool_not) "boolean" else "binary", operand_type.fmt(pt),
14493 });
14494 }
1449514483
14484fn analyzeBitNot(
14485 sema: *Sema,
14486 block: *Block,
14487 operand: Air.Inst.Ref,
14488 src: LazySrcLoc,
14489) CompileError!Air.Inst.Ref {
14490 const pt = sema.pt;
14491 const zcu = pt.zcu;
14492 const operand_ty = sema.typeOf(operand);
14493 const scalar_ty = operand_ty.scalarType(zcu);
14496 if (try sema.resolveValue(operand)) |val| {14494 if (try sema.resolveValue(operand)) |val| {
14497 if (val.isUndef(zcu)) {14495 if (val.isUndef(zcu)) {
14498 return pt.undefRef(operand_type);14496 return pt.undefRef(operand_ty);
14499 } else if (operand_type.zigTypeTag(zcu) == .vector) {14497 } else if (operand_ty.zigTypeTag(zcu) == .vector) {
14500 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen(zcu));14498 const vec_len = try sema.usizeCast(block, src, operand_ty.vectorLen(zcu));
14501 const elems = try sema.arena.alloc(InternPool.Index, vec_len);14499 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
14502 for (elems, 0..) |*elem, i| {14500 for (elems, 0..) |*elem, i| {
14503 const elem_val = try val.elemValue(pt, i);14501 const elem_val = try val.elemValue(pt, i);
14504 elem.* = (try elem_val.bitwiseNot(scalar_type, sema.arena, pt)).toIntern();14502 elem.* = (try elem_val.bitwiseNot(scalar_ty, sema.arena, pt)).toIntern();
14505 }14503 }
14506 return Air.internedToRef((try pt.intern(.{ .aggregate = .{14504 return Air.internedToRef((try pt.intern(.{ .aggregate = .{
14507 .ty = operand_type.toIntern(),14505 .ty = operand_ty.toIntern(),
14508 .storage = .{ .elems = elems },14506 .storage = .{ .elems = elems },
14509 } })));14507 } })));
14510 } else {14508 } else {
14511 const result_val = try val.bitwiseNot(operand_type, sema.arena, pt);14509 const result_val = try val.bitwiseNot(operand_ty, sema.arena, pt);
14512 return Air.internedToRef(result_val.toIntern());14510 return Air.internedToRef(result_val.toIntern());
14513 }14511 }
14514 }14512 }
1451514513
14516 try sema.requireRuntimeBlock(block, src, null);14514 try sema.requireRuntimeBlock(block, src, null);
14517 return block.addTyOp(.not, operand_type, operand);14515 return block.addTyOp(.not, operand_ty, operand);
14518}14516}
1451914517
14520fn analyzeTupleCat(14518fn analyzeTupleCat(
...@@ -18367,6 +18365,30 @@ fn zirTypeofPeer(...@@ -18367,6 +18365,30 @@ fn zirTypeofPeer(
18367 return Air.internedToRef(result_type.toIntern());18365 return Air.internedToRef(result_type.toIntern());
18368}18366}
1836918367
18368fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18369 const pt = sema.pt;
18370 const zcu = pt.zcu;
18371 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
18372 const src = block.nodeOffset(inst_data.src_node);
18373 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
18374 const uncasted_operand = try sema.resolveInst(inst_data.operand);
18375 const uncasted_ty = sema.typeOf(uncasted_operand);
18376 if (uncasted_ty.isVector(zcu)) {
18377 if (uncasted_ty.scalarType(zcu).zigTypeTag(zcu) != .bool) {
18378 return sema.fail(block, operand_src, "boolean not operation on type '{}'", .{
18379 uncasted_ty.fmt(pt),
18380 });
18381 }
18382 return analyzeBitNot(sema, block, uncasted_operand, src);
18383 }
18384 const operand = try sema.coerce(block, .bool, uncasted_operand, operand_src);
18385 if (try sema.resolveValue(operand)) |val| {
18386 return if (val.isUndef(zcu)) .undef_bool else if (val.toBool()) .bool_false else .bool_true;
18387 }
18388 try sema.requireRuntimeBlock(block, src, null);
18389 return block.addTyOp(.not, .bool, operand);
18390}
18391
18370fn zirBoolBr(18392fn zirBoolBr(
18371 sema: *Sema,18393 sema: *Sema,
18372 parent_block: *Block,18394 parent_block: *Block,
test/cases/compile_errors/binary_not_on_number_literal.zig+1-1
...@@ -10,4 +10,4 @@ export fn entry() usize {...@@ -10,4 +10,4 @@ export fn entry() usize {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :3:60: error: unable to perform binary not operation on type 'comptime_int'13// :3:61: error: bitwise not operation on type 'comptime_int'
test/cases/compile_errors/bool_not_on_vector_of_ints.zig created+10
...@@ -0,0 +1,10 @@
1export fn foo() void {
2 var x: @Vector(2, u1) = .{ 0, 1 };
3 x = !x;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:10: error: boolean not operation on type '@Vector(2, u1)'