mirror of
https://github.com/ziglang/zig.git
synced 2025-12-31 10:33:19 +00:00
Merge pull request #12117 from Vexu/stage2-compile-errors
Stage2: explain why value must be comptime known
This commit is contained in:
commit
8e75ba653b
@ -11,6 +11,7 @@ const InstallDirectoryOptions = std.build.InstallDirectoryOptions;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const zig_version = std.builtin.Version{ .major = 0, .minor = 10, .patch = 0 };
|
||||
const stack_size = 32 * 1024 * 1024;
|
||||
|
||||
pub fn build(b: *Builder) !void {
|
||||
b.setPreferredReleaseMode(.ReleaseFast);
|
||||
@ -41,6 +42,7 @@ pub fn build(b: *Builder) !void {
|
||||
const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain");
|
||||
|
||||
var test_cases = b.addTest("src/test.zig");
|
||||
test_cases.stack_size = stack_size;
|
||||
test_cases.setBuildMode(mode);
|
||||
test_cases.addPackagePath("test_cases", "test/cases.zig");
|
||||
test_cases.single_threaded = single_threaded;
|
||||
@ -141,6 +143,7 @@ pub fn build(b: *Builder) !void {
|
||||
};
|
||||
|
||||
const exe = b.addExecutable("zig", main_file);
|
||||
exe.stack_size = stack_size;
|
||||
exe.strip = strip;
|
||||
exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false;
|
||||
exe.install();
|
||||
|
||||
@ -1347,7 +1347,7 @@ fn arrayInitExpr(
|
||||
}
|
||||
}
|
||||
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
|
||||
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
|
||||
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, array_init.ast.type_expr);
|
||||
break :inst .{
|
||||
.array = array_type_inst,
|
||||
.elem = .none,
|
||||
@ -2332,7 +2332,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.ptr_type_simple,
|
||||
.overflow_arithmetic_ptr,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
@ -3110,24 +3110,6 @@ fn ptrType(
|
||||
|
||||
const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
|
||||
|
||||
const simple = ptr_info.ast.align_node == 0 and
|
||||
ptr_info.ast.addrspace_node == 0 and
|
||||
ptr_info.ast.sentinel == 0 and
|
||||
ptr_info.ast.bit_range_start == 0;
|
||||
|
||||
if (simple) {
|
||||
const result = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
|
||||
.ptr_type_simple = .{
|
||||
.is_allowzero = ptr_info.allowzero_token != null,
|
||||
.is_mutable = ptr_info.const_token == null,
|
||||
.is_volatile = ptr_info.volatile_token != null,
|
||||
.size = ptr_info.size,
|
||||
.elem_type = elem_type,
|
||||
},
|
||||
} });
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
|
||||
var sentinel_ref: Zir.Inst.Ref = .none;
|
||||
var align_ref: Zir.Inst.Ref = .none;
|
||||
var addrspace_ref: Zir.Inst.Ref = .none;
|
||||
@ -3160,7 +3142,10 @@ fn ptrType(
|
||||
try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.PtrType).Struct.fields.len +
|
||||
trailing_count);
|
||||
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{ .elem_type = elem_type });
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{
|
||||
.elem_type = elem_type,
|
||||
.src_node = gz.nodeIndexToRelative(node),
|
||||
});
|
||||
if (sentinel_ref != .none) {
|
||||
gz.astgen.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));
|
||||
}
|
||||
@ -4314,7 +4299,7 @@ fn unionDeclInner(
|
||||
members: []const Ast.Node.Index,
|
||||
layout: std.builtin.Type.ContainerLayout,
|
||||
arg_node: Ast.Node.Index,
|
||||
have_auto_enum: bool,
|
||||
auto_enum_tok: ?Ast.TokenIndex,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const decl_inst = try gz.reserveInstructionIndex();
|
||||
|
||||
@ -4348,6 +4333,15 @@ fn unionDeclInner(
|
||||
const decl_count = try astgen.scanDecls(&namespace, members);
|
||||
const field_count = @intCast(u32, members.len - decl_count);
|
||||
|
||||
if (layout != .Auto and (auto_enum_tok != null or arg_node != 0)) {
|
||||
const layout_str = if (layout == .Extern) "extern" else "packed";
|
||||
if (arg_node != 0) {
|
||||
return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{layout_str});
|
||||
} else {
|
||||
return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{layout_str});
|
||||
}
|
||||
}
|
||||
|
||||
const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
|
||||
try typeExpr(&block_scope, &namespace.base, arg_node)
|
||||
else
|
||||
@ -4382,7 +4376,7 @@ fn unionDeclInner(
|
||||
if (have_type) {
|
||||
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
|
||||
wip_members.appendToField(@enumToInt(field_type));
|
||||
} else if (arg_inst == .none and !have_auto_enum) {
|
||||
} else if (arg_inst == .none and auto_enum_tok == null) {
|
||||
return astgen.failNode(member_node, "union field missing type", .{});
|
||||
}
|
||||
if (have_align) {
|
||||
@ -4404,7 +4398,7 @@ fn unionDeclInner(
|
||||
},
|
||||
);
|
||||
}
|
||||
if (!have_auto_enum) {
|
||||
if (auto_enum_tok == null) {
|
||||
return astgen.failNodeNotes(
|
||||
node,
|
||||
"explicitly valued tagged union requires inferred enum tag type",
|
||||
@ -4440,7 +4434,7 @@ fn unionDeclInner(
|
||||
.body_len = body_len,
|
||||
.fields_len = field_count,
|
||||
.decls_len = decl_count,
|
||||
.auto_enum_tag = have_auto_enum,
|
||||
.auto_enum_tag = auto_enum_tok != null,
|
||||
});
|
||||
|
||||
wip_members.finishBits(bits_per_field);
|
||||
@ -4496,9 +4490,7 @@ fn containerDecl(
|
||||
else => unreachable,
|
||||
} else std.builtin.Type.ContainerLayout.Auto;
|
||||
|
||||
const have_auto_enum = container_decl.ast.enum_token != null;
|
||||
|
||||
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, have_auto_enum);
|
||||
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token);
|
||||
return rvalue(gz, rl, result, node);
|
||||
},
|
||||
.keyword_enum => {
|
||||
@ -4732,7 +4724,10 @@ fn containerDecl(
|
||||
defer wip_members.deinit();
|
||||
|
||||
for (container_decl.ast.members) |member_node| {
|
||||
_ = try containerMember(gz, &namespace.base, &wip_members, member_node);
|
||||
const res = try containerMember(gz, &namespace.base, &wip_members, member_node);
|
||||
if (res == .field) {
|
||||
return astgen.failNode(member_node, "opaque types cannot have fields", .{});
|
||||
}
|
||||
}
|
||||
|
||||
try gz.setOpaque(decl_inst, .{
|
||||
@ -7588,15 +7583,7 @@ fn builtinCall(
|
||||
.shl_with_overflow => {
|
||||
const int_type = try typeExpr(gz, scope, params[0]);
|
||||
const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
|
||||
const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
|
||||
.ptr_type_simple = .{
|
||||
.is_allowzero = false,
|
||||
.is_mutable = true,
|
||||
.is_volatile = false,
|
||||
.size = .One,
|
||||
.elem_type = int_type,
|
||||
},
|
||||
} });
|
||||
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
|
||||
const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
|
||||
const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);
|
||||
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
|
||||
@ -7987,15 +7974,7 @@ fn overflowArithmetic(
|
||||
tag: Zir.Inst.Extended,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const int_type = try typeExpr(gz, scope, params[0]);
|
||||
const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
|
||||
.ptr_type_simple = .{
|
||||
.is_allowzero = false,
|
||||
.is_mutable = true,
|
||||
.is_volatile = false,
|
||||
.size = .One,
|
||||
.elem_type = int_type,
|
||||
},
|
||||
} });
|
||||
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
|
||||
const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
|
||||
const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);
|
||||
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
|
||||
|
||||
392
src/Module.zig
392
src/Module.zig
@ -2348,7 +2348,92 @@ pub const SrcLoc = struct {
|
||||
}
|
||||
} else unreachable;
|
||||
},
|
||||
|
||||
.node_offset_switch_prong_capture => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const case_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const case = switch (node_tags[case_node]) {
|
||||
.switch_case_one => tree.switchCaseOne(case_node),
|
||||
.switch_case => tree.switchCase(case_node),
|
||||
else => unreachable,
|
||||
};
|
||||
const start_tok = case.payload_token.?;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const end_tok = switch (token_tags[start_tok]) {
|
||||
.asterisk => start_tok + 1,
|
||||
else => start_tok,
|
||||
};
|
||||
const start = tree.tokens.items(.start)[start_tok];
|
||||
const end_start = tree.tokens.items(.start)[end_tok];
|
||||
const end = end_start + @intCast(u32, tree.tokenSlice(end_tok).len);
|
||||
return Span{ .start = start, .end = end, .main = start };
|
||||
},
|
||||
.node_offset_fn_type_align => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
var params: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node),
|
||||
.fn_proto => tree.fnProto(node),
|
||||
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node_datas[node].lhs),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node_datas[node].lhs),
|
||||
.fn_proto => tree.fnProto(node_datas[node].lhs),
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.align_expr);
|
||||
},
|
||||
.node_offset_fn_type_addrspace => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
var params: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node),
|
||||
.fn_proto => tree.fnProto(node),
|
||||
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node_datas[node].lhs),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node_datas[node].lhs),
|
||||
.fn_proto => tree.fnProto(node_datas[node].lhs),
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.addrspace_expr);
|
||||
},
|
||||
.node_offset_fn_type_section => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
var params: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node),
|
||||
.fn_proto => tree.fnProto(node),
|
||||
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node_datas[node].lhs),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node_datas[node].lhs),
|
||||
.fn_proto => tree.fnProto(node_datas[node].lhs),
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.section_expr);
|
||||
},
|
||||
.node_offset_fn_type_cc => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
@ -2374,6 +2459,7 @@ pub const SrcLoc = struct {
|
||||
|
||||
.node_offset_fn_type_ret_ty => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
var params: [1]Ast.Node.Index = undefined;
|
||||
@ -2382,10 +2468,55 @@ pub const SrcLoc = struct {
|
||||
.fn_proto_multi => tree.fnProtoMulti(node),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node),
|
||||
.fn_proto => tree.fnProto(node),
|
||||
.fn_decl => blk: {
|
||||
const fn_proto = node_datas[node].lhs;
|
||||
break :blk switch (node_tags[fn_proto]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, fn_proto),
|
||||
.fn_proto_multi => tree.fnProtoMulti(fn_proto),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, fn_proto),
|
||||
.fn_proto => tree.fnProto(fn_proto),
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.return_type);
|
||||
},
|
||||
.node_offset_param => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
var first_tok = tree.firstToken(node);
|
||||
while (true) switch (token_tags[first_tok - 1]) {
|
||||
.colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
|
||||
else => break,
|
||||
};
|
||||
return tokensToSpan(
|
||||
tree,
|
||||
first_tok,
|
||||
tree.lastToken(node),
|
||||
first_tok,
|
||||
);
|
||||
},
|
||||
.token_offset_param => |token_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node];
|
||||
const tok_index = @bitCast(Ast.TokenIndex, token_off + @bitCast(i32, main_token));
|
||||
|
||||
var first_tok = tok_index;
|
||||
while (true) switch (token_tags[first_tok - 1]) {
|
||||
.colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
|
||||
else => break,
|
||||
};
|
||||
return tokensToSpan(
|
||||
tree,
|
||||
first_tok,
|
||||
tok_index,
|
||||
first_tok,
|
||||
);
|
||||
},
|
||||
|
||||
.node_offset_anyframe_type => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
@ -2466,6 +2597,113 @@ pub const SrcLoc = struct {
|
||||
|
||||
return nodeToSpan(tree, node_datas[node].lhs);
|
||||
},
|
||||
.node_offset_ptr_elem => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.child_type);
|
||||
},
|
||||
.node_offset_ptr_sentinel => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.sentinel);
|
||||
},
|
||||
.node_offset_ptr_align => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.align_node);
|
||||
},
|
||||
.node_offset_ptr_addrspace => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.addrspace_node);
|
||||
},
|
||||
.node_offset_ptr_bitoffset => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.bit_range_start);
|
||||
},
|
||||
.node_offset_ptr_hostsize => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
|
||||
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
|
||||
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
|
||||
.ptr_type => tree.ptrType(parent_node),
|
||||
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, full.ast.bit_range_end);
|
||||
},
|
||||
.node_offset_container_tag => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
|
||||
switch (node_tags[parent_node]) {
|
||||
.container_decl_arg, .container_decl_arg_trailing => {
|
||||
const full = tree.containerDeclArg(parent_node);
|
||||
return nodeToSpan(tree, full.ast.arg);
|
||||
},
|
||||
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
|
||||
const full = tree.taggedUnionEnumTag(parent_node);
|
||||
|
||||
return tokensToSpan(
|
||||
tree,
|
||||
tree.firstToken(full.ast.arg) - 2,
|
||||
tree.lastToken(full.ast.arg) + 1,
|
||||
tree.nodes.items(.main_token)[full.ast.arg],
|
||||
);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -2694,6 +2932,27 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// range nodes. The error applies to all of them.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_switch_range: i32,
|
||||
/// The source location points to the capture of a switch_prong.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_switch_prong_capture: i32,
|
||||
/// The source location points to the align expr of a function type
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function type AST node. Next, navigate to
|
||||
/// the calling convention node.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_fn_type_align: i32,
|
||||
/// The source location points to the addrspace expr of a function type
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function type AST node. Next, navigate to
|
||||
/// the calling convention node.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_fn_type_addrspace: i32,
|
||||
/// The source location points to the linksection expr of a function type
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function type AST node. Next, navigate to
|
||||
/// the calling convention node.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_fn_type_section: i32,
|
||||
/// The source location points to the calling convention of a function type
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function type AST node. Next, navigate to
|
||||
@ -2706,6 +2965,8 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// the return type node.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_fn_type_ret_ty: i32,
|
||||
node_offset_param: i32,
|
||||
token_offset_param: i32,
|
||||
/// The source location points to the type expression of an `anyframe->T`
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
|
||||
@ -2739,6 +3000,27 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// The source location points to the operand of an unary expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_un_op: i32,
|
||||
/// The source location points to the elem type of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_elem: i32,
|
||||
/// The source location points to the sentinel of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_sentinel: i32,
|
||||
/// The source location points to the align expr of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_align: i32,
|
||||
/// The source location points to the addrspace expr of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_addrspace: i32,
|
||||
/// The source location points to the bit-offset of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_bitoffset: i32,
|
||||
/// The source location points to the host size of a pointer.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_ptr_hostsize: i32,
|
||||
/// The source location points to the tag type of an union or an enum.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_container_tag: i32,
|
||||
|
||||
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
|
||||
|
||||
@ -2795,14 +3077,27 @@ pub const LazySrcLoc = union(enum) {
|
||||
.node_offset_switch_operand,
|
||||
.node_offset_switch_special_prong,
|
||||
.node_offset_switch_range,
|
||||
.node_offset_switch_prong_capture,
|
||||
.node_offset_fn_type_align,
|
||||
.node_offset_fn_type_addrspace,
|
||||
.node_offset_fn_type_section,
|
||||
.node_offset_fn_type_cc,
|
||||
.node_offset_fn_type_ret_ty,
|
||||
.node_offset_param,
|
||||
.token_offset_param,
|
||||
.node_offset_anyframe_type,
|
||||
.node_offset_lib_name,
|
||||
.node_offset_array_type_len,
|
||||
.node_offset_array_type_sentinel,
|
||||
.node_offset_array_type_elem,
|
||||
.node_offset_un_op,
|
||||
.node_offset_ptr_elem,
|
||||
.node_offset_ptr_sentinel,
|
||||
.node_offset_ptr_align,
|
||||
.node_offset_ptr_addrspace,
|
||||
.node_offset_ptr_bitoffset,
|
||||
.node_offset_ptr_hostsize,
|
||||
.node_offset_container_tag,
|
||||
=> .{
|
||||
.file_scope = decl.getFileScope(),
|
||||
.parent_decl_node = decl.src_node,
|
||||
@ -3957,18 +4252,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
|
||||
var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
|
||||
defer wip_captures.deinit();
|
||||
|
||||
var block_scope: Sema.Block = .{
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.src_decl = new_decl_index,
|
||||
.namespace = &struct_obj.namespace,
|
||||
.wip_capture_scope = wip_captures.scope,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.is_comptime = true,
|
||||
};
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
|
||||
try wip_captures.finalize();
|
||||
new_decl.analysis = .complete;
|
||||
@ -4077,7 +4360,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||
const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
|
||||
try wip_captures.finalize();
|
||||
const src = LazySrcLoc.nodeOffset(0);
|
||||
const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref);
|
||||
const decl_tv = try sema.resolveInstValue(&block_scope, .unneeded, result_ref, undefined);
|
||||
const decl_align: u32 = blk: {
|
||||
const align_ref = decl.zirAlignRef();
|
||||
if (align_ref == .none) break :blk 0;
|
||||
@ -4086,7 +4369,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||
const decl_linksection: ?[*:0]const u8 = blk: {
|
||||
const linksection_ref = decl.zirLinksectionRef();
|
||||
if (linksection_ref == .none) break :blk null;
|
||||
const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref);
|
||||
const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref, "linksection must be comptime known");
|
||||
break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
|
||||
};
|
||||
const target = sema.mod.getTarget();
|
||||
@ -4518,7 +4801,7 @@ pub fn scanNamespace(
|
||||
extra_start: usize,
|
||||
decls_len: u32,
|
||||
parent_decl: *Decl,
|
||||
) SemaError!usize {
|
||||
) Allocator.Error!usize {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -4565,7 +4848,7 @@ const ScanDeclIter = struct {
|
||||
unnamed_test_index: usize = 0,
|
||||
};
|
||||
|
||||
fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!void {
|
||||
fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -5382,6 +5665,7 @@ pub const SwitchProngSrc = union(enum) {
|
||||
scalar: u32,
|
||||
multi: Multi,
|
||||
range: Multi,
|
||||
multi_capture: u32,
|
||||
|
||||
pub const Multi = struct {
|
||||
prong: u32,
|
||||
@ -5437,6 +5721,9 @@ pub const SwitchProngSrc = union(enum) {
|
||||
.scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(case.ast.values[0]),
|
||||
),
|
||||
.multi_capture => |i| if (is_multi and i == multi_i) {
|
||||
return LazySrcLoc{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
|
||||
},
|
||||
.multi => |s| if (is_multi and s.prong == multi_i) {
|
||||
var item_i: u32 = 0;
|
||||
for (case.ast.values) |item_node| {
|
||||
@ -5578,6 +5865,77 @@ fn queryFieldSrc(
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn paramSrc(
|
||||
func_node_offset: i32,
|
||||
gpa: Allocator,
|
||||
decl: *Decl,
|
||||
param_i: usize,
|
||||
) LazySrcLoc {
|
||||
@setCold(true);
|
||||
const tree = decl.getFileScope().getTree(gpa) catch |err| {
|
||||
// In this case we emit a warning + a less precise source location.
|
||||
log.warn("unable to load {s}: {s}", .{
|
||||
decl.getFileScope().sub_file_path, @errorName(err),
|
||||
});
|
||||
return LazySrcLoc.nodeOffset(0);
|
||||
};
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = decl.relativeToNodeIndex(func_node_offset);
|
||||
var params: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node),
|
||||
.fn_proto => tree.fnProto(node),
|
||||
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
|
||||
.fn_proto_simple => tree.fnProtoSimple(¶ms, node_datas[node].lhs),
|
||||
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
|
||||
.fn_proto_one => tree.fnProtoOne(¶ms, node_datas[node].lhs),
|
||||
.fn_proto => tree.fnProto(node_datas[node].lhs),
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
var it = full.iterate(tree);
|
||||
while (true) {
|
||||
if (it.param_i == param_i) {
|
||||
const param = it.next().?;
|
||||
if (param.anytype_ellipsis3) |some| {
|
||||
const main_token = tree.nodes.items(.main_token)[decl.src_node];
|
||||
return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
|
||||
}
|
||||
return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
|
||||
}
|
||||
_ = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn argSrc(
|
||||
call_node_offset: i32,
|
||||
gpa: Allocator,
|
||||
decl: *Decl,
|
||||
arg_i: usize,
|
||||
) LazySrcLoc {
|
||||
@setCold(true);
|
||||
const tree = decl.getFileScope().getTree(gpa) catch |err| {
|
||||
// In this case we emit a warning + a less precise source location.
|
||||
log.warn("unable to load {s}: {s}", .{
|
||||
decl.getFileScope().sub_file_path, @errorName(err),
|
||||
});
|
||||
return LazySrcLoc.nodeOffset(0);
|
||||
};
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = decl.relativeToNodeIndex(call_node_offset);
|
||||
var args: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),
|
||||
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
|
||||
else => unreachable,
|
||||
};
|
||||
return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));
|
||||
}
|
||||
|
||||
/// Called from `performAllTheWork`, after all AstGen workers have finished,
|
||||
/// and before the main semantic analysis loop begins.
|
||||
pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
|
||||
|
||||
1569
src/Sema.zig
1569
src/Sema.zig
File diff suppressed because it is too large
Load Diff
21
src/Zir.zig
21
src/Zir.zig
@ -534,9 +534,9 @@ pub const Inst = struct {
|
||||
/// Obtains the return type of the in-scope function.
|
||||
/// Uses the `node` union field.
|
||||
ret_type,
|
||||
/// Create a pointer type that does not have a sentinel, alignment, address space, or bit range specified.
|
||||
/// Uses the `ptr_type_simple` union field.
|
||||
ptr_type_simple,
|
||||
/// Create a pointer type for overflow arithmetic.
|
||||
/// TODO remove when doing https://github.com/ziglang/zig/issues/10248
|
||||
overflow_arithmetic_ptr,
|
||||
/// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range.
|
||||
/// Uses the `ptr_type` union field.
|
||||
ptr_type,
|
||||
@ -1121,7 +1121,7 @@ pub const Inst = struct {
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.ptr_type_simple,
|
||||
.overflow_arithmetic_ptr,
|
||||
.ensure_err_payload_void,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
@ -1417,7 +1417,7 @@ pub const Inst = struct {
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.ptr_type_simple,
|
||||
.overflow_arithmetic_ptr,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
@ -1659,7 +1659,7 @@ pub const Inst = struct {
|
||||
.ret_err_value_code = .str_tok,
|
||||
.ret_ptr = .node,
|
||||
.ret_type = .node,
|
||||
.ptr_type_simple = .ptr_type_simple,
|
||||
.overflow_arithmetic_ptr = .un_node,
|
||||
.ptr_type = .ptr_type,
|
||||
.slice_start = .pl_node,
|
||||
.slice_end = .pl_node,
|
||||
@ -2499,13 +2499,6 @@ pub const Inst = struct {
|
||||
node: i32,
|
||||
int: u64,
|
||||
float: f64,
|
||||
ptr_type_simple: struct {
|
||||
is_allowzero: bool,
|
||||
is_mutable: bool,
|
||||
is_volatile: bool,
|
||||
size: std.builtin.Type.Pointer.Size,
|
||||
elem_type: Ref,
|
||||
},
|
||||
ptr_type: struct {
|
||||
flags: packed struct {
|
||||
is_allowzero: bool,
|
||||
@ -2608,7 +2601,6 @@ pub const Inst = struct {
|
||||
node,
|
||||
int,
|
||||
float,
|
||||
ptr_type_simple,
|
||||
ptr_type,
|
||||
int_type,
|
||||
bool_br,
|
||||
@ -2869,6 +2861,7 @@ pub const Inst = struct {
|
||||
/// 4. host_size: Ref // if `has_bit_range` flag is set
|
||||
pub const PtrType = struct {
|
||||
elem_type: Ref,
|
||||
src_node: i32,
|
||||
};
|
||||
|
||||
pub const ArrayTypeSentinel = struct {
|
||||
|
||||
@ -233,6 +233,7 @@ const Writer = struct {
|
||||
.validate_struct_init_ty,
|
||||
.make_ptr_const,
|
||||
.validate_deref,
|
||||
.overflow_arithmetic_ptr,
|
||||
=> try self.writeUnNode(stream, inst),
|
||||
|
||||
.ref,
|
||||
@ -247,7 +248,6 @@ const Writer = struct {
|
||||
|
||||
.array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
|
||||
.param_type => try self.writeParamType(stream, inst),
|
||||
.ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
|
||||
.ptr_type => try self.writePtrType(stream, inst),
|
||||
.int => try self.writeInt(stream, inst),
|
||||
.int_big => try self.writeIntBig(stream, inst),
|
||||
@ -601,24 +601,6 @@ const Writer = struct {
|
||||
try stream.print(", {d})", .{inst_data.param_index});
|
||||
}
|
||||
|
||||
fn writePtrTypeSimple(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Zir.Inst.Index,
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
|
||||
const str_allowzero = if (inst_data.is_allowzero) "allowzero, " else "";
|
||||
const str_const = if (!inst_data.is_mutable) "const, " else "";
|
||||
const str_volatile = if (inst_data.is_volatile) "volatile, " else "";
|
||||
try self.writeInstRef(stream, inst_data.elem_type);
|
||||
try stream.print(", {s}{s}{s}{s})", .{
|
||||
str_allowzero,
|
||||
str_const,
|
||||
str_volatile,
|
||||
@tagName(inst_data.size),
|
||||
});
|
||||
}
|
||||
|
||||
fn writePtrType(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
@ -660,7 +642,8 @@ const Writer = struct {
|
||||
try self.writeInstRef(stream, @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]));
|
||||
try stream.writeAll(")");
|
||||
}
|
||||
try stream.writeAll(")");
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.data.src_node));
|
||||
}
|
||||
|
||||
fn writeInt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
|
||||
@ -744,6 +744,7 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {
|
||||
}
|
||||
}
|
||||
|
||||
/// This function returns 1 if function alignment is not observable or settable.
|
||||
pub fn defaultFunctionAlignment(target: std.Target) u32 {
|
||||
return switch (target.cpu.arch) {
|
||||
.arm, .armeb => 4,
|
||||
@ -753,3 +754,10 @@ pub fn defaultFunctionAlignment(target: std.Target) u32 {
|
||||
else => 1,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn supportsFunctionAlignment(target: std.Target) bool {
|
||||
return switch (target.cpu.arch) {
|
||||
.wasm32, .wasm64 => false,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
22
src/type.zig
22
src/type.zig
@ -4643,13 +4643,27 @@ pub const Type = extern union {
|
||||
}
|
||||
|
||||
/// Asserts the type is a function.
|
||||
pub fn fnCallingConventionAllowsZigTypes(self: Type) bool {
|
||||
return switch (self.fnCallingConvention()) {
|
||||
pub fn fnCallingConventionAllowsZigTypes(cc: std.builtin.CallingConvention) bool {
|
||||
return switch (cc) {
|
||||
.Unspecified, .Async, .Inline, .PtxKernel => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isValidParamType(self: Type) bool {
|
||||
return switch (self.zigTypeTagOrPoison() catch return true) {
|
||||
.Undefined, .Null, .Opaque, .NoReturn => false,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isValidReturnType(self: Type) bool {
|
||||
return switch (self.zigTypeTagOrPoison() catch return true) {
|
||||
.Undefined, .Null, .Opaque => false,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
/// Asserts the type is a function.
|
||||
pub fn fnIsVarArgs(self: Type) bool {
|
||||
return switch (self.tag()) {
|
||||
@ -5650,6 +5664,10 @@ pub const Type = extern union {
|
||||
const union_obj = ty.cast(Payload.Union).?.data;
|
||||
return union_obj.srcLoc(mod);
|
||||
},
|
||||
.@"opaque" => {
|
||||
const opaque_obj = ty.cast(Payload.Opaque).?.data;
|
||||
return opaque_obj.srcLoc(mod);
|
||||
},
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
|
||||
@ -299,8 +299,7 @@ test "implicitly decreasing fn alignment" {
|
||||
try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
|
||||
}
|
||||
|
||||
// TODO make it a compile error to put align on the fn proto instead of on the ptr
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void {
|
||||
try expect(ptr() == answer);
|
||||
}
|
||||
|
||||
@ -326,7 +325,7 @@ test "@alignCast functions" {
|
||||
fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
|
||||
return fnExpects4(@alignCast(4, ptr));
|
||||
}
|
||||
fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
|
||||
fn fnExpects4(ptr: *const fn () align(4) i32) i32 {
|
||||
return ptr();
|
||||
}
|
||||
fn simple4() align(4) i32 {
|
||||
|
||||
@ -4,7 +4,7 @@ const builtin = @import("builtin");
|
||||
|
||||
pub const VM = ?[*]const struct_InvocationTable_;
|
||||
pub const struct_InvocationTable_ = extern struct {
|
||||
GetVM: ?fn (?[*]VM) callconv(.C) c_int,
|
||||
GetVM: ?*const fn (?[*]VM) callconv(.C) c_int,
|
||||
};
|
||||
|
||||
pub const struct_VM_ = extern struct {
|
||||
@ -23,5 +23,7 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
|
||||
}
|
||||
|
||||
test "fixed" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
try expect(agent_callback(undefined, undefined) == 11);
|
||||
}
|
||||
|
||||
@ -1016,7 +1016,6 @@ test "switching on non exhaustive union" {
|
||||
switch (a) {
|
||||
.a => |val| try expect(val == 2),
|
||||
.b => return error.Fail,
|
||||
_ => return error.Fail,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
const Foo = struct {};
|
||||
export fn a() void {
|
||||
const T = [*c]Foo;
|
||||
var t: T = undefined;
|
||||
_ = t;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'
|
||||
// :3:19: note: only structs with packed or extern layout are extern compatible
|
||||
// :1:13: note: struct declared here
|
||||
@ -5,7 +5,7 @@ export fn a() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:16: error: C pointers cannot point to opaque types
|
||||
// :3:16: error: C pointers cannot point to opaque types
|
||||
@ -0,0 +1,9 @@
|
||||
export fn foo() align(1) void {
|
||||
return;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=wasm32-freestanding-none
|
||||
//
|
||||
// :1:23: error: target does not support function alignment
|
||||
@ -8,8 +8,8 @@ export fn g() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:8: error: array access of non-array type 'bool'
|
||||
// tmp.zig:7:12: error: array access of non-array type 'bool'
|
||||
// :3:8: error: element access of non-indexable type 'bool'
|
||||
// :7:12: error: element access of non-indexable type 'bool'
|
||||
@ -10,8 +10,8 @@ export fn g() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:11: error: expected type 'usize', found 'bool'
|
||||
// tmp.zig:9:15: error: expected type 'usize', found 'bool'
|
||||
// :4:11: error: expected type 'usize', found 'bool'
|
||||
// :9:15: error: expected type 'usize', found 'bool'
|
||||
16
test/cases/compile_errors/array_in_c_exported_function.zig
Normal file
16
test/cases/compile_errors/array_in_c_exported_function.zig
Normal file
@ -0,0 +1,16 @@
|
||||
export fn zig_array(x: [10]u8) void {
|
||||
try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
|
||||
}
|
||||
const std = @import("std");
|
||||
export fn zig_return_array() [10]u8 {
|
||||
return "1234567890".*;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:21: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
|
||||
// :1:21: note: arrays are not allowed as a parameter type
|
||||
// :5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
|
||||
// :5:30: note: arrays are not allowed as a return type
|
||||
@ -14,5 +14,5 @@ fn doSomeAsm() void {
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// :6:5: error: unable to resolve comptime value
|
||||
// :6:5: error: unable to evalutate comptime expression
|
||||
// :2:14: note: called from here
|
||||
|
||||
@ -7,5 +7,5 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:1: error: C pointers cannot point to non-C-ABI-compatible type 'void'
|
||||
// :1:1: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
|
||||
// :2:16: error: C pointers cannot point to non-C-ABI-compatible type 'void'
|
||||
// :2:16: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
|
||||
|
||||
@ -17,4 +17,4 @@ fn bad(ok: bool) void {
|
||||
// target=native
|
||||
// backend=stage2
|
||||
//
|
||||
// :12:18: error: unable to resolve comptime value
|
||||
// :12:18: error: cannot load runtime value in comptime block
|
||||
|
||||
@ -7,4 +7,4 @@ pub extern fn foo(format: *const u8, ...) void;
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:8: error: expected type '*const u8', found '[5:0]u8'
|
||||
// :2:16: error: expected type '*const u8', found '[5:0]u8'
|
||||
|
||||
@ -13,9 +13,9 @@ comptime {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:8:20: error: capture group with incompatible types
|
||||
// tmp.zig:8:9: note: type 'usize' here
|
||||
// tmp.zig:8:13: note: type 'isize' here
|
||||
// :8:20: error: capture group with incompatible types
|
||||
// :8:10: note: type 'usize' here
|
||||
// :8:14: note: type 'isize' here
|
||||
@ -18,6 +18,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:15: error: expected type '*const u3', found '*align(0:3:1) const u3'
|
||||
// :8:15: note: pointer host size '1' cannot cast into pointer host size '0'
|
||||
// :8:15: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
|
||||
// :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3'
|
||||
// :8:16: note: pointer host size '1' cannot cast into pointer host size '0'
|
||||
// :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
|
||||
|
||||
@ -7,4 +7,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:15: error: expected type 'type', found 'i32'
|
||||
// :2:11: error: expected type 'type', found 'i32'
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
fn a() i32 {}
|
||||
export fn entry() void { _ = a(); }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:13: error: expected type 'i32', found 'void'
|
||||
// :1:8: note: function return type declared here
|
||||
@ -45,7 +45,11 @@ pub export fn entry() void {
|
||||
// backend=llvm
|
||||
//
|
||||
// :11:22: error: comparison of 'void' with null
|
||||
// :25:51: error: unable to resolve comptime value
|
||||
// :25:51: error: unable to resolve comptime value
|
||||
// :25:51: error: unable to resolve comptime value
|
||||
// :25:51: error: unable to resolve comptime value
|
||||
// :25:51: error: values of type 'anyopaque' must be comptime known, but operand value is runtime known
|
||||
// :25:51: note: opaque type 'anyopaque' has undefined size
|
||||
// :25:51: error: values of type 'fn(*anyopaque, usize, u29, u29, usize) error{OutOfMemory}![]u8' must be comptime known, but operand value is runtime known
|
||||
// :25:51: note: use '*const fn(*anyopaque, usize, u29, u29, usize) error{OutOfMemory}![]u8' for a function pointer type
|
||||
// :25:51: error: values of type 'fn(*anyopaque, []u8, u29, usize, u29, usize) ?usize' must be comptime known, but operand value is runtime known
|
||||
// :25:51: note: use '*const fn(*anyopaque, []u8, u29, usize, u29, usize) ?usize' for a function pointer type
|
||||
// :25:51: error: values of type 'fn(*anyopaque, []u8, u29, usize) void' must be comptime known, but operand value is runtime known
|
||||
// :25:51: note: use '*const fn(*anyopaque, []u8, u29, usize) void' for a function pointer type
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
const O = opaque {};
|
||||
const Foo = struct {
|
||||
o: O,
|
||||
};
|
||||
const Bar = union {
|
||||
One: i32,
|
||||
Two: O,
|
||||
};
|
||||
export fn a() void {
|
||||
var foo: Foo = undefined;
|
||||
_ = foo;
|
||||
}
|
||||
export fn b() void {
|
||||
var bar: Bar = undefined;
|
||||
_ = bar;
|
||||
}
|
||||
export fn c() void {
|
||||
const baz = &@as(opaque {}, undefined);
|
||||
const qux = .{baz.*};
|
||||
_ = qux;
|
||||
}
|
||||
export fn d() void {
|
||||
const baz = &@as(opaque {}, undefined);
|
||||
const qux = .{ .a = baz.* };
|
||||
_ = qux;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs
|
||||
// :1:11: note: opaque declared here
|
||||
// :7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions
|
||||
// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
|
||||
// :18:22: note: opaque declared here
|
||||
// :24:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
|
||||
// :23:22: note: opaque declared here
|
||||
@ -1,12 +1,13 @@
|
||||
extern fn puts(s: [*:0]const u8) c_int;
|
||||
pub fn main() void {
|
||||
pub export fn entry() void {
|
||||
const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};
|
||||
const no_zero_ptr: [*]const u8 = &no_zero_array;
|
||||
_ = puts(no_zero_ptr);
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:14: error: expected type '[*:0]const u8', found '[*]const u8'
|
||||
// :5:14: error: expected type '[*:0]const u8', found '[*]const u8'
|
||||
// :5:14: note: destination pointer requires '0' sentinel
|
||||
@ -0,0 +1,15 @@
|
||||
const seventh_fib_number = fibonacci(7);
|
||||
fn fibonacci(x: i32) i32 {
|
||||
return fibonacci(x - 1) + fibonacci(x - 2);
|
||||
}
|
||||
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(&seventh_fib_number)); }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:21: error: evaluation exceeded 1000 backwards branches
|
||||
// :3:21: note: use @setEvalBranchQuota() to raise the branch limit from 1000
|
||||
// :3:21: note: called from here (999 times)
|
||||
// :1:37: note: called from here
|
||||
@ -8,6 +8,6 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:17: error: expected type '*const fn(i32) void', found '*const fn(bool) void'
|
||||
// :4:17: note: pointer type child 'fn(bool) void' cannot cast into pointer type child 'fn(i32) void'
|
||||
// :4:17: note: parameter 0 'bool' cannot cast into 'i32'
|
||||
// :4:18: error: expected type '*const fn(i32) void', found '*const fn(bool) void'
|
||||
// :4:18: note: pointer type child 'fn(bool) void' cannot cast into pointer type child 'fn(i32) void'
|
||||
// :4:18: note: parameter 0 'bool' cannot cast into 'i32'
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
export fn foo(comptime x: anytype, y: i32) i32{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:15: error: generic parameters not allowed in function with calling convention 'C'
|
||||
10
test/cases/compile_errors/export_generic_function.zig
Normal file
10
test/cases/compile_errors/export_generic_function.zig
Normal file
@ -0,0 +1,10 @@
|
||||
export fn foo(num: anytype) i32 {
|
||||
_ = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:15: error: generic parameters not allowed in function with calling convention 'C'
|
||||
@ -0,0 +1,20 @@
|
||||
extern fn foo(comptime x: i32, y: i32) i32;
|
||||
fn f() i32 {
|
||||
return foo(1, 2);
|
||||
}
|
||||
pub extern fn entry1(b: u32, comptime a: [2]u8, c: i32) void;
|
||||
pub extern fn entry2(b: u32, noalias a: anytype, i43) void;
|
||||
comptime { _ = f; }
|
||||
comptime { _ = entry1; }
|
||||
comptime { _ = entry2; }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:12: error: extern function cannot be generic
|
||||
// :5:30: note: function is generic because of this parameter
|
||||
// :6:12: error: extern function cannot be generic
|
||||
// :6:30: note: function is generic because of this parameter
|
||||
// :1:8: error: extern function cannot be generic
|
||||
// :1:15: note: function is generic because of this parameter
|
||||
@ -39,7 +39,7 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :33:8: error: extern structs cannot contain fields of type 'tmp.E'
|
||||
// :33:8: note: enum tag type 'u9' is not extern compatible
|
||||
// :33:8: note: only integers with power of two bits are extern compatible
|
||||
// :31:5: error: extern structs cannot contain fields of type 'tmp.E'
|
||||
// :31:5: note: enum tag type 'u9' is not extern compatible
|
||||
// :31:5: note: only integers with power of two bits are extern compatible
|
||||
// :1:15: note: enum declared here
|
||||
|
||||
@ -11,7 +11,7 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:8: error: extern structs cannot contain fields of type 'tmp.E'
|
||||
// :5:8: note: enum tag type 'u31' is not extern compatible
|
||||
// :5:8: note: only integers with power of two bits are extern compatible
|
||||
// :3:5: error: extern structs cannot contain fields of type 'tmp.E'
|
||||
// :3:5: note: enum tag type 'u31' is not extern compatible
|
||||
// :3:5: note: only integers with power of two bits are extern compatible
|
||||
// :1:15: note: enum declared here
|
||||
|
||||
@ -14,7 +14,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:30: error: extern union does not support enum tag type
|
||||
// :6:30: error: extern union does not support enum tag type
|
||||
@ -2,7 +2,7 @@ extern fn foo() align(3) void;
|
||||
export fn entry() void { return foo(); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:23: error: alignment value 3 is not a power of 2
|
||||
// :1:23: error: alignment value '3' is not a power of two
|
||||
@ -11,3 +11,4 @@ fn concat() [16]f32 {
|
||||
// target=native
|
||||
//
|
||||
// :3:17: error: expected type '[4]f32', found '[16]f32'
|
||||
// :3:17: note: array of length 16 cannot cast into an array of length 4
|
||||
|
||||
@ -20,10 +20,11 @@ export fn entry4() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:28: error: parameter of opaque type 'FooType' not allowed
|
||||
// tmp.zig:8:28: error: parameter of type '@Type(.Null)' not allowed
|
||||
// tmp.zig:12:11: error: parameter of opaque type 'FooType' not allowed
|
||||
// tmp.zig:17:11: error: parameter of type '@Type(.Null)' not allowed
|
||||
// :3:28: error: parameter of opaque type 'tmp.FooType' not allowed
|
||||
// :1:17: note: opaque declared here
|
||||
// :8:28: error: parameter of type '@TypeOf(null)' not allowed
|
||||
// :12:8: error: parameter of opaque type 'tmp.FooType' not allowed
|
||||
// :17:8: error: parameter of type '@TypeOf(null)' not allowed
|
||||
28
test/cases/compile_errors/function_ptr_alignment.zig
Normal file
28
test/cases/compile_errors/function_ptr_alignment.zig
Normal file
@ -0,0 +1,28 @@
|
||||
comptime {
|
||||
var a: *align(2) @TypeOf(foo) = undefined;
|
||||
_ = a;
|
||||
}
|
||||
fn foo() void {}
|
||||
|
||||
comptime {
|
||||
var a: *align(1) fn () void = undefined;
|
||||
_ = a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(2) fn () align(2) void = undefined;
|
||||
_ = a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(2) fn () void = undefined;
|
||||
_ = a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(1) fn () align(2) void = undefined;
|
||||
_ = a;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :20:19: error: function pointer alignment disagrees with function alignment
|
||||
19
test/cases/compile_errors/function_returning_opaque_type.zig
Normal file
19
test/cases/compile_errors/function_returning_opaque_type.zig
Normal file
@ -0,0 +1,19 @@
|
||||
const FooType = opaque {};
|
||||
export fn bar() !FooType {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
export fn bav() !@TypeOf(null) {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
export fn baz() !@TypeOf(undefined) {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:18: error: opaque return type 'tmp.FooType' not allowed
|
||||
// :1:17: note: opaque declared here
|
||||
// :5:18: error: return type '@TypeOf(null)' not allowed
|
||||
// :8:18: error: return type '@TypeOf(undefined)' not allowed
|
||||
@ -0,0 +1,11 @@
|
||||
const Foo = enum { A, B, C };
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
|
||||
// :2:17: note: enum tag type 'u2' is not extern compatible
|
||||
// :2:17: note: only integers with power of two bits are extern compatible
|
||||
// :1:13: note: enum declared here
|
||||
@ -0,0 +1,14 @@
|
||||
const Foo = struct {
|
||||
A: i32,
|
||||
B: f32,
|
||||
C: bool,
|
||||
};
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
|
||||
// :6:17: note: only structs with packed or extern layout are extern compatible
|
||||
// :1:13: note: struct declared here
|
||||
@ -0,0 +1,14 @@
|
||||
const Foo = union {
|
||||
A: i32,
|
||||
B: f32,
|
||||
C: bool,
|
||||
};
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
|
||||
// :6:17: note: only unions with packed or extern layout are extern compatible
|
||||
// :1:13: note: union declared here
|
||||
@ -0,0 +1,13 @@
|
||||
fn foo(comptime x: i32, y: i32) i32 { return x + y; }
|
||||
fn test1(a: i32, b: i32) i32 {
|
||||
return foo(a, b);
|
||||
}
|
||||
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(&test1)); }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:16: error: unable to resolve comptime value
|
||||
// :3:16: note: parameter is comptime
|
||||
@ -5,7 +5,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:9: error: expected type '[]i32', found '[10]i32'
|
||||
// :4:9: error: array literal requires address-of operator (&) to coerce to slice type '[]i32'
|
||||
@ -13,7 +13,8 @@ fn bar(x: *u32) void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:8:13: error: expected type '*u32', found '*align(1) u32'
|
||||
// :8:9: error: expected type '*u32', found '*align(1) u32'
|
||||
// :8:9: note: pointer alignment '1' cannot cast into pointer alignment '4'
|
||||
@ -12,4 +12,6 @@ export fn bar() void {
|
||||
// target=native
|
||||
//
|
||||
// :3:35: error: unable to resolve comptime value
|
||||
// :3:35: note: value being casted to 'comptime_int' must be comptime known
|
||||
// :7:37: error: unable to resolve comptime value
|
||||
// :7:37: note: value being casted to 'comptime_float' must be comptime known
|
||||
|
||||
@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:8: error: extern structs cannot contain fields of type '?[*c]u8'
|
||||
// :4:8: note: only pointer like optionals are extern compatible
|
||||
// :2:5: error: extern structs cannot contain fields of type '?[*c]u8'
|
||||
// :2:5: note: only pointer like optionals are extern compatible
|
||||
|
||||
@ -7,7 +7,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:28: error: attempt to read 8 bytes from pointer to f32 which is 4 bytes
|
||||
// :5:28: error: dereference of '*const i64' exceeds bounds of containing decl of type 'f32'
|
||||
@ -14,5 +14,5 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:26: error: unable to resolve comptime value
|
||||
// :6:26: error: cannot store to runtime value in comptime block
|
||||
// :4:17: note: called from here
|
||||
|
||||
@ -7,7 +7,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:19: error: expected enum tag type, found 'u32'
|
||||
// :1:19: error: expected enum tag type, found 'u32'
|
||||
@ -7,7 +7,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:24: error: expected integer tag type, found 'f32'
|
||||
// :1:24: error: expected integer tag type, found 'f32'
|
||||
13
test/cases/compile_errors/non-integer_tag_type_to_enum.zig
Normal file
13
test/cases/compile_errors/non-integer_tag_type_to_enum.zig
Normal file
@ -0,0 +1,13 @@
|
||||
const Foo = enum(f32) {
|
||||
A,
|
||||
};
|
||||
export fn entry() void {
|
||||
var f: Foo = undefined;
|
||||
_ = f;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:18: error: expected integer tag type, found 'f32'
|
||||
@ -21,5 +21,5 @@ export fn function_with_return_type_type() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:7: error: unable to resolve comptime value
|
||||
// :3:7: error: cannot load runtime value in comptime block
|
||||
// :16:19: note: called from here
|
||||
|
||||
@ -10,5 +10,5 @@ export fn entry() usize { return @offsetOf(Foo, "y"); }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:25: error: unable to resolve comptime value
|
||||
// :5:25: error: cannot load runtime value in comptime block
|
||||
// :2:15: note: called from here
|
||||
|
||||
@ -5,7 +5,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:25: error: opaque types cannot have fields
|
||||
// :1:25: error: opaque types cannot have fields
|
||||
@ -8,10 +8,11 @@ fn ptrEql(a: *[]const u8, b: *[]const u8) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:19: error: expected type '*[]const u8', found '*const []const u8'
|
||||
// :4:19: error: expected type '*[]const u8', found '*const []const u8'
|
||||
// :4:19: note: cast discards const qualifier
|
||||
@ -2,7 +2,7 @@ fn a() *noreturn {}
|
||||
export fn entry() void { _ = a(); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:9: error: pointer to noreturn not allowed
|
||||
// :1:9: error: pointer to noreturn not allowed
|
||||
@ -7,5 +7,5 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:19: error: type '[]u8' does not support array initialization syntax
|
||||
// :2:19: note: inferred array length is specified with an underscore: '[_]u8'
|
||||
// :2:15: error: type '[]u8' does not support array initialization syntax
|
||||
// :2:15: note: inferred array length is specified with an underscore: '[_]u8'
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
const Foo = struct {};
|
||||
export fn a() void {
|
||||
const T = [*c]Foo;
|
||||
var t: T = undefined;
|
||||
_ = t;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'
|
||||
@ -1,9 +0,0 @@
|
||||
export fn foo() align(1) void {
|
||||
return;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=wasm32-freestanding-none
|
||||
//
|
||||
// tmp.zig:1:23: error: align(N) expr is not allowed on function prototypes in wasm32/wasm64
|
||||
@ -1,14 +0,0 @@
|
||||
export fn zig_array(x: [10]u8) void {
|
||||
try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
|
||||
}
|
||||
const std = @import("std");
|
||||
export fn zig_return_array() [10]u8 {
|
||||
return "1234567890".*;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:24: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
|
||||
// tmp.zig:5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
|
||||
@ -1,8 +0,0 @@
|
||||
fn a() i32 {}
|
||||
export fn entry() void { _ = a(); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:12: error: expected type 'i32', found 'void'
|
||||
@ -1,29 +0,0 @@
|
||||
const O = opaque {};
|
||||
const Foo = struct {
|
||||
o: O,
|
||||
};
|
||||
const Bar = union {
|
||||
One: i32,
|
||||
Two: O,
|
||||
};
|
||||
export fn a() void {
|
||||
var foo: Foo = undefined;
|
||||
_ = foo;
|
||||
}
|
||||
export fn b() void {
|
||||
var bar: Bar = undefined;
|
||||
_ = bar;
|
||||
}
|
||||
export fn c() void {
|
||||
var baz: *opaque {} = undefined;
|
||||
const qux = .{baz.*};
|
||||
_ = qux;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs
|
||||
// tmp.zig:7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions
|
||||
// tmp.zig:19:22: error: opaque types have unknown size and therefore cannot be directly embedded in structs
|
||||
@ -1,12 +0,0 @@
|
||||
const seventh_fib_number = fibonacci(7);
|
||||
fn fibonacci(x: i32) i32 {
|
||||
return fibonacci(x - 1) + fibonacci(x - 2);
|
||||
}
|
||||
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(seventh_fib_number)); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:21: error: evaluation exceeded 1000 backwards branches
|
||||
@ -1,9 +0,0 @@
|
||||
export fn foo(comptime x: i32, y: i32) i32{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'
|
||||
@ -1,10 +0,0 @@
|
||||
export fn foo(num: anytype) i32 {
|
||||
_ = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:15: error: parameter of type 'anytype' not allowed in function with calling convention 'C'
|
||||
@ -1,11 +0,0 @@
|
||||
extern fn foo(comptime x: i32, y: i32) i32;
|
||||
fn f() i32 {
|
||||
return foo(1, 2);
|
||||
}
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(f)); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'
|
||||
@ -1,19 +0,0 @@
|
||||
const FooType = opaque {};
|
||||
export fn bar() !FooType {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
export fn bav() !@TypeOf(null) {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
export fn baz() !@TypeOf(undefined) {
|
||||
return error.InvalidValue;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:18: error: Opaque return type 'FooType' not allowed
|
||||
// tmp.zig:1:1: note: type declared here
|
||||
// tmp.zig:5:18: error: Null return type '@Type(.Null)' not allowed
|
||||
// tmp.zig:8:18: error: Undefined return type '@Type(.Undefined)' not allowed
|
||||
@ -1,8 +0,0 @@
|
||||
const Foo = enum { A, B, C };
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'
|
||||
@ -1,12 +0,0 @@
|
||||
const Foo = struct {
|
||||
A: i32,
|
||||
B: f32,
|
||||
C: bool,
|
||||
};
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'
|
||||
@ -1,12 +0,0 @@
|
||||
const Foo = union {
|
||||
A: i32,
|
||||
B: f32,
|
||||
C: bool,
|
||||
};
|
||||
export fn entry(foo: Foo) void { _ = foo; }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'
|
||||
@ -1,12 +0,0 @@
|
||||
fn foo(comptime x: i32, y: i32) i32 { return x + y; }
|
||||
fn test1(a: i32, b: i32) i32 {
|
||||
return foo(a, b);
|
||||
}
|
||||
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(test1)); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:16: error: runtime value cannot be passed to comptime arg
|
||||
@ -1,7 +0,0 @@
|
||||
export const T = [*]opaque {};
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:21: error: unknown-length pointer to opaque
|
||||
@ -1,14 +0,0 @@
|
||||
export fn entry() void {
|
||||
var x: i32 = 1234;
|
||||
var p: *i32 = &x;
|
||||
var pp: *?*i32 = &p;
|
||||
pp.* = null;
|
||||
var y = p.*;
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:23: error: expected type '*?*i32', found '**i32'
|
||||
@ -1,12 +0,0 @@
|
||||
const Derp = opaque {};
|
||||
extern fn bar(d: *Derp) void;
|
||||
export fn foo() void {
|
||||
var x = @as(u8, 1);
|
||||
bar(@ptrCast(*anyopaque, &x));
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:9: error: expected type '*Derp', found '*anyopaque'
|
||||
@ -16,6 +16,6 @@ export fn entry() usize {
|
||||
// error
|
||||
// target=native
|
||||
//
|
||||
// :7:1: error: enum field(s) missing in union
|
||||
// :7:11: error: enum field(s) missing in union
|
||||
// :4:5: note: field 'c' missing, declared here
|
||||
// :1:11: note: enum declared here
|
||||
|
||||
@ -16,5 +16,5 @@ export fn entry() usize {
|
||||
// error
|
||||
// target=native
|
||||
//
|
||||
// :6:1: error: enum 'tmp.E' has no field named 'd'
|
||||
// :10:5: error: enum 'tmp.E' has no field named 'd'
|
||||
// :1:11: note: enum declared here
|
||||
|
||||
@ -19,5 +19,5 @@ export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
|
||||
// target=native
|
||||
//
|
||||
// :8:5: error: switch must handle all possibilities
|
||||
// :8:5: note: unhandled enumeration value: 'Four'
|
||||
// :5:5: note: unhandled enumeration value: 'Four'
|
||||
// :1:16: note: enum 'tmp.Number' declared here
|
||||
|
||||
@ -10,5 +10,5 @@ export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :5:5: error: switch must handle all possibilities
|
||||
// :5:5: note: unhandled enumeration value: 'M'
|
||||
// :1:20: note: unhandled enumeration value: 'M'
|
||||
// :1:13: note: enum 'tmp.Foo' declared here
|
||||
|
||||
@ -7,16 +7,21 @@ const U = union(E) {
|
||||
a: i32,
|
||||
b: u32,
|
||||
};
|
||||
pub export fn entry() void {
|
||||
pub export fn entry1() void {
|
||||
var e: E = .b;
|
||||
switch (e) { // error: switch not handling the tag `b`
|
||||
.a => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
pub export fn entry2() void {
|
||||
var e: E = .b;
|
||||
switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong
|
||||
.a => {},
|
||||
.b => {},
|
||||
}
|
||||
}
|
||||
pub export fn entry3() void {
|
||||
var u = U{.a = 2};
|
||||
switch (u) { // error: `_` prong not allowed when switching on tagged union
|
||||
.a => {},
|
||||
@ -26,10 +31,12 @@ pub export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:12:5: error: enumeration value 'E.b' not handled in switch
|
||||
// tmp.zig:16:5: error: switch on non-exhaustive enum must include `else` or `_` prong
|
||||
// tmp.zig:21:5: error: `_` prong not allowed when switching on tagged union
|
||||
// :12:5: error: switch must handle all possibilities
|
||||
// :3:5: note: unhandled enumeration value: 'b'
|
||||
// :1:11: note: enum 'tmp.E' declared here
|
||||
// :19:5: error: switch on non-exhaustive enum must include 'else' or '_' prong
|
||||
// :26:5: error: '_' prong only allowed when switching on non-exhaustive enums
|
||||
// :29:11: note: '_' prong here
|
||||
@ -10,6 +10,6 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:6: error: expected type '*const fn(*const u8) void', found '*const fn(u8) void'
|
||||
// :6:6: note: pointer type child 'fn(u8) void' cannot cast into pointer type child 'fn(*const u8) void'
|
||||
// :6:6: note: parameter 0 'u8' cannot cast into '*const u8'
|
||||
// :6:7: error: expected type '*const fn(*const u8) void', found '*const fn(u8) void'
|
||||
// :6:7: note: pointer type child 'fn(u8) void' cannot cast into pointer type child 'fn(*const u8) void'
|
||||
// :6:7: note: parameter 0 'u8' cannot cast into '*const u8'
|
||||
|
||||
@ -15,6 +15,6 @@ export fn entry() usize {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:1: error: enum field(s) missing in union
|
||||
// :6:17: error: enum field(s) missing in union
|
||||
// :4:5: note: field 'C' missing, declared here
|
||||
// :1:16: note: enum declared here
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
export const T = [*]opaque {};
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:21: error: unknown-length pointer to opaque not allowed
|
||||
@ -2,7 +2,7 @@ fn f(a: noreturn) void { _ = a; }
|
||||
export fn entry() void { f(); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:9: error: parameter of type 'noreturn' not allowed
|
||||
// :1:6: error: parameter of type 'noreturn' not allowed
|
||||
@ -4,7 +4,7 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:20: error: return type cannot be opaque
|
||||
// :2:20: error: opaque return type 'anyopaque' not allowed
|
||||
@ -0,0 +1,16 @@
|
||||
export fn entry() void {
|
||||
var x: i32 = 1234;
|
||||
var p: *i32 = &x;
|
||||
var pp: *?*i32 = &p;
|
||||
pp.* = null;
|
||||
var y = p.*;
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:22: error: expected type '*?*i32', found '**i32'
|
||||
// :4:22: note: pointer type child '*i32' cannot cast into pointer type child '?*i32'
|
||||
// :4:22: note: mutable '*i32' allows illegal null values stored to type '?*i32'
|
||||
@ -7,7 +7,7 @@ comptime {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:21: error: expected array type or [_], found '[*][*]const u8'
|
||||
// :1:22: error: type '[*][*]const u8' does not support array initialization syntax
|
||||
@ -10,7 +10,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:9:8: error: use of undefined value here causes undefined behavior
|
||||
// :9:14: error: expected type 'type', found 'tmp.U'
|
||||
// :1:11: note: union declared here
|
||||
@ -0,0 +1,14 @@
|
||||
const Derp = opaque {};
|
||||
extern fn bar(d: *Derp) void;
|
||||
export fn foo() void {
|
||||
var x = @as(u8, 1);
|
||||
bar(@ptrCast(*anyopaque, &x));
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:9: error: expected type '*tmp.Derp', found '*anyopaque'
|
||||
// :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp'
|
||||
// :1:14: note: opaque declared here
|
||||
@ -6,4 +6,4 @@ extern var foo: i32;
|
||||
|
||||
// error
|
||||
//
|
||||
// :2:15: error: unable to resolve comptime value
|
||||
// :2:15: error: cannot load runtime value in comptime block
|
||||
|
||||
@ -22,3 +22,4 @@ pub fn assert(ok: bool) void {
|
||||
// error
|
||||
//
|
||||
// :3:21: error: unable to resolve comptime value
|
||||
// :3:21: note: condition in comptime branch must be comptime known
|
||||
|
||||
@ -17,3 +17,4 @@ pub fn assert(ok: bool) void {
|
||||
// error
|
||||
//
|
||||
// :5:21: error: unable to resolve comptime value
|
||||
// :5:21: note: condition in comptime branch must be comptime known
|
||||
|
||||
@ -51,8 +51,8 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\}
|
||||
\\var y: @import("std").builtin.CallingConvention = .C;
|
||||
, &.{
|
||||
":2:22: error: unable to resolve comptime value",
|
||||
":5:26: error: unable to resolve comptime value",
|
||||
":2:22: error: cannot load runtime value in comptime block",
|
||||
":5:26: error: cannot load runtime value in comptime block",
|
||||
});
|
||||
}
|
||||
|
||||
@ -772,7 +772,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\}
|
||||
, &.{
|
||||
":4:5: error: switch must handle all possibilities",
|
||||
":4:5: note: unhandled enumeration value: 'b'",
|
||||
":1:21: note: unhandled enumeration value: 'b'",
|
||||
":1:11: note: enum 'tmp.E' declared here",
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user