From cc3336c7841c48622db855be95a79bbd030bade8 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 28 Jun 2022 20:50:14 +0300 Subject: [PATCH] Sema: add source location to coerce result ptr, fix negation error --- src/AstGen.zig | 9 ++-- src/Sema.zig | 43 ++++++++++++++++--- src/Zir.zig | 4 +- src/print_zir.zig | 2 +- .../assign_inline_fn_to_non-comptime_var.zig | 12 ++++++ ...n-integer_non-float_or_non-vector_type.zig | 4 +- .../test => }/reassign_to_array_parameter.zig | 5 +-- .../reassign_to_struct_parameter.zig | 5 +-- .../assign_inline_fn_to_non-comptime_var.zig | 12 ------ 9 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig rename test/cases/compile_errors/{stage1/obj => }/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig (63%) rename test/cases/compile_errors/{stage1/test => }/reassign_to_array_parameter.zig (63%) rename test/cases/compile_errors/{stage1/test => }/reassign_to_struct_parameter.zig (66%) delete mode 100644 test/cases/compile_errors/stage1/obj/assign_inline_fn_to_non-comptime_var.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index c4cba54bdc..c9abb1859b 100644 --- a/src/AstGen.zig +++ b/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; diff --git a/src/Sema.zig b/src/Sema.zig index 8b8d828f54..2674d61a7d 100644 --- a/src/Sema.zig +++ b/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()); }, diff --git a/src/Zir.zig b/src/Zir.zig index b43b775dfa..e6acfe8ed2 100644 --- a/src/Zir.zig +++ b/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, diff --git a/src/print_zir.zig b/src/print_zir.zig index dbb91a0ae0..480a3e2a4f 100644 --- a/src/print_zir.zig +++ b/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), diff --git a/test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig b/test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig new file mode 100644 index 0000000000..857123eae5 --- /dev/null +++ b/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 diff --git a/test/cases/compile_errors/stage1/obj/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig b/test/cases/compile_errors/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig similarity index 63% rename from test/cases/compile_errors/stage1/obj/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig rename to test/cases/compile_errors/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig index e9bbf921ab..66b249653c 100644 --- a/test/cases/compile_errors/stage1/obj/attempt_to_negate_a_non-integer_non-float_or_non-vector_type.zig +++ b/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' diff --git a/test/cases/compile_errors/stage1/test/reassign_to_array_parameter.zig b/test/cases/compile_errors/reassign_to_array_parameter.zig similarity index 63% rename from test/cases/compile_errors/stage1/test/reassign_to_array_parameter.zig rename to test/cases/compile_errors/reassign_to_array_parameter.zig index f3b51d2c0f..63d7a6d3e5 100644 --- a/test/cases/compile_errors/stage1/test/reassign_to_array_parameter.zig +++ b/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 diff --git a/test/cases/compile_errors/stage1/test/reassign_to_struct_parameter.zig b/test/cases/compile_errors/reassign_to_struct_parameter.zig similarity index 66% rename from test/cases/compile_errors/stage1/test/reassign_to_struct_parameter.zig rename to test/cases/compile_errors/reassign_to_struct_parameter.zig index 994833d989..963448f8fe 100644 --- a/test/cases/compile_errors/stage1/test/reassign_to_struct_parameter.zig +++ b/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 diff --git a/test/cases/compile_errors/stage1/obj/assign_inline_fn_to_non-comptime_var.zig b/test/cases/compile_errors/stage1/obj/assign_inline_fn_to_non-comptime_var.zig deleted file mode 100644 index 7714bb7282..0000000000 --- a/test/cases/compile_errors/stage1/obj/assign_inline_fn_to_non-comptime_var.zig +++ /dev/null @@ -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