mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Sema: get restricted function pointers working
This commit is contained in:
+22
-16
@@ -11913,23 +11913,29 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
|
||||
}
|
||||
|
||||
pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
|
||||
const unwrapped_ty = ty.unwrap(ip);
|
||||
const ty_extra = unwrapped_ty.getExtra(ip);
|
||||
const ty_item = unwrapped_ty.getItem(ip);
|
||||
const child_extra, const child_item = switch (ty_item.tag) {
|
||||
.type_pointer => child: {
|
||||
const child_index: Index = @enumFromInt(ty_extra.view().items(.@"0")[
|
||||
ty_item.data + std.meta.fieldIndex(Tag.TypePointer, "child").?
|
||||
]);
|
||||
const unwrapped_child = child_index.unwrap(ip);
|
||||
break :child .{ unwrapped_child.getExtra(ip), unwrapped_child.getItem(ip) };
|
||||
},
|
||||
.type_function => .{ ty_extra, ty_item },
|
||||
else => unreachable,
|
||||
var ty_item, var ty_extra = unwrapped: {
|
||||
const unwrapped_ty = ty.unwrap(ip);
|
||||
break :unwrapped .{ unwrapped_ty.getItem(ip), unwrapped_ty.getExtra(ip) };
|
||||
};
|
||||
assert(child_item.tag == .type_function);
|
||||
return @enumFromInt(child_extra.view().items(.@"0")[
|
||||
child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
|
||||
if (ty_item.tag == .type_restricted) {
|
||||
const unrestricted_ty: Index = @enumFromInt(ty_extra.view().items(.@"0")[
|
||||
ty_item.data + std.meta.fieldIndex(Tag.TypeRestricted, "unrestricted_type").?
|
||||
]);
|
||||
const unwrapped_ty = unrestricted_ty.unwrap(ip);
|
||||
ty_item = unwrapped_ty.getItem(ip);
|
||||
ty_extra = unwrapped_ty.getExtra(ip);
|
||||
}
|
||||
if (ty_item.tag == .type_pointer) {
|
||||
const child_ty: Index = @enumFromInt(ty_extra.view().items(.@"0")[
|
||||
ty_item.data + std.meta.fieldIndex(Tag.TypePointer, "child").?
|
||||
]);
|
||||
const unwrapped_ty = child_ty.unwrap(ip);
|
||||
ty_item = unwrapped_ty.getItem(ip);
|
||||
ty_extra = unwrapped_ty.getExtra(ip);
|
||||
}
|
||||
assert(ty_item.tag == .type_function);
|
||||
return @enumFromInt(ty_extra.view().items(.@"0")[
|
||||
ty_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
+27
-21
@@ -6274,16 +6274,17 @@ fn checkCallArgumentCount(
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const func_ty: Type = func_ty: {
|
||||
switch (callee_ty.zigTypeTag(zcu)) {
|
||||
.@"fn" => break :func_ty callee_ty,
|
||||
const unrestricted_callee_ty = callee_ty.unrestrictedType(zcu) orelse callee_ty;
|
||||
switch (unrestricted_callee_ty.zigTypeTag(zcu)) {
|
||||
.@"fn" => break :func_ty unrestricted_callee_ty,
|
||||
.pointer => {
|
||||
const ptr_info = callee_ty.ptrInfo(zcu);
|
||||
const ptr_info = unrestricted_callee_ty.ptrInfo(zcu);
|
||||
if (ptr_info.flags.size == .one and Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") {
|
||||
break :func_ty .fromInterned(ptr_info.child);
|
||||
}
|
||||
},
|
||||
.optional => {
|
||||
const opt_child = callee_ty.optionalChild(zcu);
|
||||
const opt_child = unrestricted_callee_ty.optionalChild(zcu);
|
||||
if (opt_child.zigTypeTag(zcu) == .@"fn" or (opt_child.isSinglePointer(zcu) and
|
||||
opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))
|
||||
{
|
||||
@@ -7012,13 +7013,21 @@ fn analyzeCall(
|
||||
break :func .{ Air.internedToRef(func_instance), runtime_args.items };
|
||||
};
|
||||
|
||||
ref_func: {
|
||||
const runtime_func_val = sema.resolveValue(runtime_func) orelse break :ref_func;
|
||||
if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func;
|
||||
const orig_fn_index = ip.unwrapCoercedFunc(runtime_func_val.toIntern());
|
||||
try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = orig_fn_index }));
|
||||
try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index);
|
||||
}
|
||||
const unrestricted_runtime_func: Air.Inst.Ref = if (sema.resolveValue(runtime_func)) |runtime_func_val| unrestricted_runtime_func: {
|
||||
const unrestricted_runtime_func_val = switch (ip.indexToKey(runtime_func_val.toIntern())) {
|
||||
else => runtime_func_val.toIntern(),
|
||||
.restricted_value => |restricted_value| restricted_value.unrestricted_value,
|
||||
};
|
||||
if (ip.isFuncBody(unrestricted_runtime_func_val)) {
|
||||
const orig_fn_index = ip.unwrapCoercedFunc(unrestricted_runtime_func_val);
|
||||
try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = orig_fn_index }));
|
||||
try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index);
|
||||
}
|
||||
break :unrestricted_runtime_func .fromIntern(unrestricted_runtime_func_val);
|
||||
} else if (sema.typeOf(runtime_func).unrestrictedType(zcu)) |unrestricted_ty|
|
||||
try sema.unwrapRestricted(block, unrestricted_ty, runtime_func, func_src)
|
||||
else
|
||||
runtime_func;
|
||||
|
||||
const call_tag: Air.Inst.Tag = switch (modifier) {
|
||||
.auto, .no_suspend => .call,
|
||||
@@ -7035,7 +7044,7 @@ fn analyzeCall(
|
||||
const call_ref = try block.addInst(.{
|
||||
.tag = call_tag,
|
||||
.data = .{ .pl_op = .{
|
||||
.operand = runtime_func,
|
||||
.operand = unrestricted_runtime_func,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.Call{
|
||||
.args_len = @intCast(runtime_args.len),
|
||||
}),
|
||||
@@ -7050,10 +7059,10 @@ fn analyzeCall(
|
||||
}
|
||||
|
||||
if (call_tag == .call_always_tail) {
|
||||
const func_or_ptr_ty = sema.typeOf(runtime_func);
|
||||
const runtime_func_ty = switch (func_or_ptr_ty.zigTypeTag(zcu)) {
|
||||
.@"fn" => func_or_ptr_ty,
|
||||
.pointer => func_or_ptr_ty.childType(zcu),
|
||||
const unrestricted_runtime_func_ty = sema.typeOf(unrestricted_runtime_func);
|
||||
const runtime_func_ty = switch (unrestricted_runtime_func_ty.zigTypeTag(zcu)) {
|
||||
.@"fn" => unrestricted_runtime_func_ty,
|
||||
.pointer => unrestricted_runtime_func_ty.childType(zcu),
|
||||
else => unreachable,
|
||||
};
|
||||
const result = sema.coerceExtra(block, sema.fn_ret_ty, call_ref, call_src, .{ .is_ret = true }) catch |err| switch (err) {
|
||||
@@ -9129,11 +9138,8 @@ fn analyzeAs(
|
||||
const zcu = pt.zcu;
|
||||
const operand = sema.resolveInst(zir_operand);
|
||||
const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
|
||||
switch (dest_ty.zigTypeTag(zcu)) {
|
||||
.@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}),
|
||||
.noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
|
||||
else => {},
|
||||
}
|
||||
if (dest_ty.toIntern() == .noreturn_type) return sema.fail(block, src, "cannot cast to noreturn", .{});
|
||||
if (zcu.intern_pool.isOpaqueType(dest_ty.toIntern())) return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)});
|
||||
|
||||
const is_ret = if (zir_dest_type.toIndex()) |ptr_index|
|
||||
sema.code.instructions.items(.tag)[@intFromEnum(ptr_index)] == .ret_type
|
||||
|
||||
@@ -289,7 +289,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
assert(!field_ty.isGenericPoison());
|
||||
const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) });
|
||||
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
|
||||
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
|
||||
if (ip.isOpaqueType(field_ty.toIntern())) {
|
||||
return sema.failWithOwnedErrorMsg(&block, msg: {
|
||||
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)});
|
||||
errdefer msg.destroy(gpa);
|
||||
|
||||
Reference in New Issue
Block a user