mirror of
https://github.com/ziglang/zig.git
synced 2026-01-06 05:25:10 +00:00
commit
ecf56d85ef
@ -346,14 +346,8 @@ pub const TypeInfo = union(enum) {
|
||||
decls: []const Declaration,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
/// TODO rename to Param and put inside `Fn`.
|
||||
pub const FnArg = struct {
|
||||
is_generic: bool,
|
||||
is_noalias: bool,
|
||||
arg_type: ?type,
|
||||
};
|
||||
/// TODO deprecated use Fn.Param
|
||||
pub const FnArg = Fn.Param;
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
@ -363,7 +357,15 @@ pub const TypeInfo = union(enum) {
|
||||
is_generic: bool,
|
||||
is_var_args: bool,
|
||||
return_type: ?type,
|
||||
args: []const FnArg,
|
||||
args: []const Param,
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Param = struct {
|
||||
is_generic: bool,
|
||||
is_noalias: bool,
|
||||
arg_type: ?type,
|
||||
};
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
|
||||
@ -947,7 +947,7 @@ fn testRem() !void {
|
||||
/// Result is an unsigned integer.
|
||||
pub fn absCast(x: anytype) switch (@typeInfo(@TypeOf(x))) {
|
||||
.ComptimeInt => comptime_int,
|
||||
.Int => |intInfo| std.meta.Int(.unsigned, intInfo.bits),
|
||||
.Int => |int_info| std.meta.Int(.unsigned, int_info.bits),
|
||||
else => @compileError("absCast only accepts integers"),
|
||||
} {
|
||||
switch (@typeInfo(@TypeOf(x))) {
|
||||
@ -958,8 +958,9 @@ pub fn absCast(x: anytype) switch (@typeInfo(@TypeOf(x))) {
|
||||
return x;
|
||||
}
|
||||
},
|
||||
.Int => |intInfo| {
|
||||
const Uint = std.meta.Int(.unsigned, intInfo.bits);
|
||||
.Int => |int_info| {
|
||||
if (int_info.signedness == .unsigned) return x;
|
||||
const Uint = std.meta.Int(.unsigned, int_info.bits);
|
||||
if (x < 0) {
|
||||
return ~@bitCast(Uint, x +% -1);
|
||||
} else {
|
||||
|
||||
87
src/Sema.zig
87
src/Sema.zig
@ -3351,9 +3351,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
|
||||
// Check for the possibility of this pattern:
|
||||
// %a = ret_ptr
|
||||
// %b = store(%a, %c)
|
||||
// Where %c is an error union. In such case we need to add to the current function's
|
||||
// inferred error set, if any.
|
||||
if (sema.typeOf(operand).zigTypeTag() == .ErrorUnion and
|
||||
// Where %c is an error union or error set. In such case we need to add
|
||||
// to the current function's inferred error set, if any.
|
||||
if ((sema.typeOf(operand).zigTypeTag() == .ErrorUnion or
|
||||
sema.typeOf(operand).zigTypeTag() == .ErrorSet) and
|
||||
sema.fn_ret_ty.zigTypeTag() == .ErrorUnion)
|
||||
{
|
||||
if (Zir.refToIndex(extra.lhs)) |ptr_index| {
|
||||
@ -7665,6 +7666,8 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
|
||||
const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
|
||||
|
||||
// tuples are structs but they don't have a namespace
|
||||
if (container_type.isTuple()) return Air.Inst.Ref.bool_false;
|
||||
const namespace = container_type.getNamespace() orelse return sema.fail(
|
||||
block,
|
||||
lhs_src,
|
||||
@ -9886,7 +9889,65 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
}),
|
||||
),
|
||||
.Fn => {
|
||||
// TODO: look into memoizing this result.
|
||||
const info = ty.fnInfo();
|
||||
var params_anon_decl = try block.startAnonDecl(src);
|
||||
defer params_anon_decl.deinit();
|
||||
|
||||
const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
|
||||
for (param_vals) |*param_val, i| {
|
||||
const param_ty = info.param_types[i];
|
||||
const is_generic = param_ty.tag() == .generic_poison;
|
||||
const param_ty_val = if (is_generic)
|
||||
Value.@"null"
|
||||
else
|
||||
try Value.Tag.opt_payload.create(
|
||||
params_anon_decl.arena(),
|
||||
try Value.Tag.ty.create(params_anon_decl.arena(), param_ty),
|
||||
);
|
||||
|
||||
const param_fields = try params_anon_decl.arena().create([3]Value);
|
||||
param_fields.* = .{
|
||||
// is_generic: bool,
|
||||
Value.makeBool(is_generic),
|
||||
// is_noalias: bool,
|
||||
Value.@"false", // TODO
|
||||
// arg_type: ?type,
|
||||
param_ty_val,
|
||||
};
|
||||
param_val.* = try Value.Tag.@"struct".create(params_anon_decl.arena(), param_fields);
|
||||
}
|
||||
|
||||
const args_val = v: {
|
||||
const fn_info_decl = (try sema.namespaceLookup(
|
||||
block,
|
||||
src,
|
||||
type_info_ty.getNamespace().?,
|
||||
"Fn",
|
||||
)).?;
|
||||
try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);
|
||||
try sema.ensureDeclAnalyzed(fn_info_decl);
|
||||
const param_info_decl = (try sema.namespaceLookup(
|
||||
block,
|
||||
src,
|
||||
fn_info_decl.val.castTag(.ty).?.data.getNamespace().?,
|
||||
"Param",
|
||||
)).?;
|
||||
try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);
|
||||
try sema.ensureDeclAnalyzed(param_info_decl);
|
||||
const new_decl = try params_anon_decl.finish(
|
||||
try Type.Tag.array.create(params_anon_decl.arena(), .{
|
||||
.len = param_vals.len,
|
||||
.elem_type = param_info_decl.ty,
|
||||
}),
|
||||
try Value.Tag.array.create(
|
||||
params_anon_decl.arena(),
|
||||
param_vals,
|
||||
),
|
||||
);
|
||||
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
|
||||
};
|
||||
|
||||
const field_values = try sema.arena.alloc(Value, 6);
|
||||
// calling_convention: CallingConvention,
|
||||
field_values[0] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc));
|
||||
@ -9897,9 +9958,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
// is_var_args: bool,
|
||||
field_values[3] = Value.makeBool(info.is_var_args);
|
||||
// return_type: ?type,
|
||||
field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
|
||||
// args: []const FnArg,
|
||||
field_values[5] = Value.@"null"; // TODO
|
||||
field_values[4] = try Value.Tag.ty.create(sema.arena, info.return_type);
|
||||
// args: []const Fn.Param,
|
||||
field_values[5] = args_val;
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
@ -10102,7 +10163,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
}),
|
||||
try Value.Tag.array.create(
|
||||
fields_anon_decl.arena(),
|
||||
try fields_anon_decl.arena().dupe(Value, enum_field_vals),
|
||||
enum_field_vals,
|
||||
),
|
||||
);
|
||||
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
|
||||
@ -12128,7 +12189,7 @@ fn checkPtrOperand(
|
||||
ty: Type,
|
||||
) CompileError!void {
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Pointer => {},
|
||||
.Pointer => return,
|
||||
.Fn => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
@ -12145,8 +12206,10 @@ fn checkPtrOperand(
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
},
|
||||
else => return sema.fail(block, ty_src, "expected pointer, found '{}'", .{ty}),
|
||||
.Optional => if (ty.isPtrLikeOptional()) return,
|
||||
else => {},
|
||||
}
|
||||
return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty});
|
||||
}
|
||||
|
||||
fn checkPtrType(
|
||||
@ -12156,7 +12219,7 @@ fn checkPtrType(
|
||||
ty: Type,
|
||||
) CompileError!void {
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Pointer => {},
|
||||
.Pointer => return,
|
||||
.Fn => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
@ -12173,8 +12236,10 @@ fn checkPtrType(
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
},
|
||||
else => return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty}),
|
||||
.Optional => if (ty.isPtrLikeOptional()) return,
|
||||
else => {},
|
||||
}
|
||||
return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty});
|
||||
}
|
||||
|
||||
fn checkVectorElemType(
|
||||
|
||||
@ -18750,8 +18750,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
|
||||
return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
|
||||
fields[4]->data.x_optional = return_type;
|
||||
}
|
||||
// args: []TypeInfo.FnArg
|
||||
ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
|
||||
// args: []TypeInfo.Fn.Param
|
||||
ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "Param", result->type);
|
||||
if ((err = type_resolve(g, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -19614,14 +19614,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
assert(args_arr->data.x_array.special == ConstArraySpecialNone);
|
||||
for (size_t i = 0; i < args_len; i++) {
|
||||
ZigValue *arg_value = &args_arr->data.x_array.data.s_none.elements[i];
|
||||
assert(arg_value->type == ir_type_info_get_type(ira, "FnArg", nullptr));
|
||||
FnTypeParamInfo *info = &fn_type_id.param_info[i];
|
||||
Error err;
|
||||
bool is_generic;
|
||||
if ((err = get_const_field_bool(ira, source_node, arg_value, "is_generic", 0, &is_generic)))
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
if (is_generic) {
|
||||
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.FnArg.is_generic must be false for @Type"));
|
||||
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.Fn.Param.is_generic must be false for @Type"));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
if ((err = get_const_field_bool(ira, source_node, arg_value, "is_noalias", 1, &info->is_noalias)))
|
||||
@ -19629,7 +19628,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
ZigType *type = get_const_field_meta_type_optional(
|
||||
ira, source_node, arg_value, "arg_type", 2);
|
||||
if (type == nullptr) {
|
||||
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.FnArg.arg_type must be non-null for @Type"));
|
||||
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.Fn.Param.arg_type must be non-null for @Type"));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
info->type = type;
|
||||
|
||||
@ -593,10 +593,12 @@ pub const Type = extern union {
|
||||
|
||||
for (a_info.param_types) |a_param_ty, i| {
|
||||
const b_param_ty = b_info.param_types[i];
|
||||
if (!eql(a_param_ty, b_param_ty))
|
||||
if (a_info.comptime_params[i] != b_info.comptime_params[i])
|
||||
return false;
|
||||
|
||||
if (a_info.comptime_params[i] != b_info.comptime_params[i])
|
||||
if (a_param_ty.tag() == .generic_poison) continue;
|
||||
if (b_param_ty.tag() == .generic_poison) continue;
|
||||
if (!eql(a_param_ty, b_param_ty))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -120,6 +120,15 @@ test {
|
||||
_ = @import("behavior/sizeof_and_typeof.zig");
|
||||
_ = @import("behavior/switch.zig");
|
||||
_ = @import("behavior/widening.zig");
|
||||
_ = @import("behavior/bugs/421.zig");
|
||||
_ = @import("behavior/bugs/726.zig");
|
||||
_ = @import("behavior/bugs/1421.zig");
|
||||
_ = @import("behavior/bugs/2114.zig");
|
||||
_ = @import("behavior/bugs/3742.zig");
|
||||
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
||||
_ = @import("behavior/switch_prong_err_enum.zig");
|
||||
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
||||
_ = @import("behavior/union_with_members.zig");
|
||||
|
||||
if (builtin.zig_backend == .stage1) {
|
||||
// Tests that only pass for the stage1 backend.
|
||||
@ -128,20 +137,15 @@ test {
|
||||
_ = @import("behavior/async_fn.zig");
|
||||
}
|
||||
_ = @import("behavior/await_struct.zig");
|
||||
_ = @import("behavior/bugs/421.zig");
|
||||
_ = @import("behavior/bugs/529.zig");
|
||||
_ = @import("behavior/bugs/718.zig");
|
||||
_ = @import("behavior/bugs/726.zig");
|
||||
_ = @import("behavior/bugs/828.zig");
|
||||
_ = @import("behavior/bugs/920.zig");
|
||||
_ = @import("behavior/bugs/1120.zig");
|
||||
_ = @import("behavior/bugs/1421.zig");
|
||||
_ = @import("behavior/bugs/1442.zig");
|
||||
_ = @import("behavior/bugs/1607.zig");
|
||||
_ = @import("behavior/bugs/1851.zig");
|
||||
_ = @import("behavior/bugs/2114.zig");
|
||||
_ = @import("behavior/bugs/3384.zig");
|
||||
_ = @import("behavior/bugs/3742.zig");
|
||||
_ = @import("behavior/bugs/3779.zig");
|
||||
_ = @import("behavior/bugs/4328.zig");
|
||||
_ = @import("behavior/bugs/5398.zig");
|
||||
@ -161,12 +165,8 @@ test {
|
||||
_ = @import("behavior/muladd.zig");
|
||||
_ = @import("behavior/select.zig");
|
||||
_ = @import("behavior/shuffle.zig");
|
||||
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
||||
_ = @import("behavior/struct_contains_slice_of_itself.zig");
|
||||
_ = @import("behavior/switch_prong_err_enum.zig");
|
||||
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
||||
_ = @import("behavior/typename.zig");
|
||||
_ = @import("behavior/union_with_members.zig");
|
||||
_ = @import("behavior/vector.zig");
|
||||
if (builtin.target.cpu.arch == .wasm32) {
|
||||
_ = @import("behavior/wasm.zig");
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "@src" {
|
||||
// TODO why is this failing on stage1?
|
||||
return error.SkipZigTest;
|
||||
|
||||
// try doTheTest();
|
||||
}
|
||||
|
||||
fn doTheTest() !void {
|
||||
const src = @src();
|
||||
const src = @src(); // do not move
|
||||
|
||||
try expect(src.line == 9);
|
||||
try expect(src.line == 2);
|
||||
try expect(src.column == 17);
|
||||
try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
|
||||
try expect(std.mem.endsWith(u8, src.file, "src.zig"));
|
||||
try expect(src.fn_name[src.fn_name.len] == 0);
|
||||
try expect(src.file[src.file.len] == 0);
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "@src" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest;
|
||||
|
||||
try doTheTest();
|
||||
}
|
||||
|
||||
@ -323,7 +323,9 @@ fn testOpaque() !void {
|
||||
}
|
||||
|
||||
test "type info: function type info" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
|
||||
// wasm doesn't support align attributes on functions
|
||||
if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
|
||||
@ -343,6 +345,7 @@ fn testFunction() !void {
|
||||
const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
|
||||
try expect(fn_aligned_info.Fn.alignment == 4);
|
||||
|
||||
if (builtin.zig_backend != .stage1) return; // no bound fn in stage2
|
||||
const test_instance: TestPackedStruct = undefined;
|
||||
const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
|
||||
try expect(bound_fn_info == .BoundFn);
|
||||
|
||||
@ -450,7 +450,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\ .is_generic = true,
|
||||
\\ .is_var_args = false,
|
||||
\\ .return_type = u0,
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.Fn.Param{},
|
||||
\\ },
|
||||
\\});
|
||||
\\comptime { _ = Foo; }
|
||||
@ -466,7 +466,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\ .is_generic = false,
|
||||
\\ .is_var_args = true,
|
||||
\\ .return_type = u0,
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.Fn.Param{},
|
||||
\\ },
|
||||
\\});
|
||||
\\comptime { _ = Foo; }
|
||||
@ -482,7 +482,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\ .is_generic = false,
|
||||
\\ .is_var_args = false,
|
||||
\\ .return_type = null,
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
|
||||
\\ .args = &[_]@import("std").builtin.TypeInfo.Fn.Param{},
|
||||
\\ },
|
||||
\\});
|
||||
\\comptime { _ = Foo; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user