Commit 283afb50b5

mlugg <mlugg@mlugg.co.uk>
2023-08-21 03:27:11
AstGen: disallow '-0' integer literal
The intent here is ambiguous: this resolves to the comptime_int '0', but it's likely the user meant to use a floating-point literal. Resolves: #16890
1 parent 411462e
Changed files (5)
lib
std
src
test
behavior
cases
lib/std/math/big/int_test.zig
@@ -2317,17 +2317,6 @@ test "big.int bitwise xor single negative simple" {
     try testing.expect((try a.to(i64)) == -0x2efed94fcb932ef9);
 }
 
-test "big.int bitwise xor single negative zero" {
-    var a = try Managed.initSet(testing.allocator, 0);
-    defer a.deinit();
-    var b = try Managed.initSet(testing.allocator, -0);
-    defer b.deinit();
-
-    try a.bitXor(&a, &b);
-
-    try testing.expect(a.eqlZero());
-}
-
 test "big.int bitwise xor single negative multi-limb" {
     var a = try Managed.initSet(testing.allocator, -0x9849c6e7a10d66d0e4260d4846254c32);
     defer a.deinit();
@@ -2687,8 +2676,6 @@ test "big int popcount" {
     try a.set(0);
     try popCountTest(&a, 0, 0);
     try popCountTest(&a, 567, 0);
-    try a.set(-0);
-    try popCountTest(&a, 0, 0);
 
     try a.set(1);
     try popCountTest(&a, 1, 1);
lib/std/math/pow.zig
@@ -209,8 +209,8 @@ test "math.pow.special" {
     try expect(pow(f32, -45, 1.0) == -45);
     try expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
     try expect(math.isPositiveInf(pow(f32, -math.inf(f32), 0.5)));
-    try expect(math.isPositiveInf(pow(f32, -0, -0.5)));
-    try expect(pow(f32, -0, 0.5) == 0);
+    try expect(math.isPositiveInf(pow(f32, -0.0, -0.5)));
+    try expect(pow(f32, -0.0, 0.5) == 0);
     try expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
     try expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
     //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
src/AstGen.zig
@@ -7270,7 +7270,15 @@ fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node:
 
     const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
         .int => |num| switch (num) {
-            0 => .zero,
+            0 => if (sign == .positive) .zero else return astgen.failTokNotes(
+                num_token,
+                "integer literal '-0' is ambiguous",
+                .{},
+                &.{
+                    try astgen.errNoteTok(num_token, "use '0' for an integer zero", .{}),
+                    try astgen.errNoteTok(num_token, "use '-0.0' for a floating-point signed zero", .{}),
+                },
+            ),
             1 => .one,
             else => try gz.addInt(num),
         },
test/behavior/bitcast.zig
@@ -63,8 +63,6 @@ fn testBitCast(comptime N: usize) !void {
     try expect(conv_uN(N, 0) == 0);
     try expect(conv_iN(N, 0) == 0);
 
-    try expect(conv_iN(N, -0) == 0);
-
     if (N > 24) {
         try expect(conv_uN(N, 0xf23456) == 0xf23456);
     }
test/cases/compile_errors/negative_zero_literal.zig
@@ -0,0 +1,11 @@
+export fn foo() void {
+    _ = -0;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:10: error: integer literal '-0' is ambiguous
+// :2:10: note: use '0' for an integer zero
+// :2:10: note: use '-0.0' for a floating-point signed zero