| ... | ... | @@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in |
| 2352 | 2352 | }); |
| 2353 | 2353 | } |
| 2354 | 2354 | |
| 2355 | pub fn failWithUndefSliceLen(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | return sema.fail(block, src, "use of slice with undefined length here causes illegal behavior", .{}); |
| 2357 | } |
| 2358 | |
| 2355 | 2359 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | 2360 | return sema.fail(block, src, "division by zero here causes illegal behavior", .{}); |
| 2357 | 2361 | } |
| ... | ... | @@ -3113,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 3113 | 3117 | try sema.validateDeref(block, src, operand, operand_ty); |
| 3114 | 3118 | |
| 3115 | 3119 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 3116 | | return switch (ptr_info.flags.size) { |
| 3117 | | .many, .slice => unreachable, // cannot be dereferenced |
| 3118 | | .c => single_ptr: { |
| 3120 | return single_ptr: switch (ptr_info.flags.size) { |
| 3121 | .many => unreachable, // cannot be dereferenced directly |
| 3122 | .slice => { |
| 3123 | const slice_val = sema.resolveValue(operand).?; |
| 3124 | const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice; |
| 3125 | break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice)); |
| 3126 | }, |
| 3127 | .c => { |
| 3119 | 3128 | const single_ptr_ty = try pt.ptrType(p: { |
| 3120 | 3129 | var p = ptr_info; |
| 3121 | 3130 | p.flags.size = .one; |
| ... | ... | @@ -3149,18 +3158,26 @@ fn validateDeref( |
| 3149 | 3158 | ) CompileError!void { |
| 3150 | 3159 | const pt = sema.pt; |
| 3151 | 3160 | const zcu = pt.zcu; |
| 3161 | const ip = &zcu.intern_pool; |
| 3152 | 3162 | if (ty.zigTypeTag(zcu) != .pointer) { |
| 3153 | 3163 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); |
| 3154 | | } else switch (ty.ptrSize(zcu)) { |
| 3155 | | .one, .c => {}, |
| 3164 | } |
| 3165 | const size = ty.ptrSize(zcu); |
| 3166 | switch (size) { |
| 3156 | 3167 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}), |
| 3157 | | .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{ty.fmt(pt)}), |
| 3168 | .one, .c, .slice => {}, |
| 3158 | 3169 | } |
| 3159 | 3170 | if (sema.resolveValue(ref)) |val| { |
| 3160 | 3171 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. |
| 3161 | 3172 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { |
| 3162 | 3173 | return sema.fail(block, src, "cannot dereference undefined value", .{}); |
| 3163 | 3174 | } |
| 3175 | // We need a defined slice length for the array type the slice should be dereferenced to. |
| 3176 | if (size == .slice and ip.indexToKey(val.toIntern()).slice.len == .undef_usize) { |
| 3177 | return sema.fail(block, src, "cannot dereference slice with undefined length", .{}); |
| 3178 | } |
| 3179 | } else if (size == .slice) { |
| 3180 | return sema.fail(block, src, "index syntax required to access runtime-known slice", .{}); |
| 3164 | 3181 | } |
| 3165 | 3182 | } |
| 3166 | 3183 | |
| ... | ... | @@ -28241,9 +28258,94 @@ fn coerceExtra( |
| 28241 | 28258 | }, |
| 28242 | 28259 | else => {}, |
| 28243 | 28260 | }, |
| 28244 | | .one => {}, |
| 28261 | // []T to *[n]T |
| 28262 | .one => slice_to_array_ptr: { |
| 28263 | if (!inst_ty.isSlice(zcu)) break :slice_to_array_ptr; |
| 28264 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :slice_to_array_ptr; |
| 28265 | const array_ty: Type = .fromInterned(dest_info.child); |
| 28266 | if (array_ty.zigTypeTag(zcu) != .array) break :slice_to_array_ptr; |
| 28267 | const inst_val = maybe_inst_val orelse { |
| 28268 | if (!opts.report_err) return error.NotCoercible; |
| 28269 | return sema.fail( |
| 28270 | block, |
| 28271 | inst_src, |
| 28272 | "coercion from slice to array pointer type '{f}' requires length to be known at compile-time", |
| 28273 | .{dest_ty.fmt(pt)}, |
| 28274 | ); |
| 28275 | }; |
| 28276 | |
| 28277 | const slice: InternPool.Key.Slice = slice: { |
| 28278 | switch (ip.indexToKey(inst_val.toIntern())) { |
| 28279 | .undef => {}, |
| 28280 | .slice => |slice| if (slice.len != .undef_usize) break :slice slice, |
| 28281 | else => unreachable, |
| 28282 | } |
| 28283 | if (!opts.report_err) return error.NotCoercible; |
| 28284 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 28285 | const msg = try sema.errMsg(inst_src, "slice with undefined length cannot cast into array pointer type '{f}'", .{ |
| 28286 | dest_ty.fmt(pt), |
| 28287 | }); |
| 28288 | errdefer msg.destroy(gpa); |
| 28289 | try sema.errNote(inst_src, msg, "length of slice must be defined and match length of array type", .{}); |
| 28290 | break :msg msg; |
| 28291 | }); |
| 28292 | }; |
| 28293 | const slice_len = Value.fromInterned(slice.len).toUnsignedInt(zcu); |
| 28294 | if (array_ty.arrayLen(zcu) != slice_len) { |
| 28295 | if (!opts.report_err) return error.NotCoercible; |
| 28296 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 28297 | const msg = try sema.errMsg(inst_src, "slice of length {d} cannot cast into array pointer type '{f}'", .{ |
| 28298 | slice_len, dest_ty.fmt(pt), |
| 28299 | }); |
| 28300 | errdefer msg.destroy(gpa); |
| 28301 | try sema.errNote(inst_src, msg, "length of slice must match length of array type", .{}); |
| 28302 | break :msg msg; |
| 28303 | }); |
| 28304 | } |
| 28305 | |
| 28306 | const inst_elem_ty = inst_ty.childType(zcu); |
| 28307 | const dest_elem_ty = array_ty.childType(zcu); |
| 28308 | const dest_is_mut = !dest_info.flags.is_const; |
| 28309 | switch (try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { |
| 28310 | .ok => {}, |
| 28311 | else => |elem_res| { |
| 28312 | in_memory_result = .{ .ptr_child = .{ |
| 28313 | .child = try elem_res.dupe(sema.arena), |
| 28314 | .actual = inst_elem_ty, |
| 28315 | .wanted = dest_elem_ty, |
| 28316 | } }; |
| 28317 | break :slice_to_array_ptr; |
| 28318 | }, |
| 28319 | } |
| 28320 | |
| 28321 | if (array_ty.sentinel(zcu)) |array_sentinel| { |
| 28322 | if (inst_ty.sentinel(zcu)) |slice_sentinel| { |
| 28323 | if (array_sentinel.toIntern() != |
| 28324 | (try pt.getCoerced(slice_sentinel, dest_elem_ty)).toIntern()) |
| 28325 | { |
| 28326 | in_memory_result = .{ .ptr_sentinel = .{ |
| 28327 | .actual = slice_sentinel, |
| 28328 | .wanted = array_sentinel, |
| 28329 | .ty = dest_elem_ty, |
| 28330 | } }; |
| 28331 | break :slice_to_array_ptr; |
| 28332 | } |
| 28333 | } else { |
| 28334 | in_memory_result = .{ .ptr_sentinel = .{ |
| 28335 | .actual = .@"unreachable", |
| 28336 | .wanted = array_sentinel, |
| 28337 | .ty = dest_elem_ty, |
| 28338 | } }; |
| 28339 | break :slice_to_array_ptr; |
| 28340 | } |
| 28341 | } |
| 28342 | |
| 28343 | const array_ptr = try pt.sliceToArrayPtr(slice); |
| 28344 | return sema.coerceCompatiblePtrs(block, dest_ty, .fromValue(array_ptr), inst_src); |
| 28345 | }, |
| 28245 | 28346 | .slice => to_slice: { |
| 28246 | 28347 | if (inst_ty.zigTypeTag(zcu) == .array) { |
| 28348 | if (!opts.report_err) return error.NotCoercible; |
| 28247 | 28349 | return sema.fail( |
| 28248 | 28350 | block, |
| 28249 | 28351 | inst_src, |
| ... | ... | @@ -28271,6 +28373,7 @@ fn coerceExtra( |
| 28271 | 28373 | |
| 28272 | 28374 | // pointer to tuple to slice |
| 28273 | 28375 | if (!dest_info.flags.is_const) { |
| 28376 | if (!opts.report_err) return error.NotCoercible; |
| 28274 | 28377 | const err_msg = err_msg: { |
| 28275 | 28378 | const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)}); |
| 28276 | 28379 | errdefer err_msg.destroy(sema.gpa); |
| ... | ... | @@ -28366,6 +28469,7 @@ fn coerceExtra( |
| 28366 | 28469 | if (maybe_inst_val) |val| { |
| 28367 | 28470 | const result_val = try val.floatCast(dest_ty, pt); |
| 28368 | 28471 | if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) { |
| 28472 | if (!opts.report_err) return error.NotCoercible; |
| 28369 | 28473 | return sema.fail( |
| 28370 | 28474 | block, |
| 28371 | 28475 | inst_src, |
| ... | ... | @@ -28423,12 +28527,15 @@ fn coerceExtra( |
| 28423 | 28527 | break :fits result_big_int.toConst().eql(operand_big_int); |
| 28424 | 28528 | }, |
| 28425 | 28529 | }; |
| 28426 | | if (!fits) return sema.fail( |
| 28427 | | block, |
| 28428 | | inst_src, |
| 28429 | | "type '{f}' cannot represent integer value '{f}'", |
| 28430 | | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, |
| 28431 | | ); |
| 28530 | if (!fits) { |
| 28531 | if (!opts.report_err) return error.NotCoercible; |
| 28532 | return sema.fail( |
| 28533 | block, |
| 28534 | inst_src, |
| 28535 | "type '{f}' cannot represent integer value '{f}'", |
| 28536 | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, |
| 28537 | ); |
| 28538 | } |
| 28432 | 28539 | return .fromValue(result_val); |
| 28433 | 28540 | }, |
| 28434 | 28541 | else => {}, |
| ... | ... | @@ -28439,6 +28546,7 @@ fn coerceExtra( |
| 28439 | 28546 | const val = sema.resolveValue(inst).?; |
| 28440 | 28547 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; |
| 28441 | 28548 | const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { |
| 28549 | if (!opts.report_err) return error.NotCoercible; |
| 28442 | 28550 | return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ |
| 28443 | 28551 | string.fmt(&zcu.intern_pool), dest_ty.fmt(pt), |
| 28444 | 28552 | }); |
| ... | ... | @@ -30940,8 +31048,11 @@ fn analyzeLoad( |
| 30940 | 31048 | }; |
| 30941 | 31049 | |
| 30942 | 31050 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 30943 | | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| 30944 | | return Air.internedToRef(elem_val.toIntern()); |
| 31051 | if (switch (ptr_ty.ptrSize(zcu)) { |
| 31052 | .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val), |
| 31053 | else => try sema.pointerDeref(block, src, ptr_val, ptr_ty), |
| 31054 | }) |elem_val| { |
| 31055 | return .fromValue(elem_val); |
| 30945 | 31056 | } |
| 30946 | 31057 | } |
| 30947 | 31058 | |
| ... | ... | @@ -34615,7 +34726,6 @@ fn maybeDerefSliceAsArray( |
| 34615 | 34726 | ) CompileError!?Value { |
| 34616 | 34727 | const pt = sema.pt; |
| 34617 | 34728 | const zcu = pt.zcu; |
| 34618 | | const ip = &zcu.intern_pool; |
| 34619 | 34729 | const slice_ty = slice_val.typeOf(zcu); |
| 34620 | 34730 | assert(slice_ty.zigTypeTag(zcu) == .pointer); |
| 34621 | 34731 | switch (slice_ty.ptrInfo(zcu).flags.size) { |
| ... | ... | @@ -34623,26 +34733,14 @@ fn maybeDerefSliceAsArray( |
| 34623 | 34733 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), |
| 34624 | 34734 | .many, .c => unreachable, |
| 34625 | 34735 | } |
| 34626 | | const slice = switch (ip.indexToKey(slice_val.toIntern())) { |
| 34736 | const slice = switch (zcu.intern_pool.indexToKey(slice_val.toIntern())) { |
| 34627 | 34737 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34628 | 34738 | .slice => |slice| slice, |
| 34629 | 34739 | else => unreachable, |
| 34630 | 34740 | }; |
| 34631 | | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); |
| 34632 | | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); |
| 34633 | | const array_ty = try pt.arrayType(.{ |
| 34634 | | .child = elem_ty.toIntern(), |
| 34635 | | .len = len, |
| 34636 | | }); |
| 34637 | | const ptr_ty = try pt.ptrType(p: { |
| 34638 | | var p = Type.fromInterned(slice.ty).ptrInfo(zcu); |
| 34639 | | p.flags.size = .one; |
| 34640 | | p.child = array_ty.toIntern(); |
| 34641 | | p.sentinel = .none; |
| 34642 | | break :p p; |
| 34643 | | }); |
| 34644 | | const casted_ptr = try pt.getCoerced(Value.fromInterned(slice.ptr), ptr_ty); |
| 34645 | | return sema.pointerDeref(block, src, casted_ptr, ptr_ty); |
| 34741 | if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src); |
| 34742 | const casted_ptr = try pt.sliceToArrayPtr(slice); |
| 34743 | return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu)); |
| 34646 | 34744 | } |
| 34647 | 34745 | |
| 34648 | 34746 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { |