Commit 299836dbd9
Changed files (19)
test
cases
compile_errors
stage1
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),
src/print_zir.zig
@@ -197,6 +197,7 @@ const Writer = struct {
.embed_file,
.error_name,
.panic,
+ .panic_comptime,
.set_cold,
.set_runtime_safety,
.sqrt,
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.
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,
test/cases/compile_errors/stage1/obj/mul_overflow_in_function_evaluation.zig
@@ -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
test/cases/compile_errors/stage1/obj/negation_overflow_in_function_evaluation.zig
@@ -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
test/cases/compile_errors/stage1/obj/non-const_variables_of_things_that_require_const_variables.zig
@@ -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
test/cases/compile_errors/stage1/obj/non_error_sets_used_in_merge_error_sets_operator.zig
@@ -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
test/cases/compile_errors/stage1/obj/non_compile_time_array_concatenation.zig → test/cases/compile_errors/stage1/non_compile_time_array_concatenation.zig
File renamed without changes
test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_primitive.zig → 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'
test/cases/compile_errors/stage1/obj/method_call_with_first_arg_type_wrong_container.zig → 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'
test/cases/compile_errors/stage1/obj/missing_const_in_slice_with_nested_array_type.zig → 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'
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
+
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
test/cases/compile_errors/stage1/obj/no_else_prong_on_switch_on_global_error_set.zig → 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'
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
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'
test/cases/compile_errors/stage1/obj/panic_called_at_compile_time.zig → 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
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