Commit cc3336c784

Veikka Tuominen <git@vexu.eu>
2022-06-28 19:50:14
Sema: add source location to coerce result ptr, fix negation error
1 parent 979910d
src/AstGen.zig
@@ -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;
src/print_zir.zig
@@ -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),
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());
         },
 
src/Zir.zig
@@ -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,
test/cases/compile_errors/stage1/obj/assign_inline_fn_to_non-comptime_var.zig
@@ -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
test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig
@@ -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
test/cases/compile_errors/stage1/obj/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig โ†’ test/cases/compile_errors/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig
@@ -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'
test/cases/compile_errors/stage1/test/reassign_to_array_parameter.zig โ†’ test/cases/compile_errors/reassign_to_array_parameter.zig
@@ -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
test/cases/compile_errors/stage1/test/reassign_to_struct_parameter.zig โ†’ test/cases/compile_errors/reassign_to_struct_parameter.zig
@@ -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