authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-31 13:38:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:58-07:00
log870e3843c5736def21234ca8b7159b179985505c
tree599fc65f4c195703d6687e72e01fa8b104407bdc
parentb2391a7d4425418a29598523dcbdf2bfc9325ecd

Sema: elide comptime-checked slice safety

Before, Zig would emit a start<=end safety check for `foo[1..2]` even though it was already checked at compile-time.

1 files changed, 20 insertions(+), 26 deletions(-)

src/Sema.zig+20-26
...@@ -24146,20 +24146,6 @@ fn panicIndexOutOfBounds(...@@ -24146,20 +24146,6 @@ fn panicIndexOutOfBounds(
24146 try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });24146 try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });
24147}24147}
2414824148
24149fn panicStartGreaterThanEnd(
24150 sema: *Sema,
24151 parent_block: *Block,
24152 start: Air.Inst.Ref,
24153 end: Air.Inst.Ref,
24154) !void {
24155 assert(!parent_block.is_comptime);
24156 const ok = try parent_block.addBinOp(.cmp_lte, start, end);
24157 if (!sema.mod.comp.formatted_panics) {
24158 return sema.addSafetyCheck(parent_block, ok, .start_index_greater_than_end);
24159 }
24160 try sema.safetyCheckFormatted(parent_block, ok, "panicStartGreaterThanEnd", &.{ start, end });
24161}
24162
24163fn panicInactiveUnionField(24149fn panicInactiveUnionField(
24164 sema: *Sema,24150 sema: *Sema,
24165 parent_block: *Block,24151 parent_block: *Block,
...@@ -30209,11 +30195,12 @@ fn analyzeSlice(...@@ -30209,11 +30195,12 @@ fn analyzeSlice(
30209 };30195 };
30210 const slice_sentinel = if (sentinel_opt != .none) sentinel else null;30196 const slice_sentinel = if (sentinel_opt != .none) sentinel else null;
3021130197
30198 var checked_start_lte_end = by_length;
30199 var runtime_src: ?LazySrcLoc = null;
30200
30212 // requirement: start <= end30201 // requirement: start <= end
30213 var need_start_gt_end_check = true;
30214 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {30202 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
30215 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {30203 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
30216 need_start_gt_end_check = false;
30217 if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {30204 if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {
30218 return sema.fail(30205 return sema.fail(
30219 block,30206 block,
...@@ -30225,6 +30212,7 @@ fn analyzeSlice(...@@ -30225,6 +30212,7 @@ fn analyzeSlice(
30225 },30212 },
30226 );30213 );
30227 }30214 }
30215 checked_start_lte_end = true;
30228 if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: {30216 if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: {
30229 const expected_sentinel = sentinel orelse break :sentinel_check;30217 const expected_sentinel = sentinel orelse break :sentinel_check;
30230 const start_int = start_val.getUnsignedInt(mod).?;30218 const start_int = start_val.getUnsignedInt(mod).?;
...@@ -30266,13 +30254,26 @@ fn analyzeSlice(...@@ -30266,13 +30254,26 @@ fn analyzeSlice(
30266 };30254 };
30267 return sema.failWithOwnedErrorMsg(msg);30255 return sema.failWithOwnedErrorMsg(msg);
30268 }30256 }
30257 } else {
30258 runtime_src = ptr_src;
30269 }30259 }
30260 } else {
30261 runtime_src = start_src;
30270 }30262 }
30263 } else {
30264 runtime_src = end_src;
30271 }30265 }
3027230266
30273 if (!by_length and block.wantSafety() and !block.is_comptime and need_start_gt_end_check) {30267 if (!checked_start_lte_end and block.wantSafety() and !block.is_comptime) {
30274 // requirement: start <= end30268 // requirement: start <= end
30275 try sema.panicStartGreaterThanEnd(block, start, end);30269 assert(!block.is_comptime);
30270 try sema.requireRuntimeBlock(block, src, runtime_src.?);
30271 const ok = try block.addBinOp(.cmp_lte, start, end);
30272 if (!sema.mod.comp.formatted_panics) {
30273 try sema.addSafetyCheck(block, ok, .start_index_greater_than_end);
30274 } else {
30275 try sema.safetyCheckFormatted(block, ok, "panicStartGreaterThanEnd", &.{ start, end });
30276 }
30276 }30277 }
30277 const new_len = if (by_length)30278 const new_len = if (by_length)
30278 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)30279 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
...@@ -30354,14 +30355,7 @@ fn analyzeSlice(...@@ -30354,14 +30355,7 @@ fn analyzeSlice(
30354 .size = .Slice,30355 .size = .Slice,
30355 });30356 });
3035630357
30357 const runtime_src = if ((try sema.resolveMaybeUndefVal(ptr_or_slice)) == null)30358 try sema.requireRuntimeBlock(block, src, runtime_src.?);
30358 ptr_src
30359 else if ((try sema.resolveMaybeUndefVal(start)) == null)
30360 start_src
30361 else
30362 end_src;
30363
30364 try sema.requireRuntimeBlock(block, src, runtime_src);
30365 if (block.wantSafety()) {30359 if (block.wantSafety()) {
30366 // requirement: slicing C ptr is non-null30360 // requirement: slicing C ptr is non-null
30367 if (ptr_ptr_child_ty.isCPtr(mod)) {30361 if (ptr_ptr_child_ty.isCPtr(mod)) {