diff --git a/src/AstGen.zig b/src/AstGen.zig index d4b942ecbc..a44ac04557 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2464,6 +2464,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner .repeat, .repeat_inline, .panic, + .panic_comptime, => { noreturn_src_node = statement; break :b true; @@ -7358,7 +7359,7 @@ fn builtinCall( .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int), .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file), .error_name => return simpleUnOp(gz, scope, rl, node, .{ .ty = .anyerror_type }, params[0], .error_name), - .panic => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .panic), + .panic => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], if (gz.force_comptime) .panic_comptime else .panic), .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold), .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety), .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt), diff --git a/src/Sema.zig b/src/Sema.zig index 49878397e9..db222b698e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -903,7 +903,8 @@ fn analyzeBodyInner( .ret_load => break sema.zirRetLoad(block, inst), .ret_err_value => break sema.zirRetErrValue(block, inst), .@"unreachable" => break sema.zirUnreachable(block, inst), - .panic => break sema.zirPanic(block, inst), + .panic => break sema.zirPanic(block, inst, false), + .panic_comptime => break sema.zirPanic(block, inst, true), // zig fmt: on .extended => ext: { @@ -3870,10 +3871,26 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}), } + const elem_ty = operand_ty.elemType2(); if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { if (val.isUndef()) { return sema.fail(block, src, "cannot dereference undefined value", .{}); } + } else if (!(try sema.validateRunTimeType(block, src, elem_ty, false))) { + const msg = msg: { + const msg = try sema.errMsg( + block, + src, + "values of type '{}' must be comptime known, but operand value is runtime known", + .{elem_ty.fmt(sema.mod)}, + ); + errdefer msg.destroy(sema.gpa); + + const src_decl = sema.mod.declPtr(block.src_decl); + try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(src_decl), elem_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); } } @@ -4308,11 +4325,15 @@ fn zirCompileLog( return Air.Inst.Ref.void_value; } -fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bool) CompileError!Zir.Inst.Index { const inst_data = sema.code.instructions.items(.data)[inst].un_node; - const src: LazySrcLoc = inst_data.src(); + const src = inst_data.src(); const msg_inst = try sema.resolveInst(inst_data.operand); + if (block.is_comptime or force_comptime) { + return sema.fail(block, src, "encountered @panic at comptime", .{}); + } + try sema.requireRuntimeBlock(block, src); return sema.panicWithMsg(block, src, msg_inst); } @@ -8357,7 +8378,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError return sema.fail( block, src, - "switch must handle all possibilities", + "else prong required when switching on type 'anyerror'", .{}, ); } @@ -17416,7 +17437,7 @@ fn zirVarExtended( const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); const src = sema.src; const ty_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at type - const mut_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at mut token + const name_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at the name token const init_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at init expr const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); @@ -17460,7 +17481,7 @@ fn zirVarExtended( return sema.failWithNeededComptime(block, init_src); } else Value.initTag(.unreachable_value); - try sema.validateVarType(block, mut_src, var_ty, small.is_extern); + try sema.validateVarType(block, name_src, var_ty, small.is_extern); const new_var = try sema.gpa.create(Module.Var); errdefer sema.gpa.destroy(new_var); @@ -17957,6 +17978,9 @@ fn validateVarType( const src_decl = mod.declPtr(block.src_decl); try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(src_decl), var_ty); + if (var_ty.zigTypeTag() == .ComptimeInt or var_ty.zigTypeTag() == .ComptimeFloat) { + try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); + } break :msg msg; }; @@ -20041,6 +20065,15 @@ fn coerce( }); return sema.addConstant(dest_ty, slice_val); } + + if (inst_ty.zigTypeTag() == .Array) { + return sema.fail( + block, + inst_src, + "array literal requires address-of operator (&) to coerce to slice type '{}'", + .{dest_ty.fmt(sema.mod)}, + ); + } }, .Many => p: { if (!inst_ty.isSlice()) break :p; @@ -24433,6 +24466,10 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil } else { // The provided type is the enum tag type. union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator); + if (union_obj.tag_ty.zigTypeTag() != .Enum) { + const tag_ty_src = src; // TODO better source location + return sema.fail(block, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}); + } // The fields of the union must match the enum exactly. // Store a copy of the enum field names so we can check for // missing or extraneous fields later. diff --git a/src/Zir.zig b/src/Zir.zig index 9448b54346..8735ba636d 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -798,6 +798,8 @@ pub const Inst = struct { error_name, /// Implement builtin `@panic`. Uses `un_node`. panic, + /// Same as `panic` but forces comptime. + panic_comptime, /// Implement builtin `@setCold`. Uses `un_node`. set_cold, /// Implement builtin `@setRuntimeSafety`. Uses `un_node`. @@ -1260,6 +1262,7 @@ pub const Inst = struct { .repeat, .repeat_inline, .panic, + .panic_comptime, => true, }; } @@ -1533,6 +1536,7 @@ pub const Inst = struct { .repeat, .repeat_inline, .panic, + .panic_comptime, .@"try", .try_ptr, //.try_inline, @@ -1726,6 +1730,7 @@ pub const Inst = struct { .embed_file = .un_node, .error_name = .un_node, .panic = .un_node, + .panic_comptime = .un_node, .set_cold = .un_node, .set_runtime_safety = .un_node, .sqrt = .un_node, diff --git a/src/print_zir.zig b/src/print_zir.zig index 6cd289c092..2fcd82baf3 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -197,6 +197,7 @@ const Writer = struct { .embed_file, .error_name, .panic, + .panic_comptime, .set_cold, .set_runtime_safety, .sqrt, diff --git a/test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_primitive.zig b/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig similarity index 70% rename from test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_primitive.zig rename to test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig index 316be2d899..e93d1e717d 100644 --- a/test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_primitive.zig +++ b/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig @@ -15,7 +15,7 @@ export fn f() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:14:5: error: expected type 'i32', found 'Foo' +// :14:9: error: type 'tmp.Foo' has no field or member function named 'init' diff --git a/test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_wrong_container.zig b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig similarity index 82% rename from test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_wrong_container.zig rename to test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig index 04ab89fb6c..0820151ff1 100644 --- a/test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_wrong_container.zig +++ b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig @@ -24,7 +24,7 @@ export fn foo() void { } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:23:5: error: expected type '*Allocator', found '*List' +// :23:6: error: type 'tmp.List' has no field or member function named 'init' diff --git a/test/cases/compile_errors/stage1/obj/missing_const_in_slice_with_nested_array_type.zig b/test/cases/compile_errors/missing_const_in_slice_with_nested_array_type.zig similarity index 71% rename from test/cases/compile_errors/stage1/obj/missing_const_in_slice_with_nested_array_type.zig rename to test/cases/compile_errors/missing_const_in_slice_with_nested_array_type.zig index af9d690d43..1ef986935b 100644 --- a/test/cases/compile_errors/stage1/obj/missing_const_in_slice_with_nested_array_type.zig +++ b/test/cases/compile_errors/missing_const_in_slice_with_nested_array_type.zig @@ -12,7 +12,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:4:30: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32' +// :4:30: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32' diff --git a/test/cases/compile_errors/mul_overflow_in_function_evaluation.zig b/test/cases/compile_errors/mul_overflow_in_function_evaluation.zig new file mode 100644 index 0000000000..6be57f770e --- /dev/null +++ b/test/cases/compile_errors/mul_overflow_in_function_evaluation.zig @@ -0,0 +1,14 @@ +const y = mul(300, 6000); +fn mul(a: u16, b: u16) u16 { + return a * b; +} + +export fn entry() usize { return @sizeOf(@TypeOf(&y)); } + +// error +// backend=stage2 +// target=native +// +// :3:14: error: overflow of integer type 'u16' with value '1800000' +// :1:14: note: called from here + diff --git a/test/cases/compile_errors/negation_overflow_in_function_evaluation.zig b/test/cases/compile_errors/negation_overflow_in_function_evaluation.zig new file mode 100644 index 0000000000..abd8549fd2 --- /dev/null +++ b/test/cases/compile_errors/negation_overflow_in_function_evaluation.zig @@ -0,0 +1,13 @@ +const y = neg(-128); +fn neg(x: i8) i8 { + return -x; +} + +export fn entry() usize { return @sizeOf(@TypeOf(&y)); } + +// error +// backend=stage2 +// target=native +// +// :3:12: error: overflow of integer type 'i8' with value '128' +// :1:14: note: called from here diff --git a/test/cases/compile_errors/stage1/obj/no_else_prong_on_switch_on_global_error_set.zig b/test/cases/compile_errors/no_else_prong_on_switch_on_global_error_set.zig similarity index 61% rename from test/cases/compile_errors/stage1/obj/no_else_prong_on_switch_on_global_error_set.zig rename to test/cases/compile_errors/no_else_prong_on_switch_on_global_error_set.zig index 39f4399caf..6c13611d64 100644 --- a/test/cases/compile_errors/stage1/obj/no_else_prong_on_switch_on_global_error_set.zig +++ b/test/cases/compile_errors/no_else_prong_on_switch_on_global_error_set.zig @@ -8,7 +8,7 @@ fn foo(a: anyerror) void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:5:5: error: else prong required when switching on type 'anyerror' +// :5:5: error: else prong required when switching on type 'anyerror' diff --git a/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig b/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig new file mode 100644 index 0000000000..c6713b755a --- /dev/null +++ b/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig @@ -0,0 +1,44 @@ +export fn entry1() void { + var m2 = &2; + _ = m2; +} +export fn entry2() void { + var a = undefined; + _ = a; +} +export fn entry3() void { + var b = 1; + _ = b; +} +export fn entry4() void { + var c = 1.0; + _ = c; +} +export fn entry5() void { + var d = null; + _ = d; +} +export fn entry6(opaque_: *Opaque) void { + var e = opaque_.*; + _ = e; +} +export fn entry7() void { + var f = i32; + _ = f; +} +const Opaque = opaque {}; + +// error +// backend=stage2 +// target=native +// +// :2:8: error: variable of type '*const comptime_int' must be const or comptime +// :6:8: error: variable of type '@TypeOf(undefined)' must be const or comptime +// :10:8: error: variable of type 'comptime_int' must be const or comptime +// :10:8: note: to modify this variable at runtime, it must be given an explicit fixed-size number type +// :14:8: error: variable of type 'comptime_float' must be const or comptime +// :14:8: note: to modify this variable at runtime, it must be given an explicit fixed-size number type +// :18:8: error: variable of type '@TypeOf(null)' must be const or comptime +// :22:19: error: values of type 'tmp.Opaque' must be comptime known, but operand value is runtime known +// :26:8: error: variable of type 'type' must be const or comptime +// :26:8: note: types are not available at runtime diff --git a/test/cases/compile_errors/non_error_sets_used_in_merge_error_sets_operator.zig b/test/cases/compile_errors/non_error_sets_used_in_merge_error_sets_operator.zig new file mode 100644 index 0000000000..eca7ba698c --- /dev/null +++ b/test/cases/compile_errors/non_error_sets_used_in_merge_error_sets_operator.zig @@ -0,0 +1,15 @@ +export fn foo() void { + const Errors = u8 || u16; + _ = Errors; +} +export fn bar() void { + const Errors = error{} || u16; + _ = Errors; +} + +// error +// backend=stage2 +// target=native +// +// :2:20: error: expected error set type, found 'u8' +// :6:31: error: expected error set type, found 'u16' diff --git a/test/cases/compile_errors/stage1/obj/panic_called_at_compile_time.zig b/test/cases/compile_errors/panic_called_at_compile_time.zig similarity index 57% rename from test/cases/compile_errors/stage1/obj/panic_called_at_compile_time.zig rename to test/cases/compile_errors/panic_called_at_compile_time.zig index 7c16932913..220161930b 100644 --- a/test/cases/compile_errors/stage1/obj/panic_called_at_compile_time.zig +++ b/test/cases/compile_errors/panic_called_at_compile_time.zig @@ -5,7 +5,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:9: error: encountered @panic at compile-time +// :3:9: error: encountered @panic at comptime diff --git a/test/cases/compile_errors/stage1/obj/non_compile_time_array_concatenation.zig b/test/cases/compile_errors/stage1/non_compile_time_array_concatenation.zig similarity index 100% rename from test/cases/compile_errors/stage1/obj/non_compile_time_array_concatenation.zig rename to test/cases/compile_errors/stage1/non_compile_time_array_concatenation.zig diff --git a/test/cases/compile_errors/stage1/obj/mul_overflow_in_function_evaluation.zig b/test/cases/compile_errors/stage1/obj/mul_overflow_in_function_evaluation.zig deleted file mode 100644 index 8209b33f94..0000000000 --- a/test/cases/compile_errors/stage1/obj/mul_overflow_in_function_evaluation.zig +++ /dev/null @@ -1,12 +0,0 @@ -const y = mul(300, 6000); -fn mul(a: u16, b: u16) u16 { - return a * b; -} - -export fn entry() usize { return @sizeOf(@TypeOf(y)); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:14: error: operation caused overflow diff --git a/test/cases/compile_errors/stage1/obj/negation_overflow_in_function_evaluation.zig b/test/cases/compile_errors/stage1/obj/negation_overflow_in_function_evaluation.zig deleted file mode 100644 index f83e0de6ae..0000000000 --- a/test/cases/compile_errors/stage1/obj/negation_overflow_in_function_evaluation.zig +++ /dev/null @@ -1,12 +0,0 @@ -const y = neg(-128); -fn neg(x: i8) i8 { - return -x; -} - -export fn entry() usize { return @sizeOf(@TypeOf(y)); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:12: error: negation caused overflow diff --git a/test/cases/compile_errors/stage1/obj/non-const_variables_of_things_that_require_const_variables.zig b/test/cases/compile_errors/stage1/obj/non-const_variables_of_things_that_require_const_variables.zig deleted file mode 100644 index 73ef29aa54..0000000000 --- a/test/cases/compile_errors/stage1/obj/non-const_variables_of_things_that_require_const_variables.zig +++ /dev/null @@ -1,51 +0,0 @@ -export fn entry1() void { - var m2 = &2; - _ = m2; -} -export fn entry2() void { - var a = undefined; - _ = a; -} -export fn entry3() void { - var b = 1; - _ = b; -} -export fn entry4() void { - var c = 1.0; - _ = c; -} -export fn entry5() void { - var d = null; - _ = d; -} -export fn entry6(opaque_: *Opaque) void { - var e = opaque_.*; - _ = e; -} -export fn entry7() void { - var f = i32; - _ = f; -} -export fn entry8() void { - var h = (Foo {}).bar; - _ = h; -} -const Opaque = opaque {}; -const Foo = struct { - fn bar(self: *const Foo) void {_ = self;} -}; - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:4: error: variable of type '*const comptime_int' must be const or comptime -// tmp.zig:6:4: error: variable of type '@Type(.Undefined)' must be const or comptime -// tmp.zig:10:4: error: variable of type 'comptime_int' must be const or comptime -// tmp.zig:10:4: note: to modify this variable at runtime, it must be given an explicit fixed-size number type -// tmp.zig:14:4: error: variable of type 'comptime_float' must be const or comptime -// tmp.zig:14:4: note: to modify this variable at runtime, it must be given an explicit fixed-size number type -// tmp.zig:18:4: error: variable of type '@Type(.Null)' must be const or comptime -// tmp.zig:22:4: error: variable of type 'Opaque' not allowed -// tmp.zig:26:4: error: variable of type 'type' must be const or comptime -// tmp.zig:30:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime diff --git a/test/cases/compile_errors/stage1/obj/non_error_sets_used_in_merge_error_sets_operator.zig b/test/cases/compile_errors/stage1/obj/non_error_sets_used_in_merge_error_sets_operator.zig deleted file mode 100644 index fc3431820c..0000000000 --- a/test/cases/compile_errors/stage1/obj/non_error_sets_used_in_merge_error_sets_operator.zig +++ /dev/null @@ -1,17 +0,0 @@ -export fn foo() void { - const Errors = u8 || u16; - _ = Errors; -} -export fn bar() void { - const Errors = error{} || u16; - _ = Errors; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:20: error: expected error set type, found type 'u8' -// tmp.zig:2:23: note: `||` merges error sets; `or` performs boolean OR -// tmp.zig:6:31: error: expected error set type, found type 'u16' -// tmp.zig:6:28: note: `||` merges error sets; `or` performs boolean OR diff --git a/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig b/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig index 6fab70abf8..120ba5c588 100644 --- a/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig +++ b/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig @@ -9,3 +9,4 @@ export fn entry() void { // target=native // // :1:1: error: variable of type 'comptime_int' must be const or comptime +// :1:1: note: to modify this variable at runtime, it must be given an explicit fixed-size number type