| author | |
| committer | |
| log | c07c2d68c7c8276f8d215cfd21f0dcd92db9cf79 |
| tree | bb4303a3dfd20e114cd6223055d665775badf996 |
| parent | 1569b9c16590f8c5359003ae310093217e5fcf63 |
17 files changed, 153 insertions(+), 143 deletions(-)
src/Sema.zig+40-36| ... | @@ -19494,6 +19494,34 @@ fn elemVal( | ... | @@ -19494,6 +19494,34 @@ fn elemVal( |
| 19494 | } | 19494 | } |
| 19495 | } | 19495 | } |
| 19496 | 19496 | ||
| 19497 | fn validateRuntimeElemAccess( | ||
| 19498 | sema: *Sema, | ||
| 19499 | block: *Block, | ||
| 19500 | elem_index_src: LazySrcLoc, | ||
| 19501 | elem_ty: Type, | ||
| 19502 | parent_ty: Type, | ||
| 19503 | parent_src: LazySrcLoc, | ||
| 19504 | ) CompileError!void { | ||
| 19505 | const valid_rt = try sema.validateRunTimeType(block, elem_index_src, elem_ty, false); | ||
| 19506 | if (!valid_rt) { | ||
| 19507 | const msg = msg: { | ||
| 19508 | const msg = try sema.errMsg( | ||
| 19509 | block, | ||
| 19510 | elem_index_src, | ||
| 19511 | "values of type '{}' must be comptime known, but index value is runtime known", | ||
| 19512 | .{parent_ty.fmt(sema.mod)}, | ||
| 19513 | ); | ||
| 19514 | errdefer msg.destroy(sema.gpa); | ||
| 19515 | |||
| 19516 | const src_decl = sema.mod.declPtr(block.src_decl); | ||
| 19517 | try sema.explainWhyTypeIsComptime(block, elem_index_src, msg, parent_src.toSrcLoc(src_decl), parent_ty); | ||
| 19518 | |||
| 19519 | break :msg msg; | ||
| 19520 | }; | ||
| 19521 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 19522 | } | ||
| 19523 | } | ||
| 19524 | |||
| 19497 | fn tupleFieldPtr( | 19525 | fn tupleFieldPtr( |
| 19498 | sema: *Sema, | 19526 | sema: *Sema, |
| 19499 | block: *Block, | 19527 | block: *Block, |
| ... | @@ -19534,6 +19562,8 @@ fn tupleFieldPtr( | ... | @@ -19534,6 +19562,8 @@ fn tupleFieldPtr( |
| 19534 | ); | 19562 | ); |
| 19535 | } | 19563 | } |
| 19536 | 19564 | ||
| 19565 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src); | ||
| 19566 | |||
| 19537 | try sema.requireRuntimeBlock(block, tuple_ptr_src); | 19567 | try sema.requireRuntimeBlock(block, tuple_ptr_src); |
| 19538 | return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty); | 19568 | return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty); |
| 19539 | } | 19569 | } |
| ... | @@ -19572,6 +19602,8 @@ fn tupleField( | ... | @@ -19572,6 +19602,8 @@ fn tupleField( |
| 19572 | return sema.addConstant(field_ty, field_values[field_index]); | 19602 | return sema.addConstant(field_ty, field_values[field_index]); |
| 19573 | } | 19603 | } |
| 19574 | 19604 | ||
| 19605 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); | ||
| 19606 | |||
| 19575 | try sema.requireRuntimeBlock(block, tuple_src); | 19607 | try sema.requireRuntimeBlock(block, tuple_src); |
| 19576 | return block.addStructFieldVal(tuple, field_index, field_ty); | 19608 | return block.addStructFieldVal(tuple, field_index, field_ty); |
| 19577 | } | 19609 | } |
| ... | @@ -19622,24 +19654,7 @@ fn elemValArray( | ... | @@ -19622,24 +19654,7 @@ fn elemValArray( |
| 19622 | } | 19654 | } |
| 19623 | } | 19655 | } |
| 19624 | 19656 | ||
| 19625 | const valid_rt = try sema.validateRunTimeType(block, elem_index_src, elem_ty, false); | 19657 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src); |
| 19626 | if (!valid_rt) { | ||
| 19627 | const msg = msg: { | ||
| 19628 | const msg = try sema.errMsg( | ||
| 19629 | block, | ||
| 19630 | elem_index_src, | ||
| 19631 | "values of type '{}' must be comptime known, but index value is runtime known", | ||
| 19632 | .{array_ty.fmt(sema.mod)}, | ||
| 19633 | ); | ||
| 19634 | errdefer msg.destroy(sema.gpa); | ||
| 19635 | |||
| 19636 | const src_decl = sema.mod.declPtr(block.src_decl); | ||
| 19637 | try sema.explainWhyTypeIsComptime(block, elem_index_src, msg, array_src.toSrcLoc(src_decl), array_ty); | ||
| 19638 | |||
| 19639 | break :msg msg; | ||
| 19640 | }; | ||
| 19641 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 19642 | } | ||
| 19643 | 19658 | ||
| 19644 | const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src; | 19659 | const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src; |
| 19645 | try sema.requireRuntimeBlock(block, runtime_src); | 19660 | try sema.requireRuntimeBlock(block, runtime_src); |
| ... | @@ -19697,23 +19712,8 @@ fn elemPtrArray( | ... | @@ -19697,23 +19712,8 @@ fn elemPtrArray( |
| 19697 | } | 19712 | } |
| 19698 | } | 19713 | } |
| 19699 | 19714 | ||
| 19700 | const valid_rt = try sema.validateRunTimeType(block, elem_index_src, array_ty.elemType2(), false); | 19715 | if (!init) { |
| 19701 | if (!valid_rt and !init) { | 19716 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(), array_ty, array_ptr_src); |
| 19702 | const msg = msg: { | ||
| 19703 | const msg = try sema.errMsg( | ||
| 19704 | block, | ||
| 19705 | elem_index_src, | ||
| 19706 | "values of type '{}' must be comptime known, but index value is runtime known", | ||
| 19707 | .{array_ty.fmt(sema.mod)}, | ||
| 19708 | ); | ||
| 19709 | errdefer msg.destroy(sema.gpa); | ||
| 19710 | |||
| 19711 | const src_decl = sema.mod.declPtr(block.src_decl); | ||
| 19712 | try sema.explainWhyTypeIsComptime(block, elem_index_src, msg, array_ptr_src.toSrcLoc(src_decl), array_ty); | ||
| 19713 | |||
| 19714 | break :msg msg; | ||
| 19715 | }; | ||
| 19716 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 19717 | } | 19717 | } |
| 19718 | 19718 | ||
| 19719 | const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src; | 19719 | const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src; |
| ... | @@ -19769,6 +19769,8 @@ fn elemValSlice( | ... | @@ -19769,6 +19769,8 @@ fn elemValSlice( |
| 19769 | } | 19769 | } |
| 19770 | } | 19770 | } |
| 19771 | 19771 | ||
| 19772 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src); | ||
| 19773 | |||
| 19772 | try sema.requireRuntimeBlock(block, runtime_src); | 19774 | try sema.requireRuntimeBlock(block, runtime_src); |
| 19773 | if (block.wantSafety()) { | 19775 | if (block.wantSafety()) { |
| 19774 | const len_inst = if (maybe_slice_val) |slice_val| | 19776 | const len_inst = if (maybe_slice_val) |slice_val| |
| ... | @@ -19822,6 +19824,8 @@ fn elemPtrSlice( | ... | @@ -19822,6 +19824,8 @@ fn elemPtrSlice( |
| 19822 | } | 19824 | } |
| 19823 | } | 19825 | } |
| 19824 | 19826 | ||
| 19827 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_ty, slice_src); | ||
| 19828 | |||
| 19825 | const runtime_src = if (maybe_undef_slice_val != null) elem_index_src else slice_src; | 19829 | const runtime_src = if (maybe_undef_slice_val != null) elem_index_src else slice_src; |
| 19826 | try sema.requireRuntimeBlock(block, runtime_src); | 19830 | try sema.requireRuntimeBlock(block, runtime_src); |
| 19827 | if (block.wantSafety()) { | 19831 | if (block.wantSafety()) { |
| ... | @@ -22426,7 +22430,7 @@ fn analyzeLoad( | ... | @@ -22426,7 +22430,7 @@ fn analyzeLoad( |
| 22426 | } | 22430 | } |
| 22427 | 22431 | ||
| 22428 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 22432 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 22429 | if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) |elem_val| { | 22433 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| 22430 | return sema.addConstant(elem_ty, elem_val); | 22434 | return sema.addConstant(elem_ty, elem_val); |
| 22431 | } | 22435 | } |
| 22432 | if (block.is_typeof) { | 22436 | if (block.is_typeof) { |
test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | name: []const u8, | ||
| 3 | T: type, | ||
| 4 | }; | ||
| 5 | export fn entry() void { | ||
| 6 | const xx: [2]Foo = .{ .{ .name = "", .T = u8 }, .{ .name = "", .T = u8 } }; | ||
| 7 | for (xx) |f| { _ = f;} | ||
| 8 | } | ||
| 9 | |||
| 10 | // error | ||
| 11 | // backend=stage2 | ||
| 12 | // target=native | ||
| 13 | // | ||
| 14 | // :7:10: error: values of type '[2]tmp.Foo' must be comptime known, but index value is runtime known | ||
| 15 | // :3:8: note: struct requires comptime because of this field | ||
| 16 | // :3:8: note: types are not available at runtime | ||
test/cases/compile_errors/range_operator_in_switch_used_on_error_set.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | foo(452) catch |err| switch (err) { | ||
| 3 | error.Foo ... error.Bar => {}, | ||
| 4 | else => {}, | ||
| 5 | }; | ||
| 6 | } | ||
| 7 | fn foo(x: i32) !void { | ||
| 8 | switch (x) { | ||
| 9 | 0 ... 10 => return error.Foo, | ||
| 10 | 11 ... 20 => return error.Bar, | ||
| 11 | else => {}, | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=llvm | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // :2:34: error: ranges not allowed when switching on type '@typeInfo(@typeInfo(@TypeOf(tmp.foo)).Fn.return_type.?).ErrorUnion.error_set' | ||
| 20 | // :3:19: note: range here | ||
test/cases/compile_errors/reading_past_end_of_pointer_casted_array.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | comptime { | ||
| 2 | const array: [4]u8 = "aoeu".*; | ||
| 3 | const sub_array = array[1..]; | ||
| 4 | const int_ptr = @ptrCast(*const u24, sub_array); | ||
| 5 | const deref = int_ptr.*; | ||
| 6 | _ = deref; | ||
| 7 | } | ||
| 8 | |||
| 9 | // error | ||
| 10 | // backend=stage2 | ||
| 11 | // target=native | ||
| 12 | // | ||
| 13 | // :5:26: error: dereference of '*const u24' exceeds bounds of containing decl of type '[4]u8' | ||
test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const Struct = struct { | ||
| 2 | a: u32, | ||
| 3 | }; | ||
| 4 | fn getIndex() usize { | ||
| 5 | return 2; | ||
| 6 | } | ||
| 7 | export fn entry() void { | ||
| 8 | const index = getIndex(); | ||
| 9 | const field = @typeInfo(Struct).Struct.fields[index]; | ||
| 10 | _ = field; | ||
| 11 | } | ||
| 12 | |||
| 13 | // error | ||
| 14 | // backend=stage2 | ||
| 15 | // target=native | ||
| 16 | // | ||
| 17 | // :9:51: error: values of type '[]const builtin.Type.StructField' must be comptime known, but index value is runtime known | ||
| 18 | // :287:21: note: struct requires comptime because of this field | ||
| 19 | // :287:21: note: types are not available at runtime | ||
| 20 | // :290:20: note: struct requires comptime because of this field | ||
test/cases/compile_errors/stage1/obj/non-inline_for_loop_on_a_type_that_requires_comptime.zig deleted-14| ... | @@ -1,14 +0,0 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | name: []const u8, | ||
| 3 | T: type, | ||
| 4 | }; | ||
| 5 | export fn entry() void { | ||
| 6 | const xx: [2]Foo = undefined; | ||
| 7 | for (xx) |f| { _ = f;} | ||
| 8 | } | ||
| 9 | |||
| 10 | // error | ||
| 11 | // backend=stage1 | ||
| 12 | // target=native | ||
| 13 | // | ||
| 14 | // tmp.zig:7:5: error: values of type 'Foo' must be comptime known, but index value is runtime known | ||
test/cases/compile_errors/stage1/obj/ptrCast_a_0_bit_type_to_a_non-_0_bit_type.zig deleted-13| ... | @@ -1,13 +0,0 @@ | ||
| 1 | export fn entry() bool { | ||
| 2 | var x: u0 = 0; | ||
| 3 | const p = @ptrCast(?*u0, &x); | ||
| 4 | return p == null; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:15: error: '*u0' and '?*u0' do not have the same in-memory representation | ||
| 12 | // tmp.zig:3:31: note: '*u0' has no in-memory bits | ||
| 13 | // tmp.zig:3:24: note: '?*u0' has in-memory bits | ||
test/cases/compile_errors/stage1/obj/ptrToInt_on_void.zig deleted-9| ... | @@ -1,9 +0,0 @@ | ||
| 1 | export fn entry() bool { | ||
| 2 | return @ptrToInt(&{}) == @ptrToInt(&{}); | ||
| 3 | } | ||
| 4 | |||
| 5 | // error | ||
| 6 | // backend=stage1 | ||
| 7 | // target=native | ||
| 8 | // | ||
| 9 | // tmp.zig:2:23: error: pointer to size 0 type has no address | ||
test/cases/compile_errors/stage1/obj/range_operator_in_switch_used_on_error_set.zig deleted-19| ... | @@ -1,19 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | try foo(452) catch |err| switch (err) { | ||
| 3 | error.A ... error.B => {}, | ||
| 4 | else => {}, | ||
| 5 | }; | ||
| 6 | } | ||
| 7 | fn foo(x: i32) !void { | ||
| 8 | switch (x) { | ||
| 9 | 0 ... 10 => return error.Foo, | ||
| 10 | 11 ... 20 => return error.Bar, | ||
| 11 | else => {}, | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=stage1 | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // tmp.zig:3:17: error: operator not allowed for errors | ||
test/cases/compile_errors/stage1/obj/reading_past_end_of_pointer_casted_array.zig deleted-13| ... | @@ -1,13 +0,0 @@ | ||
| 1 | comptime { | ||
| 2 | const array: [4]u8 = "aoeu".*; | ||
| 3 | const sub_array = array[1..]; | ||
| 4 | const int_ptr = @ptrCast(*const u24, sub_array); | ||
| 5 | const deref = int_ptr.*; | ||
| 6 | _ = deref; | ||
| 7 | } | ||
| 8 | |||
| 9 | // error | ||
| 10 | // backend=stage1 | ||
| 11 | // target=native | ||
| 12 | // | ||
| 13 | // tmp.zig:5:26: error: attempt to read 4 bytes from [4]u8 at index 1 which is 3 bytes | ||
test/cases/compile_errors/stage1/obj/recursive_inferred_error_set.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | foo() catch unreachable; | ||
| 3 | } | ||
| 4 | fn foo() !void { | ||
| 5 | try foo(); | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage1 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // tmp.zig:5:5: error: cannot resolve inferred error set '@typeInfo(@typeInfo(@TypeOf(foo)).Fn.return_type.?).ErrorUnion.error_set': function 'foo' not fully analyzed yet | ||
test/cases/compile_errors/stage1/obj/runtime_index_into_comptime_type_slice.zig deleted-17| ... | @@ -1,17 +0,0 @@ | ||
| 1 | const Struct = struct { | ||
| 2 | a: u32, | ||
| 3 | }; | ||
| 4 | fn getIndex() usize { | ||
| 5 | return 2; | ||
| 6 | } | ||
| 7 | export fn entry() void { | ||
| 8 | const index = getIndex(); | ||
| 9 | const field = @typeInfo(Struct).Struct.fields[index]; | ||
| 10 | _ = field; | ||
| 11 | } | ||
| 12 | |||
| 13 | // error | ||
| 14 | // backend=stage1 | ||
| 15 | // target=native | ||
| 16 | // | ||
| 17 | // tmp.zig:9:51: error: values of type 'std.builtin.Type.StructField' must be comptime known, but index value is runtime known | ||
test/cases/compile_errors/stage1/obj/slicing_of_global_undefined_pointer.zig deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | var buf: *[1]u8 = undefined; | ||
| 2 | export fn entry() void { | ||
| 3 | _ = buf[0..1]; | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage1 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // tmp.zig:3:12: error: non-zero length slice of undefined pointer | ||
test/cases/compile_errors/stage1/ptrCast_a_0_bit_type_to_a_non-_0_bit_type.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | export fn entry() bool { | ||
| 2 | var x: u0 = 0; | ||
| 3 | const p = @ptrCast(?*u0, &x); | ||
| 4 | return p == null; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:15: error: '*u0' and '?*u0' do not have the same in-memory representation | ||
| 12 | // tmp.zig:3:31: note: '*u0' has no in-memory bits | ||
| 13 | // tmp.zig:3:24: note: '?*u0' has in-memory bits | ||
test/cases/compile_errors/stage1/ptrToInt_on_void.zig created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | export fn entry() bool { | ||
| 2 | return @ptrToInt(&{}) == @ptrToInt(&{}); | ||
| 3 | } | ||
| 4 | |||
| 5 | // error | ||
| 6 | // backend=stage1 | ||
| 7 | // target=native | ||
| 8 | // | ||
| 9 | // tmp.zig:2:23: error: pointer to size 0 type has no address | ||
test/cases/compile_errors/stage1/recursive_inferred_error_set.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | foo() catch unreachable; | ||
| 3 | } | ||
| 4 | fn foo() !void { | ||
| 5 | try foo(); | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage1 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // tmp.zig:5:5: error: cannot resolve inferred error set '@typeInfo(@typeInfo(@TypeOf(foo)).Fn.return_type.?).ErrorUnion.error_set': function 'foo' not fully analyzed yet | ||
test/cases/compile_errors/stage1/slicing_of_global_undefined_pointer.zig created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | var buf: *[1]u8 = undefined; | ||
| 2 | export fn entry() void { | ||
| 3 | _ = buf[0..1]; | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage1 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // tmp.zig:3:12: error: non-zero length slice of undefined pointer | ||