From 58caed1c71179f48c4e7bffadef0392fa8381e72 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 15 Dec 2022 21:18:42 +0200 Subject: [PATCH] Sema: make is_non_{null,err} stricter about types Closes #13023 --- src/AstGen.zig | 4 ++-- src/Sema.zig | 23 ++++++++++++++++++ src/link/MachO/load_commands.zig | 2 +- .../compile_errors/invalid_capture_type.zig | 24 +++++++++++++++++++ .../stage1/obj/invalid_maybe_type.zig | 9 ------- 5 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 test/cases/compile_errors/invalid_capture_type.zig delete mode 100644 test/cases/compile_errors/stage1/obj/invalid_maybe_type.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index 8df3d56a88..69f3e2d381 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -6071,7 +6071,7 @@ fn whileExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, - .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.then_expr), + .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.cond_expr), }; } else if (while_full.payload_token) |_| { const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; @@ -6079,7 +6079,7 @@ fn whileExpr( const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, - .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.then_expr), + .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr), }; } else { const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr); diff --git a/src/Sema.zig b/src/Sema.zig index e67965271a..0a7496f730 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16356,6 +16356,15 @@ fn finishCondBr( return Air.indexToRef(block_inst); } +fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { + switch (ty.zigTypeTag()) { + .Optional, .Null, .Undefined => return, + .Pointer => if (ty.isPtrLikeOptional()) return, + else => {}, + } + return sema.failWithExpectedOptionalType(block, src, ty); +} + fn zirIsNonNull( sema: *Sema, block: *Block, @@ -16367,6 +16376,7 @@ fn zirIsNonNull( const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand = try sema.resolveInst(inst_data.operand); + try sema.checkNullableType(block, src, sema.typeOf(operand)); return sema.analyzeIsNull(block, src, operand, true); } @@ -16381,6 +16391,7 @@ fn zirIsNonNullPtr( const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const ptr = try sema.resolveInst(inst_data.operand); + try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2()); if ((try sema.resolveMaybeUndefVal(ptr)) == null) { return block.addUnOp(.is_non_null_ptr, ptr); } @@ -16388,12 +16399,23 @@ fn zirIsNonNullPtr( return sema.analyzeIsNull(block, src, loaded, true); } +fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { + switch (ty.zigTypeTag()) { + .ErrorSet, .ErrorUnion, .Undefined => return, + else => return sema.fail(block, src, "expected error union type, found '{}'", .{ + ty.fmt(sema.mod), + }), + } +} + fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const src = inst_data.src(); const operand = try sema.resolveInst(inst_data.operand); + try sema.checkErrorType(block, src, sema.typeOf(operand)); return sema.analyzeIsNonErr(block, inst_data.src(), operand); } @@ -16404,6 +16426,7 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const ptr = try sema.resolveInst(inst_data.operand); + try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2()); const loaded = try sema.analyzeLoad(block, src, ptr, src); return sema.analyzeIsNonErr(block, src, loaded); } diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 73c28965ff..0e3760526c 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -36,7 +36,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx // LC_DYLD_INFO_ONLY sizeofcmds += @sizeOf(macho.dyld_info_command); // LC_FUNCTION_STARTS - if (has_text_segment and ctx.wants_function_starts) |_| { + if (has_text_segment and ctx.wants_function_starts) { sizeofcmds += @sizeOf(macho.linkedit_data_command); } // LC_DATA_IN_CODE diff --git a/test/cases/compile_errors/invalid_capture_type.zig b/test/cases/compile_errors/invalid_capture_type.zig new file mode 100644 index 0000000000..3813021c95 --- /dev/null +++ b/test/cases/compile_errors/invalid_capture_type.zig @@ -0,0 +1,24 @@ +export fn f1() void { + if (true) |x| { _ = x; } +} +export fn f2() void { + if (@as(usize, 5)) |_| {} +} +export fn f3() void { + if (@as(usize, 5)) |_| {} else |_| {} +} +export fn f4() void { + if (null) |_| {} +} +export fn f5() void { + if (error.Foo) |_| {} else |_| {} +} + +// error +// backend=stage2 +// target=native +// +// :2:9: error: expected optional type, found 'bool' +// :5:9: error: expected optional type, found 'usize' +// :8:9: error: expected error union type, found 'usize' +// :14:9: error: expected error union type, found 'error{Foo}' diff --git a/test/cases/compile_errors/stage1/obj/invalid_maybe_type.zig b/test/cases/compile_errors/stage1/obj/invalid_maybe_type.zig deleted file mode 100644 index cb075c36b7..0000000000 --- a/test/cases/compile_errors/stage1/obj/invalid_maybe_type.zig +++ /dev/null @@ -1,9 +0,0 @@ -export fn f() void { - if (true) |x| { _ = x; } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:9: error: expected optional type, found 'bool'