authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-15 21:18:42+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-17 13:22:09+02:00
log58caed1c71179f48c4e7bffadef0392fa8381e72
tree7dec9c4a86979d129d824ac3124054d89eb1c849
parent90477e5c10c9c263a3c0038e1ae7b814d2c5397e

Sema: make is_non_{null,err} stricter about types

Closes #13023

5 files changed, 50 insertions(+), 12 deletions(-)

src/AstGen.zig+2-2
......@@ -6071,7 +6071,7 @@ fn whileExpr(
60716071 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
60726072 break :c .{
60736073 .inst = err_union,
6074 .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.then_expr),
6074 .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.cond_expr),
60756075 };
60766076 } else if (while_full.payload_token) |_| {
60776077 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
......@@ -6079,7 +6079,7 @@ fn whileExpr(
60796079 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
60806080 break :c .{
60816081 .inst = optional,
6082 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.then_expr),
6082 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr),
60836083 };
60846084 } else {
60856085 const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr);
src/Sema.zig+23
......@@ -16356,6 +16356,15 @@ fn finishCondBr(
1635616356 return Air.indexToRef(block_inst);
1635716357}
1635816358
16359fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16360 switch (ty.zigTypeTag()) {
16361 .Optional, .Null, .Undefined => return,
16362 .Pointer => if (ty.isPtrLikeOptional()) return,
16363 else => {},
16364 }
16365 return sema.failWithExpectedOptionalType(block, src, ty);
16366}
16367
1635916368fn zirIsNonNull(
1636016369 sema: *Sema,
1636116370 block: *Block,
......@@ -16367,6 +16376,7 @@ fn zirIsNonNull(
1636716376 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1636816377 const src = inst_data.src();
1636916378 const operand = try sema.resolveInst(inst_data.operand);
16379 try sema.checkNullableType(block, src, sema.typeOf(operand));
1637016380 return sema.analyzeIsNull(block, src, operand, true);
1637116381}
1637216382
......@@ -16381,6 +16391,7 @@ fn zirIsNonNullPtr(
1638116391 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1638216392 const src = inst_data.src();
1638316393 const ptr = try sema.resolveInst(inst_data.operand);
16394 try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2());
1638416395 if ((try sema.resolveMaybeUndefVal(ptr)) == null) {
1638516396 return block.addUnOp(.is_non_null_ptr, ptr);
1638616397 }
......@@ -16388,12 +16399,23 @@ fn zirIsNonNullPtr(
1638816399 return sema.analyzeIsNull(block, src, loaded, true);
1638916400}
1639016401
16402fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16403 switch (ty.zigTypeTag()) {
16404 .ErrorSet, .ErrorUnion, .Undefined => return,
16405 else => return sema.fail(block, src, "expected error union type, found '{}'", .{
16406 ty.fmt(sema.mod),
16407 }),
16408 }
16409}
16410
1639116411fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1639216412 const tracy = trace(@src());
1639316413 defer tracy.end();
1639416414
1639516415 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16416 const src = inst_data.src();
1639616417 const operand = try sema.resolveInst(inst_data.operand);
16418 try sema.checkErrorType(block, src, sema.typeOf(operand));
1639716419 return sema.analyzeIsNonErr(block, inst_data.src(), operand);
1639816420}
1639916421
......@@ -16404,6 +16426,7 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1640416426 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1640516427 const src = inst_data.src();
1640616428 const ptr = try sema.resolveInst(inst_data.operand);
16429 try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2());
1640716430 const loaded = try sema.analyzeLoad(block, src, ptr, src);
1640816431 return sema.analyzeIsNonErr(block, src, loaded);
1640916432}
src/link/MachO/load_commands.zig+1-1
......@@ -36,7 +36,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
3636 // LC_DYLD_INFO_ONLY
3737 sizeofcmds += @sizeOf(macho.dyld_info_command);
3838 // LC_FUNCTION_STARTS
39 if (has_text_segment and ctx.wants_function_starts) |_| {
39 if (has_text_segment and ctx.wants_function_starts) {
4040 sizeofcmds += @sizeOf(macho.linkedit_data_command);
4141 }
4242 // LC_DATA_IN_CODE
test/cases/compile_errors/invalid_capture_type.zig created+24
......@@ -0,0 +1,24 @@
1export fn f1() void {
2 if (true) |x| { _ = x; }
3}
4export fn f2() void {
5 if (@as(usize, 5)) |_| {}
6}
7export fn f3() void {
8 if (@as(usize, 5)) |_| {} else |_| {}
9}
10export fn f4() void {
11 if (null) |_| {}
12}
13export fn f5() void {
14 if (error.Foo) |_| {} else |_| {}
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :2:9: error: expected optional type, found 'bool'
22// :5:9: error: expected optional type, found 'usize'
23// :8:9: error: expected error union type, found 'usize'
24// :14:9: error: expected error union type, found 'error{Foo}'
test/cases/compile_errors/stage1/obj/invalid_maybe_type.zig deleted-9
......@@ -1,9 +0,0 @@
1export fn f() void {
2 if (true) |x| { _ = x; }
3}
4
5// error
6// backend=stage1
7// target=native
8//
9// tmp.zig:2:9: error: expected optional type, found 'bool'