| ... | @@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in | ... | @@ -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 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { | 2359 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | return sema.fail(block, src, "division by zero here causes illegal behavior", .{}); | 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,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 3113 | try sema.validateDeref(block, src, operand, operand_ty); | 3117 | try sema.validateDeref(block, src, operand, operand_ty); |
| 3114 | | 3118 | |
| 3115 | const ptr_info = operand_ty.ptrInfo(zcu); | 3119 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 3116 | return switch (ptr_info.flags.size) { | 3120 | return single_ptr: switch (ptr_info.flags.size) { |
| 3117 | .many, .slice => unreachable, // cannot be dereferenced | 3121 | .many => unreachable, // cannot be dereferenced directly |
| 3118 | .c => single_ptr: { | 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 | const single_ptr_ty = try pt.ptrType(p: { | 3128 | const single_ptr_ty = try pt.ptrType(p: { |
| 3120 | var p = ptr_info; | 3129 | var p = ptr_info; |
| 3121 | p.flags.size = .one; | 3130 | p.flags.size = .one; |
| ... | @@ -3149,18 +3158,26 @@ fn validateDeref( | ... | @@ -3149,18 +3158,26 @@ fn validateDeref( |
| 3149 | ) CompileError!void { | 3158 | ) CompileError!void { |
| 3150 | const pt = sema.pt; | 3159 | const pt = sema.pt; |
| 3151 | const zcu = pt.zcu; | 3160 | const zcu = pt.zcu; |
| | 3161 | const ip = &zcu.intern_pool; |
| 3152 | if (ty.zigTypeTag(zcu) != .pointer) { | 3162 | if (ty.zigTypeTag(zcu) != .pointer) { |
| 3153 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); | 3163 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); |
| 3154 | } else switch (ty.ptrSize(zcu)) { | 3164 | } |
| 3155 | .one, .c => {}, | 3165 | const size = ty.ptrSize(zcu); |
| | 3166 | switch (size) { |
| 3156 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}), | 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 | if (sema.resolveValue(ref)) |val| { | 3170 | if (sema.resolveValue(ref)) |val| { |
| 3160 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. | 3171 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. |
| 3161 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { | 3172 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { |
| 3162 | return sema.fail(block, src, "cannot dereference undefined value", .{}); | 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,9 +28258,94 @@ fn coerceExtra( |
| 28241 | }, | 28258 | }, |
| 28242 | else => {}, | 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 | .slice => to_slice: { | 28346 | .slice => to_slice: { |
| 28246 | if (inst_ty.zigTypeTag(zcu) == .array) { | 28347 | if (inst_ty.zigTypeTag(zcu) == .array) { |
| | 28348 | if (!opts.report_err) return error.NotCoercible; |
| 28247 | return sema.fail( | 28349 | return sema.fail( |
| 28248 | block, | 28350 | block, |
| 28249 | inst_src, | 28351 | inst_src, |
| ... | @@ -28271,6 +28373,7 @@ fn coerceExtra( | ... | @@ -28271,6 +28373,7 @@ fn coerceExtra( |
| 28271 | | 28373 | |
| 28272 | // pointer to tuple to slice | 28374 | // pointer to tuple to slice |
| 28273 | if (!dest_info.flags.is_const) { | 28375 | if (!dest_info.flags.is_const) { |
| | 28376 | if (!opts.report_err) return error.NotCoercible; |
| 28274 | const err_msg = err_msg: { | 28377 | const err_msg = err_msg: { |
| 28275 | const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)}); | 28378 | const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)}); |
| 28276 | errdefer err_msg.destroy(sema.gpa); | 28379 | errdefer err_msg.destroy(sema.gpa); |
| ... | @@ -28366,6 +28469,7 @@ fn coerceExtra( | ... | @@ -28366,6 +28469,7 @@ fn coerceExtra( |
| 28366 | if (maybe_inst_val) |val| { | 28469 | if (maybe_inst_val) |val| { |
| 28367 | const result_val = try val.floatCast(dest_ty, pt); | 28470 | const result_val = try val.floatCast(dest_ty, pt); |
| 28368 | if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) { | 28471 | if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) { |
| | 28472 | if (!opts.report_err) return error.NotCoercible; |
| 28369 | return sema.fail( | 28473 | return sema.fail( |
| 28370 | block, | 28474 | block, |
| 28371 | inst_src, | 28475 | inst_src, |
| ... | @@ -28423,12 +28527,15 @@ fn coerceExtra( | ... | @@ -28423,12 +28527,15 @@ fn coerceExtra( |
| 28423 | break :fits result_big_int.toConst().eql(operand_big_int); | 28527 | break :fits result_big_int.toConst().eql(operand_big_int); |
| 28424 | }, | 28528 | }, |
| 28425 | }; | 28529 | }; |
| 28426 | if (!fits) return sema.fail( | 28530 | if (!fits) { |
| 28427 | block, | 28531 | if (!opts.report_err) return error.NotCoercible; |
| 28428 | inst_src, | 28532 | return sema.fail( |
| 28429 | "type '{f}' cannot represent integer value '{f}'", | 28533 | block, |
| 28430 | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, | 28534 | inst_src, |
| 28431 | ); | 28535 | "type '{f}' cannot represent integer value '{f}'", |
| | 28536 | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, |
| | 28537 | ); |
| | 28538 | } |
| 28432 | return .fromValue(result_val); | 28539 | return .fromValue(result_val); |
| 28433 | }, | 28540 | }, |
| 28434 | else => {}, | 28541 | else => {}, |
| ... | @@ -28439,6 +28546,7 @@ fn coerceExtra( | ... | @@ -28439,6 +28546,7 @@ fn coerceExtra( |
| 28439 | const val = sema.resolveValue(inst).?; | 28546 | const val = sema.resolveValue(inst).?; |
| 28440 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; | 28547 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; |
| 28441 | const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { | 28548 | const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { |
| | 28549 | if (!opts.report_err) return error.NotCoercible; |
| 28442 | return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ | 28550 | return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ |
| 28443 | string.fmt(&zcu.intern_pool), dest_ty.fmt(pt), | 28551 | string.fmt(&zcu.intern_pool), dest_ty.fmt(pt), |
| 28444 | }); | 28552 | }); |
| ... | @@ -30940,8 +31048,11 @@ fn analyzeLoad( | ... | @@ -30940,8 +31048,11 @@ fn analyzeLoad( |
| 30940 | }; | 31048 | }; |
| 30941 | | 31049 | |
| 30942 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 31050 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 30943 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { | 31051 | if (switch (ptr_ty.ptrSize(zcu)) { |
| 30944 | return Air.internedToRef(elem_val.toIntern()); | 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,7 +34726,6 @@ fn maybeDerefSliceAsArray( |
| 34615 | ) CompileError!?Value { | 34726 | ) CompileError!?Value { |
| 34616 | const pt = sema.pt; | 34727 | const pt = sema.pt; |
| 34617 | const zcu = pt.zcu; | 34728 | const zcu = pt.zcu; |
| 34618 | const ip = &zcu.intern_pool; | | |
| 34619 | const slice_ty = slice_val.typeOf(zcu); | 34729 | const slice_ty = slice_val.typeOf(zcu); |
| 34620 | assert(slice_ty.zigTypeTag(zcu) == .pointer); | 34730 | assert(slice_ty.zigTypeTag(zcu) == .pointer); |
| 34621 | switch (slice_ty.ptrInfo(zcu).flags.size) { | 34731 | switch (slice_ty.ptrInfo(zcu).flags.size) { |
| ... | @@ -34623,26 +34733,14 @@ fn maybeDerefSliceAsArray( | ... | @@ -34623,26 +34733,14 @@ fn maybeDerefSliceAsArray( |
| 34623 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), | 34733 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), |
| 34624 | .many, .c => unreachable, | 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 | .undef => return sema.failWithUseOfUndef(block, src, null), | 34737 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34628 | .slice => |slice| slice, | 34738 | .slice => |slice| slice, |
| 34629 | else => unreachable, | 34739 | else => unreachable, |
| 34630 | }; | 34740 | }; |
| 34631 | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); | 34741 | if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src); |
| 34632 | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); | 34742 | const casted_ptr = try pt.sliceToArrayPtr(slice); |
| 34633 | const array_ty = try pt.arrayType(.{ | 34743 | return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu)); |
| 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); | | |
| 34646 | } | 34744 | } |
| 34647 | | 34745 | |
| 34648 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { | 34746 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { |