| author | |
| committer | |
| log | 662996e4a8826f62f76bdafdb7ccbb1d52210c96 |
| tree | c0397d9b09c6dd66bd828c4162b8439bc03ec304 |
| parent | e8a84927ab989d3c8fb6668dd242ada0a8f99585 |
| parent | d056c7732b87633ace03dd15668a88eac76b62a5 |
| signature |
Closes #4435
Closes #3893
Closes #25846 files changed, 75 insertions(+), 26 deletions(-)
lib/std/meta.zig+4-2| ... | @@ -437,7 +437,7 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { | ... | @@ -437,7 +437,7 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { |
| 437 | }, | 437 | }, |
| 438 | .Pointer => |info| { | 438 | .Pointer => |info| { |
| 439 | return switch (info.size) { | 439 | return switch (info.size) { |
| 440 | .One, .Many, .C, => a == b, | 440 | .One, .Many, .C => a == b, |
| 441 | .Slice => a.ptr == b.ptr and a.len == b.len, | 441 | .Slice => a.ptr == b.ptr and a.len == b.len, |
| 442 | }; | 442 | }; |
| 443 | }, | 443 | }, |
| ... | @@ -559,7 +559,9 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int { | ... | @@ -559,7 +559,9 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int { |
| 559 | /// Given a type, reference all the declarations inside, so that the semantic analyzer sees them. | 559 | /// Given a type, reference all the declarations inside, so that the semantic analyzer sees them. |
| 560 | pub fn refAllDecls(comptime T: type) void { | 560 | pub fn refAllDecls(comptime T: type) void { |
| 561 | if (!builtin.is_test) return; | 561 | if (!builtin.is_test) return; |
| 562 | _ = declarations(T); | 562 | inline for (declarations(T)) |decl| { |
| 563 | _ = decl; | ||
| 564 | } | ||
| 563 | } | 565 | } |
| 564 | 566 | ||
| 565 | /// Returns a slice of pointers to public declarations of a namespace. | 567 | /// Returns a slice of pointers to public declarations of a namespace. |
src/all_types.hpp+10| ... | @@ -369,12 +369,22 @@ enum LazyValueId { | ... | @@ -369,12 +369,22 @@ enum LazyValueId { |
| 369 | LazyValueIdFnType, | 369 | LazyValueIdFnType, |
| 370 | LazyValueIdErrUnionType, | 370 | LazyValueIdErrUnionType, |
| 371 | LazyValueIdArrayType, | 371 | LazyValueIdArrayType, |
| 372 | LazyValueIdTypeInfoDecls, | ||
| 372 | }; | 373 | }; |
| 373 | 374 | ||
| 374 | struct LazyValue { | 375 | struct LazyValue { |
| 375 | LazyValueId id; | 376 | LazyValueId id; |
| 376 | }; | 377 | }; |
| 377 | 378 | ||
| 379 | struct LazyValueTypeInfoDecls { | ||
| 380 | LazyValue base; | ||
| 381 | |||
| 382 | IrAnalyze *ira; | ||
| 383 | |||
| 384 | ScopeDecls *decls_scope; | ||
| 385 | IrInst *source_instr; | ||
| 386 | }; | ||
| 387 | |||
| 378 | struct LazyValueAlignOf { | 388 | struct LazyValueAlignOf { |
| 379 | LazyValue base; | 389 | LazyValue base; |
| 380 | 390 |
src/analyze.cpp+6| ... | @@ -1150,6 +1150,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent | ... | @@ -1150,6 +1150,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent |
| 1150 | case LazyValueIdInvalid: | 1150 | case LazyValueIdInvalid: |
| 1151 | case LazyValueIdAlignOf: | 1151 | case LazyValueIdAlignOf: |
| 1152 | case LazyValueIdSizeOf: | 1152 | case LazyValueIdSizeOf: |
| 1153 | case LazyValueIdTypeInfoDecls: | ||
| 1153 | zig_unreachable(); | 1154 | zig_unreachable(); |
| 1154 | case LazyValueIdPtrType: { | 1155 | case LazyValueIdPtrType: { |
| 1155 | LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy); | 1156 | 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 | ... | @@ -1209,6 +1210,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o |
| 1209 | case LazyValueIdInvalid: | 1210 | case LazyValueIdInvalid: |
| 1210 | case LazyValueIdAlignOf: | 1211 | case LazyValueIdAlignOf: |
| 1211 | case LazyValueIdSizeOf: | 1212 | case LazyValueIdSizeOf: |
| 1213 | case LazyValueIdTypeInfoDecls: | ||
| 1212 | zig_unreachable(); | 1214 | zig_unreachable(); |
| 1213 | case LazyValueIdSliceType: | 1215 | case LazyValueIdSliceType: |
| 1214 | case LazyValueIdPtrType: | 1216 | case LazyValueIdPtrType: |
| ... | @@ -1230,6 +1232,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type | ... | @@ -1230,6 +1232,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type |
| 1230 | case LazyValueIdInvalid: | 1232 | case LazyValueIdInvalid: |
| 1231 | case LazyValueIdAlignOf: | 1233 | case LazyValueIdAlignOf: |
| 1232 | case LazyValueIdSizeOf: | 1234 | case LazyValueIdSizeOf: |
| 1235 | case LazyValueIdTypeInfoDecls: | ||
| 1233 | zig_unreachable(); | 1236 | zig_unreachable(); |
| 1234 | case LazyValueIdSliceType: { | 1237 | case LazyValueIdSliceType: { |
| 1235 | LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy); | 1238 | LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy); |
| ... | @@ -1303,6 +1306,7 @@ start_over: | ... | @@ -1303,6 +1306,7 @@ start_over: |
| 1303 | case LazyValueIdInvalid: | 1306 | case LazyValueIdInvalid: |
| 1304 | case LazyValueIdAlignOf: | 1307 | case LazyValueIdAlignOf: |
| 1305 | case LazyValueIdSizeOf: | 1308 | case LazyValueIdSizeOf: |
| 1309 | case LazyValueIdTypeInfoDecls: | ||
| 1306 | zig_unreachable(); | 1310 | zig_unreachable(); |
| 1307 | case LazyValueIdSliceType: { | 1311 | case LazyValueIdSliceType: { |
| 1308 | LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy); | 1312 | 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 | ... | @@ -1370,6 +1374,7 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ |
| 1370 | case LazyValueIdInvalid: | 1374 | case LazyValueIdInvalid: |
| 1371 | case LazyValueIdAlignOf: | 1375 | case LazyValueIdAlignOf: |
| 1372 | case LazyValueIdSizeOf: | 1376 | case LazyValueIdSizeOf: |
| 1377 | case LazyValueIdTypeInfoDecls: | ||
| 1373 | zig_unreachable(); | 1378 | zig_unreachable(); |
| 1374 | case LazyValueIdSliceType: | 1379 | case LazyValueIdSliceType: |
| 1375 | case LazyValueIdPtrType: | 1380 | case LazyValueIdPtrType: |
| ... | @@ -1412,6 +1417,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV | ... | @@ -1412,6 +1417,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV |
| 1412 | case LazyValueIdInvalid: | 1417 | case LazyValueIdInvalid: |
| 1413 | case LazyValueIdAlignOf: | 1418 | case LazyValueIdAlignOf: |
| 1414 | case LazyValueIdSizeOf: | 1419 | case LazyValueIdSizeOf: |
| 1420 | case LazyValueIdTypeInfoDecls: | ||
| 1415 | zig_unreachable(); | 1421 | zig_unreachable(); |
| 1416 | case LazyValueIdSliceType: // it has the len field | 1422 | case LazyValueIdSliceType: // it has the len field |
| 1417 | case LazyValueIdOptType: // it has the optional bit | 1423 | case LazyValueIdOptType: // it has the optional bit |
src/ir.cpp+41-4| ... | @@ -21221,6 +21221,13 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins | ... | @@ -21221,6 +21221,13 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins |
| 21221 | return ira->codegen->invalid_inst_gen; | 21221 | return ira->codegen->invalid_inst_gen; |
| 21222 | if (type_is_invalid(struct_val->type)) | 21222 | if (type_is_invalid(struct_val->type)) |
| 21223 | return ira->codegen->invalid_inst_gen; | 21223 | return ira->codegen->invalid_inst_gen; |
| 21224 | |||
| 21225 | // This to allow lazy values to be resolved. | ||
| 21226 | if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, | ||
| 21227 | source_instr->source_node, struct_val, UndefOk))) | ||
| 21228 | { | ||
| 21229 | return ira->codegen->invalid_inst_gen; | ||
| 21230 | } | ||
| 21224 | if (initializing && struct_val->special == ConstValSpecialUndef) { | 21231 | if (initializing && struct_val->special == ConstValSpecialUndef) { |
| 21225 | struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count); | 21232 | struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count); |
| 21226 | struct_val->special = ConstValSpecialStatic; | 21233 | struct_val->special = ConstValSpecialStatic; |
| ... | @@ -23626,7 +23633,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig | ... | @@ -23626,7 +23633,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig |
| 23626 | } | 23633 | } |
| 23627 | 23634 | ||
| 23628 | static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val, | 23635 | static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val, |
| 23629 | ScopeDecls *decls_scope) | 23636 | ScopeDecls *decls_scope, bool resolve_types) |
| 23630 | { | 23637 | { |
| 23631 | Error err; | 23638 | Error err; |
| 23632 | ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr); | 23639 | 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 | ... | @@ -23637,6 +23644,24 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa |
| 23637 | ensure_field_index(type_info_declaration_type, "is_pub", 1); | 23644 | ensure_field_index(type_info_declaration_type, "is_pub", 1); |
| 23638 | ensure_field_index(type_info_declaration_type, "data", 2); | 23645 | ensure_field_index(type_info_declaration_type, "data", 2); |
| 23639 | 23646 | ||
| 23647 | if (!resolve_types) { | ||
| 23648 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, type_info_declaration_type, | ||
| 23649 | false, false, PtrLenUnknown, 0, 0, 0, false); | ||
| 23650 | |||
| 23651 | out_val->special = ConstValSpecialLazy; | ||
| 23652 | out_val->type = get_slice_type(ira->codegen, ptr_type); | ||
| 23653 | |||
| 23654 | LazyValueTypeInfoDecls *lazy_type_info_decls = heap::c_allocator.create<LazyValueTypeInfoDecls>(); | ||
| 23655 | lazy_type_info_decls->ira = ira; ira_ref(ira); | ||
| 23656 | out_val->data.x_lazy = &lazy_type_info_decls->base; | ||
| 23657 | lazy_type_info_decls->base.id = LazyValueIdTypeInfoDecls; | ||
| 23658 | |||
| 23659 | lazy_type_info_decls->source_instr = source_instr; | ||
| 23660 | lazy_type_info_decls->decls_scope = decls_scope; | ||
| 23661 | |||
| 23662 | return ErrorNone; | ||
| 23663 | } | ||
| 23664 | |||
| 23640 | ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type); | 23665 | ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type); |
| 23641 | if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown))) | 23666 | if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown))) |
| 23642 | return err; | 23667 | return err; |
| ... | @@ -24189,7 +24214,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy | ... | @@ -24189,7 +24214,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 24189 | // decls: []TypeInfo.Declaration | 24214 | // decls: []TypeInfo.Declaration |
| 24190 | ensure_field_index(result->type, "decls", 3); | 24215 | ensure_field_index(result->type, "decls", 3); |
| 24191 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], | 24216 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], |
| 24192 | type_entry->data.enumeration.decls_scope))) | 24217 | type_entry->data.enumeration.decls_scope, false))) |
| 24193 | { | 24218 | { |
| 24194 | return err; | 24219 | return err; |
| 24195 | } | 24220 | } |
| ... | @@ -24361,7 +24386,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy | ... | @@ -24361,7 +24386,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 24361 | // decls: []TypeInfo.Declaration | 24386 | // decls: []TypeInfo.Declaration |
| 24362 | ensure_field_index(result->type, "decls", 3); | 24387 | ensure_field_index(result->type, "decls", 3); |
| 24363 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], | 24388 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], |
| 24364 | type_entry->data.unionation.decls_scope))) | 24389 | type_entry->data.unionation.decls_scope, false))) |
| 24365 | { | 24390 | { |
| 24366 | return err; | 24391 | return err; |
| 24367 | } | 24392 | } |
| ... | @@ -24453,7 +24478,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy | ... | @@ -24453,7 +24478,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 24453 | // decls: []TypeInfo.Declaration | 24478 | // decls: []TypeInfo.Declaration |
| 24454 | ensure_field_index(result->type, "decls", 2); | 24479 | ensure_field_index(result->type, "decls", 2); |
| 24455 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[2], | 24480 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[2], |
| 24456 | type_entry->data.structure.decls_scope))) | 24481 | type_entry->data.structure.decls_scope, false))) |
| 24457 | { | 24482 | { |
| 24458 | return err; | 24483 | return err; |
| 24459 | } | 24484 | } |
| ... | @@ -30391,6 +30416,18 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { | ... | @@ -30391,6 +30416,18 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { |
| 30391 | switch (val->data.x_lazy->id) { | 30416 | switch (val->data.x_lazy->id) { |
| 30392 | case LazyValueIdInvalid: | 30417 | case LazyValueIdInvalid: |
| 30393 | zig_unreachable(); | 30418 | zig_unreachable(); |
| 30419 | case LazyValueIdTypeInfoDecls: { | ||
| 30420 | LazyValueTypeInfoDecls *type_info_decls = reinterpret_cast<LazyValueTypeInfoDecls *>(val->data.x_lazy); | ||
| 30421 | IrAnalyze *ira = type_info_decls->ira; | ||
| 30422 | |||
| 30423 | if ((err = ir_make_type_info_decls(ira, type_info_decls->source_instr, val, type_info_decls->decls_scope, true))) | ||
| 30424 | { | ||
| 30425 | return err; | ||
| 30426 | }; | ||
| 30427 | |||
| 30428 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. | ||
| 30429 | return ErrorNone; | ||
| 30430 | } | ||
| 30394 | case LazyValueIdAlignOf: { | 30431 | case LazyValueIdAlignOf: { |
| 30395 | LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy); | 30432 | LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy); |
| 30396 | IrAnalyze *ira = lazy_align_of->ira; | 30433 | IrAnalyze *ira = lazy_align_of->ira; |
test/compile_errors.zig+3-20| ... | @@ -30,10 +30,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -30,10 +30,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 30 | "tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'", | 30 | "tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'", |
| 31 | }); | 31 | }); |
| 32 | 32 | ||
| 33 | cases.addTest("dependency loop in top-level decl with @TypeInfo", | 33 | cases.addTest("dependency loop in top-level decl with @TypeInfo when accessing the decls", |
| 34 | \\export const foo = @typeInfo(@This()); | 34 | \\export const foo = @typeInfo(@This()).Struct.decls; |
| 35 | , &[_][]const u8{ | 35 | , &[_][]const u8{ |
| 36 | "tmp.zig:1:20: error: dependency loop detected", | 36 | "tmp.zig:1:20: error: dependency loop detected", |
| 37 | "tmp.zig:1:45: note: referenced here", | ||
| 37 | }); | 38 | }); |
| 38 | 39 | ||
| 39 | cases.add("function call assigned to incorrect type", | 40 | cases.add("function call assigned to incorrect type", |
| ... | @@ -1346,24 +1347,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -1346,24 +1347,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1346 | "tmp.zig:8:28: note: referenced here", | 1347 | "tmp.zig:8:28: note: referenced here", |
| 1347 | }); | 1348 | }); |
| 1348 | 1349 | ||
| 1349 | cases.add("@typeInfo causing depend on itself compile error", | ||
| 1350 | \\const start = struct { | ||
| 1351 | \\ fn crash() bug() { | ||
| 1352 | \\ return bug; | ||
| 1353 | \\ } | ||
| 1354 | \\}; | ||
| 1355 | \\fn bug() void { | ||
| 1356 | \\ _ = @typeInfo(start).Struct; | ||
| 1357 | \\} | ||
| 1358 | \\export fn entry() void { | ||
| 1359 | \\ var boom = start.crash(); | ||
| 1360 | \\} | ||
| 1361 | , &[_][]const u8{ | ||
| 1362 | "tmp.zig:7:9: error: dependency loop detected", | ||
| 1363 | "tmp.zig:2:19: note: referenced here", | ||
| 1364 | "tmp.zig:10:21: note: referenced here", | ||
| 1365 | }); | ||
| 1366 | |||
| 1367 | cases.add("enum field value references enum", | 1350 | cases.add("enum field value references enum", |
| 1368 | \\pub const Foo = extern enum { | 1351 | \\pub const Foo = extern enum { |
| 1369 | \\ A = Foo.B, | 1352 | \\ A = Foo.B, |
test/stage1/behavior/type_info.zig+11| ... | @@ -375,3 +375,14 @@ test "sentinel of opaque pointer type" { | ... | @@ -375,3 +375,14 @@ test "sentinel of opaque pointer type" { |
| 375 | const c_void_info = @typeInfo(*c_void); | 375 | const c_void_info = @typeInfo(*c_void); |
| 376 | expect(c_void_info.Pointer.sentinel == null); | 376 | expect(c_void_info.Pointer.sentinel == null); |
| 377 | } | 377 | } |
| 378 | |||
| 379 | test "@typeInfo does not force declarations into existence" { | ||
| 380 | const S = struct { | ||
| 381 | x: i32, | ||
| 382 | |||
| 383 | fn doNotReferenceMe() void { | ||
| 384 | @compileError("test failed"); | ||
| 385 | } | ||
| 386 | }; | ||
| 387 | comptime expect(@typeInfo(S).Struct.fields.len == 1); | ||
| 388 | } |