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

Closes #13023
This commit is contained in:
Veikka Tuominen 2022-12-15 21:18:42 +02:00
parent 90477e5c10
commit 58caed1c71
5 changed files with 50 additions and 12 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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}'

View File

@ -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'