mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 10:03:21 +00:00
Merge branch 'FireFox317-lazy-typeinfo-decls'
Closes #4435 Closes #3893 Closes #2584
This commit is contained in:
commit
662996e4a8
@ -437,7 +437,7 @@ pub fn eql(a: var, b: @TypeOf(a)) bool {
|
||||
},
|
||||
.Pointer => |info| {
|
||||
return switch (info.size) {
|
||||
.One, .Many, .C, => a == b,
|
||||
.One, .Many, .C => a == b,
|
||||
.Slice => a.ptr == b.ptr and a.len == b.len,
|
||||
};
|
||||
},
|
||||
@ -559,7 +559,9 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int {
|
||||
/// Given a type, reference all the declarations inside, so that the semantic analyzer sees them.
|
||||
pub fn refAllDecls(comptime T: type) void {
|
||||
if (!builtin.is_test) return;
|
||||
_ = declarations(T);
|
||||
inline for (declarations(T)) |decl| {
|
||||
_ = decl;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice of pointers to public declarations of a namespace.
|
||||
|
||||
@ -369,12 +369,22 @@ enum LazyValueId {
|
||||
LazyValueIdFnType,
|
||||
LazyValueIdErrUnionType,
|
||||
LazyValueIdArrayType,
|
||||
LazyValueIdTypeInfoDecls,
|
||||
};
|
||||
|
||||
struct LazyValue {
|
||||
LazyValueId id;
|
||||
};
|
||||
|
||||
struct LazyValueTypeInfoDecls {
|
||||
LazyValue base;
|
||||
|
||||
IrAnalyze *ira;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
IrInst *source_instr;
|
||||
};
|
||||
|
||||
struct LazyValueAlignOf {
|
||||
LazyValue base;
|
||||
|
||||
|
||||
@ -1150,6 +1150,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdPtrType: {
|
||||
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
|
||||
@ -1209,6 +1210,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdPtrType:
|
||||
@ -1230,6 +1232,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType: {
|
||||
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
|
||||
@ -1303,6 +1306,7 @@ start_over:
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType: {
|
||||
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
|
||||
@ -1370,6 +1374,7 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdPtrType:
|
||||
@ -1412,6 +1417,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
|
||||
case LazyValueIdInvalid:
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdTypeInfoDecls:
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType: // it has the len field
|
||||
case LazyValueIdOptType: // it has the optional bit
|
||||
|
||||
45
src/ir.cpp
45
src/ir.cpp
@ -21221,6 +21221,13 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
if (type_is_invalid(struct_val->type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
// This to allow lazy values to be resolved.
|
||||
if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
|
||||
source_instr->source_node, struct_val, UndefOk)))
|
||||
{
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
if (initializing && struct_val->special == ConstValSpecialUndef) {
|
||||
struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count);
|
||||
struct_val->special = ConstValSpecialStatic;
|
||||
@ -23626,7 +23633,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
|
||||
}
|
||||
|
||||
static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val,
|
||||
ScopeDecls *decls_scope)
|
||||
ScopeDecls *decls_scope, bool resolve_types)
|
||||
{
|
||||
Error err;
|
||||
ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr);
|
||||
@ -23637,6 +23644,24 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
|
||||
ensure_field_index(type_info_declaration_type, "is_pub", 1);
|
||||
ensure_field_index(type_info_declaration_type, "data", 2);
|
||||
|
||||
if (!resolve_types) {
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, type_info_declaration_type,
|
||||
false, false, PtrLenUnknown, 0, 0, 0, false);
|
||||
|
||||
out_val->special = ConstValSpecialLazy;
|
||||
out_val->type = get_slice_type(ira->codegen, ptr_type);
|
||||
|
||||
LazyValueTypeInfoDecls *lazy_type_info_decls = heap::c_allocator.create<LazyValueTypeInfoDecls>();
|
||||
lazy_type_info_decls->ira = ira; ira_ref(ira);
|
||||
out_val->data.x_lazy = &lazy_type_info_decls->base;
|
||||
lazy_type_info_decls->base.id = LazyValueIdTypeInfoDecls;
|
||||
|
||||
lazy_type_info_decls->source_instr = source_instr;
|
||||
lazy_type_info_decls->decls_scope = decls_scope;
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type);
|
||||
if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown)))
|
||||
return err;
|
||||
@ -24189,7 +24214,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
||||
// decls: []TypeInfo.Declaration
|
||||
ensure_field_index(result->type, "decls", 3);
|
||||
if ((err = ir_make_type_info_decls(ira, source_instr, fields[3],
|
||||
type_entry->data.enumeration.decls_scope)))
|
||||
type_entry->data.enumeration.decls_scope, false)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
@ -24361,7 +24386,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
||||
// decls: []TypeInfo.Declaration
|
||||
ensure_field_index(result->type, "decls", 3);
|
||||
if ((err = ir_make_type_info_decls(ira, source_instr, fields[3],
|
||||
type_entry->data.unionation.decls_scope)))
|
||||
type_entry->data.unionation.decls_scope, false)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
@ -24453,7 +24478,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
||||
// decls: []TypeInfo.Declaration
|
||||
ensure_field_index(result->type, "decls", 2);
|
||||
if ((err = ir_make_type_info_decls(ira, source_instr, fields[2],
|
||||
type_entry->data.structure.decls_scope)))
|
||||
type_entry->data.structure.decls_scope, false)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
@ -30391,6 +30416,18 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
|
||||
switch (val->data.x_lazy->id) {
|
||||
case LazyValueIdInvalid:
|
||||
zig_unreachable();
|
||||
case LazyValueIdTypeInfoDecls: {
|
||||
LazyValueTypeInfoDecls *type_info_decls = reinterpret_cast<LazyValueTypeInfoDecls *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = type_info_decls->ira;
|
||||
|
||||
if ((err = ir_make_type_info_decls(ira, type_info_decls->source_instr, val, type_info_decls->decls_scope, true)))
|
||||
{
|
||||
return err;
|
||||
};
|
||||
|
||||
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdAlignOf: {
|
||||
LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = lazy_align_of->ira;
|
||||
|
||||
@ -30,10 +30,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'",
|
||||
});
|
||||
|
||||
cases.addTest("dependency loop in top-level decl with @TypeInfo",
|
||||
\\export const foo = @typeInfo(@This());
|
||||
cases.addTest("dependency loop in top-level decl with @TypeInfo when accessing the decls",
|
||||
\\export const foo = @typeInfo(@This()).Struct.decls;
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:1:20: error: dependency loop detected",
|
||||
"tmp.zig:1:45: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("function call assigned to incorrect type",
|
||||
@ -1346,24 +1347,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:8:28: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("@typeInfo causing depend on itself compile error",
|
||||
\\const start = struct {
|
||||
\\ fn crash() bug() {
|
||||
\\ return bug;
|
||||
\\ }
|
||||
\\};
|
||||
\\fn bug() void {
|
||||
\\ _ = @typeInfo(start).Struct;
|
||||
\\}
|
||||
\\export fn entry() void {
|
||||
\\ var boom = start.crash();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:7:9: error: dependency loop detected",
|
||||
"tmp.zig:2:19: note: referenced here",
|
||||
"tmp.zig:10:21: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("enum field value references enum",
|
||||
\\pub const Foo = extern enum {
|
||||
\\ A = Foo.B,
|
||||
|
||||
@ -375,3 +375,14 @@ test "sentinel of opaque pointer type" {
|
||||
const c_void_info = @typeInfo(*c_void);
|
||||
expect(c_void_info.Pointer.sentinel == null);
|
||||
}
|
||||
|
||||
test "@typeInfo does not force declarations into existence" {
|
||||
const S = struct {
|
||||
x: i32,
|
||||
|
||||
fn doNotReferenceMe() void {
|
||||
@compileError("test failed");
|
||||
}
|
||||
};
|
||||
comptime expect(@typeInfo(S).Struct.fields.len == 1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user