From d284c00fda45b943f4ed5244ae1cb9e7f90f481f Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 18 Jan 2023 12:56:48 +0200 Subject: Sema: handle lazy values in more places * resolve lazy values in anon structs being passed to anytype params * use `resolveMaybeUndefValIntable` where appropriate Closes #14356 --- src/Sema.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index dcc38e4c0a..8da24b72cc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7514,7 +7514,7 @@ fn resolveGenericInstantiationType( } fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { - if (!ty.isSimpleTuple()) return; + if (!ty.isSimpleTupleOrAnonStruct()) return; const tuple = ty.tupleFields(); for (tuple.values) |field_val, i| { try sema.resolveTupleLazyValues(block, src, tuple.types[i]); @@ -11771,8 +11771,8 @@ fn zirShl( // TODO coerce rhs if air_tag is not shl_sat const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); - const maybe_lhs_val = try sema.resolveMaybeUndefVal(lhs); - const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); + const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs); + const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs); if (maybe_rhs_val) |rhs_val| { if (rhs_val.isUndef()) { @@ -11959,8 +11959,8 @@ fn zirShr( const target = sema.mod.getTarget(); const scalar_ty = lhs_ty.scalarType(); - const maybe_lhs_val = try sema.resolveMaybeUndefVal(lhs); - const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); + const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs); + const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs); const runtime_src = if (maybe_rhs_val) |rhs_val| rs: { if (rhs_val.isUndef()) { @@ -19697,7 +19697,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } } - if (try sema.resolveMaybeUndefVal(operand)) |val| { + if (try sema.resolveMaybeUndefValIntable(operand)) |val| { if (val.isUndef()) return sema.addConstUndef(dest_ty); if (!is_vector) { return sema.addConstant( @@ -19901,7 +19901,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); - _ = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); + const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { return sema.addConstant(operand_ty, val); @@ -19909,7 +19909,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const target = sema.mod.getTarget(); switch (operand_ty.zigTypeTag()) { - .Int, .ComptimeInt => { + .Int => { const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| { if (val.isUndef()) return sema.addConstUndef(operand_ty); const result_val = try val.bitReverse(operand_ty, target, sema.arena); @@ -19929,7 +19929,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const elems = try sema.arena.alloc(Value, vec_len); for (elems) |*elem, i| { const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); - elem.* = try elem_val.bitReverse(operand_ty, target, sema.arena); + elem.* = try elem_val.bitReverse(scalar_ty, target, sema.arena); } return sema.addConstant( operand_ty, -- cgit v1.2.3 From 5f5ab491684f0f5dd235189416f9c3d85e8e9be0 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 19 Jan 2023 18:44:09 +0200 Subject: Value: implement `compareAllWithZero` for `bytes` and `str_lit` Closes #10692 --- src/Sema.zig | 8 ++++---- src/type.zig | 6 +++--- src/value.zig | 34 +++++++++++++++++++++++++++++----- test/behavior/vector.zig | 11 +++++++++++ 4 files changed, 47 insertions(+), 12 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 8da24b72cc..a0a071c572 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11842,7 +11842,7 @@ fn zirShl( if (scalar_ty.zigTypeTag() == .ComptimeInt) { break :val shifted.wrapped_result; } - if (shifted.overflow_bit.compareAllWithZero(.eq)) { + if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) { break :val shifted.wrapped_result; } return sema.fail(block, src, "operation caused overflow", .{}); @@ -12831,7 +12831,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_val = maybe_lhs_val orelse unreachable; const rhs_val = maybe_rhs_val orelse unreachable; const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable; - if (!rem.compareAllWithZero(.eq)) { + if (!rem.compareAllWithZero(.eq, mod)) { return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{ @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod), }); @@ -13024,7 +13024,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (maybe_rhs_val) |rhs_val| { if (is_int) { const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, mod); - if (!(modulus_val.compareAllWithZero(.eq))) { + if (!(modulus_val.compareAllWithZero(.eq, mod))) { return sema.fail(block, src, "exact division produced remainder", .{}); } const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); @@ -13035,7 +13035,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return sema.addConstant(resolved_type, res); } else { const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, mod); - if (!(modulus_val.compareAllWithZero(.eq))) { + if (!(modulus_val.compareAllWithZero(.eq, mod))) { return sema.fail(block, src, "exact division produced remainder", .{}); } return sema.addConstant( diff --git a/src/type.zig b/src/type.zig index dd4be91937..c675cd225d 100644 --- a/src/type.zig +++ b/src/type.zig @@ -5533,7 +5533,7 @@ pub const Type = extern union { } const S = struct { fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize { - if (int_val.compareAllWithZero(.lt)) return null; + if (int_val.compareAllWithZero(.lt, m)) return null; var end_payload: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = end, @@ -6556,12 +6556,12 @@ pub const Type = extern union { if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) { switch (d.size) { .Slice => { - if (sent.compareAllWithZero(.eq)) { + if (sent.compareAllWithZero(.eq, mod)) { return Type.initTag(.const_slice_u8_sentinel_0); } }, .Many => { - if (sent.compareAllWithZero(.eq)) { + if (sent.compareAllWithZero(.eq, mod)) { return Type.initTag(.manyptr_const_u8_sentinel_0); } }, diff --git a/src/value.zig b/src/value.zig index 5d38bcb7a9..306e31c0a7 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2076,13 +2076,22 @@ pub const Value = extern union { /// For vectors, returns true if comparison is true for ALL elements. /// /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)` - pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator) bool { - return compareAllWithZeroAdvanced(lhs, op, null) catch unreachable; + pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool { + return compareAllWithZeroAdvancedExtra(lhs, op, mod, null) catch unreachable; } pub fn compareAllWithZeroAdvanced( lhs: Value, op: std.math.CompareOperator, + sema: *Sema, + ) Module.CompileError!bool { + return compareAllWithZeroAdvancedExtra(lhs, op, sema.mod, sema); + } + + pub fn compareAllWithZeroAdvancedExtra( + lhs: Value, + op: std.math.CompareOperator, + mod: *Module, opt_sema: ?*Sema, ) Module.CompileError!bool { if (lhs.isInf()) { @@ -2095,10 +2104,25 @@ pub const Value = extern union { } switch (lhs.tag()) { - .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, opt_sema), + .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema), .aggregate => { for (lhs.castTag(.aggregate).?.data) |elem_val| { - if (!(try elem_val.compareAllWithZeroAdvanced(op, opt_sema))) return false; + if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false; + } + return true; + }, + .str_lit => { + const str_lit = lhs.castTag(.str_lit).?.data; + const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; + for (bytes) |byte| { + if (!std.math.compare(byte, op, 0)) return false; + } + return true; + }, + .bytes => { + const bytes = lhs.castTag(.bytes).?.data; + for (bytes) |byte| { + if (!std.math.compare(byte, op, 0)) return false; } return true; }, @@ -3103,7 +3127,7 @@ pub const Value = extern union { .int_i64, .int_big_positive, .int_big_negative, - => compareAllWithZero(self, .eq), + => self.orderAgainstZero().compare(.eq), .undef => unreachable, .unreachable_value => unreachable, diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index ba3d98ee56..8bcae5fefc 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -1286,3 +1286,14 @@ test "store to vector in slice" { s[i] = s[0]; try expectEqual(v[1], v[0]); } + +test "addition of vectors represented as strings" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const V = @Vector(3, u8); + const foo: V = "foo".*; + const bar: V = @typeName(u32).*; + try expectEqual(V{ 219, 162, 161 }, foo + bar); +} -- cgit v1.2.3 From 5259d11e3b75b9b910fa1b0a479aedb702e256f6 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 21 Jan 2023 23:12:12 +0200 Subject: Sema: resolve fields before checking tuple len Closes #14400 --- src/Sema.zig | 1 + test/behavior/struct.zig | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index a0a071c572..8dc30ebbe5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3948,6 +3948,7 @@ fn validateArrayInitTy( return; }, .Struct => if (ty.isTuple()) { + _ = try sema.resolveTypeFields(ty); const array_len = ty.arrayLen(); if (extra.init_count > array_len) { return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index a32a0ed495..ed3e1ce88f 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1573,3 +1573,8 @@ test "struct fields get automatically reordered" { }; try expect(@sizeOf(S1) == @sizeOf(S2)); } + +test "directly initiating tuple like struct" { + const a = struct { u8 }{8}; + try expect(a[0] == 8); +} -- cgit v1.2.3 From 1f475de852daddbf88e8165cdaef492e616ce3fe Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 21 Jan 2023 23:17:02 +0200 Subject: Sema: fix unwrapping null when reporting error on member access Closes #14399 --- src/Sema.zig | 4 ++-- test/cases/compile_errors/bad_member_access_on_tuple.zig | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 test/cases/compile_errors/bad_member_access_on_tuple.zig (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 8dc30ebbe5..c5cd2c9cd6 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4643,11 +4643,11 @@ fn failWithBadMemberAccess( .Enum => "enum", else => unreachable, }; - if (sema.mod.declIsRoot(agg_ty.getOwnerDecl())) { + if (agg_ty.getOwnerDeclOrNull()) |some| if (sema.mod.declIsRoot(some)) { return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{ agg_ty.fmt(sema.mod), field_name, }); - } + }; const msg = msg: { const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{ kw_name, agg_ty.fmt(sema.mod), field_name, diff --git a/test/cases/compile_errors/bad_member_access_on_tuple.zig b/test/cases/compile_errors/bad_member_access_on_tuple.zig new file mode 100644 index 0000000000..0f91655fc0 --- /dev/null +++ b/test/cases/compile_errors/bad_member_access_on_tuple.zig @@ -0,0 +1,9 @@ +comptime { + _ = @TypeOf(.{}).is_optional; +} + +// error +// backend=stage2 +// target=native +// +// :2:21: error: struct '@TypeOf(.{})' has no member named 'is_optional' -- cgit v1.2.3 From a28fbf3132b0b12841ecd70518804123149f3ac0 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 21 Jan 2023 23:28:18 +0200 Subject: Sema: fix error message for bad pointer arithmetic Closes #14388 --- src/Sema.zig | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index c5cd2c9cd6..124af6c131 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12800,7 +12800,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -12960,7 +12960,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_exact); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -13123,7 +13123,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_floor); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -13239,7 +13239,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_trunc); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -13482,7 +13482,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .mod_rem); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -13665,7 +13665,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .mod); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -13767,7 +13767,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); - try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .rem); + try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ @@ -14107,12 +14107,7 @@ fn analyzeArithmetic( const air_tag: Air.Inst.Tag = switch (zir_tag) { .add => .ptr_add, .sub => .ptr_sub, - else => return sema.fail( - block, - src, - "invalid pointer arithmetic operand: '{s}''", - .{@tagName(zir_tag)}, - ), + else => return sema.fail(block, src, "invalid pointer arithmetic operator", .{}), }; return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src); }, @@ -20029,7 +20024,6 @@ fn checkInvalidPtrArithmetic( block: *Block, src: LazySrcLoc, ty: Type, - zir_tag: Zir.Inst.Tag, ) CompileError!void { switch (try ty.zigTypeTagOrPoison()) { .Pointer => switch (ty.ptrSize()) { @@ -20037,8 +20031,8 @@ fn checkInvalidPtrArithmetic( .Many, .C => return sema.fail( block, src, - "invalid pointer arithmetic operand: '{s}''", - .{@tagName(zir_tag)}, + "invalid pointer arithmetic operator", + .{}, ), }, else => return, -- cgit v1.2.3