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(
11711171 .as_node => try sema.zirAsNode(block, inst),
11721172 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),
11731173 .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),
11751175 .bit_or => try sema.zirBitwise(block, inst, .bit_or),
11761176 .bitcast => try sema.zirBitcast(block, inst),
11771177 .suspend_block => try sema.zirSuspendBlock(block, inst),
1178 .bool_not => try sema.zirBitNot(block, inst, true),
1178 .bool_not => try sema.zirBoolNot(block, inst),
11791179 .bool_br_and => try sema.zirBoolBr(block, inst, false),
11801180 .bool_br_or => try sema.zirBoolBr(block, inst, true),
11811181 .c_import => try sema.zirCImport(block, inst),
......@@ -14464,57 +14464,55 @@ fn zirBitwise(
1446414464 return block.addBinOp(air_tag, casted_lhs, casted_rhs);
1446514465}
1446614466
14467fn zirBitNot(
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
14467fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1447614468 const pt = sema.pt;
1447714469 const zcu = pt.zcu;
1447814470 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
14479 const src = block.nodeOffset(inst_data.src_node);
1448014471 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
14481
14472 const src = block.nodeOffset(inst_data.src_node);
1448214473 const operand = try sema.resolveInst(inst_data.operand);
14483 const operand_type = sema.typeOf(operand);
14484 const scalar_type = operand_type.scalarType(zcu);
14485 const scalar_tag = scalar_type.zigTypeTag(zcu);
14474 const operand_ty = sema.typeOf(operand);
14475 const scalar_ty = operand_ty.scalarType(zcu);
14476 const scalar_tag = scalar_ty.zigTypeTag(zcu);
1448614477
14487 const is_finite_int_or_bool = scalar_tag == .int or scalar_tag == .bool;
14488 const is_allowed_type = if (is_bool_not) scalar_tag == .bool else is_finite_int_or_bool;
14478 if (scalar_tag != .int and scalar_tag != .bool)
14479 return sema.fail(block, operand_src, "bitwise not operation on type '{}'", .{operand_ty.fmt(pt)});
1448914480
14490 if (!is_allowed_type) {
14491 return sema.fail(block, src, "unable to perform {s} not operation on type '{}'", .{
14492 if (is_bool_not) "boolean" else "binary", operand_type.fmt(pt),
14493 });
14494 }
14481 return analyzeBitNot(sema, block, operand, src);
14482}
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);
1449614494 if (try sema.resolveValue(operand)) |val| {
1449714495 if (val.isUndef(zcu)) {
14498 return pt.undefRef(operand_type);
14499 } else if (operand_type.zigTypeTag(zcu) == .vector) {
14500 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen(zcu));
14496 return pt.undefRef(operand_ty);
14497 } else if (operand_ty.zigTypeTag(zcu) == .vector) {
14498 const vec_len = try sema.usizeCast(block, src, operand_ty.vectorLen(zcu));
1450114499 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
1450214500 for (elems, 0..) |*elem, i| {
1450314501 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();
1450514503 }
1450614504 return Air.internedToRef((try pt.intern(.{ .aggregate = .{
14507 .ty = operand_type.toIntern(),
14505 .ty = operand_ty.toIntern(),
1450814506 .storage = .{ .elems = elems },
1450914507 } })));
1451014508 } 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);
1451214510 return Air.internedToRef(result_val.toIntern());
1451314511 }
1451414512 }
1451514513
1451614514 try sema.requireRuntimeBlock(block, src, null);
14517 return block.addTyOp(.not, operand_type, operand);
14515 return block.addTyOp(.not, operand_ty, operand);
1451814516}
1451914517
1452014518fn analyzeTupleCat(
......@@ -18367,6 +18365,30 @@ fn zirTypeofPeer(
1836718365 return Air.internedToRef(result_type.toIntern());
1836818366}
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
1837018392fn zirBoolBr(
1837118393 sema: *Sema,
1837218394 parent_block: *Block,
test/cases/compile_errors/binary_not_on_number_literal.zig+1-1
......@@ -10,4 +10,4 @@ export fn entry() usize {
1010// backend=stage2
1111// target=native
1212//
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)'