zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9 (tree)
parent 77a5f888be664f9ef09e2c93f52338448e992e00
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Wed,  4 Sep 2019 11:12:24 -0400

Merge branch 'marler8997-typeBuiltin'

Diffstat:
Mdoc/docgen.zig | 26++++++++++++++++++++++++--
Mdoc/langref.html.in | 56+++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/all_types.hpp | 16++++++++++++++++
Msrc/codegen.cpp | 35+++++++++++++++++++++--------------
Msrc/ir.cpp | 187++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/ir_print.cpp | 11+++++++++++
Mtest/compile_errors.zig | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/stage1/behavior.zig | 1+
Atest/stage1/behavior/type.zig | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 468 insertions(+), 23 deletions(-)

diff --git a/doc/docgen.zig b/doc/docgen.zig @@ -321,6 +321,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { var header_stack_size: usize = 0; var last_action = Action.Open; + var last_columns: ?u8 = null; var toc_buf = try std.Buffer.initSize(allocator, 0); defer toc_buf.deinit(); @@ -361,7 +362,23 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { _ = try eatToken(tokenizer, Token.Id.Separator); const content_token = try eatToken(tokenizer, Token.Id.TagContent); const content = tokenizer.buffer[content_token.start..content_token.end]; - _ = try eatToken(tokenizer, Token.Id.BracketClose); + var columns: ?u8 = null; + while (true) { + const bracket_tok = tokenizer.next(); + switch (bracket_tok.id) { + .BracketClose => break, + .Separator => continue, + .TagContent => { + const param = tokenizer.buffer[bracket_tok.start..bracket_tok.end]; + if (mem.eql(u8, param, "3col")) { + columns = 3; + } else { + return parseError(tokenizer, bracket_tok, "unrecognized header_open param: {}", param); + } + }, + else => return parseError(tokenizer, bracket_tok, "invalid header_open token"), + } + } header_stack_size += 1; @@ -381,10 +398,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { if (last_action == Action.Open) { try toc.writeByte('\n'); try toc.writeByteNTimes(' ', header_stack_size * 4); - try toc.write("<ul>\n"); + if (last_columns) |n| { + try toc.print("<ul style=\"columns: {}\">\n", n); + } else { + try toc.write("<ul>\n"); + } } else { last_action = Action.Open; } + last_columns = columns; try toc.writeByteNTimes(' ', 4 + header_stack_size * 4); try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", urlized, urlized, content); } else if (mem.eql(u8, tag_name, "header_close")) { diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -6323,7 +6323,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 { {#header_close#} {#header_close#} - {#header_open|Builtin Functions#} + {#header_open|Builtin Functions|3col#} <p> Builtin functions are provided by the compiler and are prefixed with <code>@</code>. The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known @@ -7232,6 +7232,9 @@ fn add(a: i32, b: i32) i32 { return a + b; } This function returns an integer type with the given signness and bit count. The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}. </p> + <p> + Deprecated. Use {#link|@Type#}. + </p> {#header_close#} {#header_open|@memberCount#} @@ -7871,6 +7874,57 @@ test "integer truncation" { </p> {#header_close#} + {#header_open|@Type#} + <pre>{#syntax#}@Type(comptime info: @import("builtin").TypeInfo) type{#endsyntax#}</pre> + <p> + This function is the inverse of {#link|@typeInfo#}. It reifies type information + into a {#syntax#}type{#endsyntax#}. + </p> + <p> + It is available for the following types: + </p> + <ul> + <li>{#syntax#}type{#endsyntax#}</li> + <li>{#syntax#}noreturn{#endsyntax#}</li> + <li>{#syntax#}void{#endsyntax#}</li> + <li>{#syntax#}bool{#endsyntax#}</li> + <li>{#link|Integers#}</li> - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}. + <li>{#link|Floats#}</li> + <li>{#link|Pointers#}</li> + <li>{#syntax#}comptime_int{#endsyntax#}</li> + <li>{#syntax#}comptime_float{#endsyntax#}</li> + <li>{#syntax#}@typeOf(undefined){#endsyntax#}</li> + <li>{#syntax#}@typeOf(null){#endsyntax#}</li> + </ul> + <p> + For these types it is a + <a href="https://github.com/ziglang/zig/issues/2907">TODO in the compiler to implement</a>: + </p> + <ul> + <li>Array</li> + <li>Optional</li> + <li>ErrorUnion</li> + <li>ErrorSet</li> + <li>Enum</li> + <li>Opaque</li> + <li>FnFrame</li> + <li>AnyFrame</li> + <li>Vector</li> + <li>EnumLiteral</li> + </ul> + <p> + For these types, {#syntax#}@Type{#endsyntax#} is not available. + <a href="https://github.com/ziglang/zig/issues/383">There is an open proposal to allow unions and structs</a>. + </p> + <ul> + <li>{#link|union#}</li> + <li>{#link|Functions#}</li> + <li>BoundFn</li> + <li>ArgTuple</li> + <li>{#link|struct#}</li> + </ul> + {#header_close#} + {#header_open|@typeId#} <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> <p> diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -54,6 +54,14 @@ enum PtrLen { PtrLenC, }; +// This one corresponds to the builtin.zig enum. +enum BuiltinPtrSize { + BuiltinPtrSizeOne, + BuiltinPtrSizeMany, + BuiltinPtrSizeSlice, + BuiltinPtrSizeC, +}; + enum UndefAllowed { UndefOk, UndefBad, @@ -1534,6 +1542,7 @@ enum BuiltinFnId { BuiltinFnIdMemberName, BuiltinFnIdField, BuiltinFnIdTypeInfo, + BuiltinFnIdType, BuiltinFnIdHasField, BuiltinFnIdTypeof, BuiltinFnIdAddWithOverflow, @@ -2436,6 +2445,7 @@ enum IrInstructionId { IrInstructionIdByteOffsetOf, IrInstructionIdBitOffsetOf, IrInstructionIdTypeInfo, + IrInstructionIdType, IrInstructionIdHasField, IrInstructionIdTypeId, IrInstructionIdSetEvalBranchQuota, @@ -3472,6 +3482,12 @@ struct IrInstructionTypeInfo { IrInstruction *type_value; }; +struct IrInstructionType { + IrInstruction base; + + IrInstruction *type_info; +}; + struct IrInstructionHasField { IrInstruction base; diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -5770,6 +5770,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdByteOffsetOf: case IrInstructionIdBitOffsetOf: case IrInstructionIdTypeInfo: + case IrInstructionIdType: case IrInstructionIdHasField: case IrInstructionIdTypeId: case IrInstructionIdSetEvalBranchQuota: @@ -7597,6 +7598,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); create_builtin_fn(g, BuiltinFnIdField, "field", 2); create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1); + create_builtin_fn(g, BuiltinFnIdType, "Type", 1); create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2); create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); @@ -8159,20 +8161,25 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { " };\n" " };\n" "};\n\n"); - assert(ContainerLayoutAuto == 0); - assert(ContainerLayoutExtern == 1); - assert(ContainerLayoutPacked == 2); - - assert(CallingConventionUnspecified == 0); - assert(CallingConventionC == 1); - assert(CallingConventionCold == 2); - assert(CallingConventionNaked == 3); - assert(CallingConventionStdcall == 4); - assert(CallingConventionAsync == 5); - - assert(FnInlineAuto == 0); - assert(FnInlineAlways == 1); - assert(FnInlineNever == 2); + static_assert(ContainerLayoutAuto == 0, ""); + static_assert(ContainerLayoutExtern == 1, ""); + static_assert(ContainerLayoutPacked == 2, ""); + + static_assert(CallingConventionUnspecified == 0, ""); + static_assert(CallingConventionC == 1, ""); + static_assert(CallingConventionCold == 2, ""); + static_assert(CallingConventionNaked == 3, ""); + static_assert(CallingConventionStdcall == 4, ""); + static_assert(CallingConventionAsync == 5, ""); + + static_assert(FnInlineAuto == 0, ""); + static_assert(FnInlineAlways == 1, ""); + static_assert(FnInlineNever == 2, ""); + + static_assert(BuiltinPtrSizeOne == 0, ""); + static_assert(BuiltinPtrSizeMany == 1, ""); + static_assert(BuiltinPtrSizeSlice == 2, ""); + static_assert(BuiltinPtrSizeC == 3, ""); } { buf_appendf(contents, diff --git a/src/ir.cpp b/src/ir.cpp @@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) { return IrInstructionIdTypeInfo; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) { + return IrInstructionIdType; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) { return IrInstructionIdHasField; } @@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } +static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_info) { + IrInstructionType *instruction = ir_build_instruction<IrInstructionType>(irb, scope, source_node); + instruction->type_info = type_info; + + ir_ref_instruction(type_info, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { @@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, type_info, lval, result_loc); } + case BuiltinFnIdType: + { + AstNode *arg_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_instruction) + return arg; + + IrInstruction *type = ir_build_type(irb, scope, node, arg); + return ir_lval_wrap(irb, scope, type, lval, result_loc); + } case BuiltinFnIdBreakpoint: return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); case BuiltinFnIdReturnAddress: @@ -20092,14 +20115,27 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr return ErrorNone; } -static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { +static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) { switch (ptr_len) { case PtrLenSingle: - return 0; + return BuiltinPtrSizeOne; case PtrLenUnknown: - return 1; + return BuiltinPtrSizeMany; case PtrLenC: - return 3; + return BuiltinPtrSizeC; + } + zig_unreachable(); +} + +static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) { + switch (size_enum_index) { + case BuiltinPtrSizeOne: + return PtrLenSingle; + case BuiltinPtrSizeMany: + case BuiltinPtrSizeSlice: + return PtrLenUnknown; + case BuiltinPtrSizeC: + return PtrLenC; } zig_unreachable(); } @@ -20107,10 +20143,10 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { Error err; ZigType *attrs_type; - uint32_t size_enum_index; + BuiltinPtrSize size_enum_index; if (is_slice(ptr_type_entry)) { attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; - size_enum_index = 2; + size_enum_index = BuiltinPtrSizeSlice; } else if (ptr_type_entry->id == ZigTypeIdPointer) { attrs_type = ptr_type_entry; size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len); @@ -20789,6 +20825,142 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, return result; } +static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ensure_field_index(struct_value->type, name, field_index); + assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic); + return &struct_value->data.x_struct.fields[field_index]; +} + +static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_bool); + return value->data.x_bool; +} + +static BigInt *get_const_field_lit_int(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_num_lit_int); + return &value->data.x_bigint; +} + +static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_type); + return value->data.x_type; +} + +static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) { + switch (tagTypeId) { + case ZigTypeIdInvalid: + zig_unreachable(); + case ZigTypeIdMetaType: + return ira->codegen->builtin_types.entry_type; + case ZigTypeIdVoid: + return ira->codegen->builtin_types.entry_void; + case ZigTypeIdBool: + return ira->codegen->builtin_types.entry_bool; + case ZigTypeIdUnreachable: + return ira->codegen->builtin_types.entry_unreachable; + case ZigTypeIdInt: + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr)); + return get_int_type(ira->codegen, + get_const_field_bool(ira, payload, "is_signed", 0), + bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 1))); + case ZigTypeIdFloat: + { + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr)); + uint32_t bits = bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 0)); + switch (bits) { + case 16: return ira->codegen->builtin_types.entry_f16; + case 32: return ira->codegen->builtin_types.entry_f32; + case 64: return ira->codegen->builtin_types.entry_f64; + case 128: return ira->codegen->builtin_types.entry_f128; + } + ir_add_error(ira, instruction, + buf_sprintf("%d-bit float unsupported", bits)); + return nullptr; + } + case ZigTypeIdPointer: + { + ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr); + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == type_info_pointer_type); + ConstExprValue *size_value = get_const_field(ira, payload, "size", 0); + assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); + BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); + PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index); + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, + get_const_field_meta_type(ira, payload, "child", 4), + get_const_field_bool(ira, payload, "is_const", 1), + get_const_field_bool(ira, payload, "is_volatile", 2), + ptr_len, + bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)), + 0, // bit_offset_in_host + 0, // host_int_bytes + get_const_field_bool(ira, payload, "is_allowzero", 5) + ); + if (size_enum_index != 2) + return ptr_type; + return get_slice_type(ira->codegen, ptr_type); + } + case ZigTypeIdComptimeFloat: + return ira->codegen->builtin_types.entry_num_lit_float; + case ZigTypeIdComptimeInt: + return ira->codegen->builtin_types.entry_num_lit_int; + case ZigTypeIdUndefined: + return ira->codegen->builtin_types.entry_undef; + case ZigTypeIdNull: + return ira->codegen->builtin_types.entry_null; + case ZigTypeIdArray: + case ZigTypeIdOptional: + case ZigTypeIdErrorUnion: + case ZigTypeIdErrorSet: + case ZigTypeIdEnum: + case ZigTypeIdOpaque: + case ZigTypeIdFnFrame: + case ZigTypeIdAnyFrame: + case ZigTypeIdVector: + case ZigTypeIdEnumLiteral: + ir_add_error(ira, instruction, buf_sprintf( + "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); + return nullptr; + case ZigTypeIdUnion: + case ZigTypeIdFn: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + case ZigTypeIdStruct: + ir_add_error(ira, instruction, buf_sprintf( + "@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId))); + return nullptr; + } + zig_unreachable(); +} + +static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) { + IrInstruction *type_info_ir = instruction->type_info->child; + if (type_is_invalid(type_info_ir->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr)); + if (type_is_invalid(casted_ir->value.type)) + return ira->codegen->invalid_instruction; + + ConstExprValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad); + if (!type_info_value) + return ira->codegen->invalid_instruction; + ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag)); + ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload); + if (!type) + return ira->codegen->invalid_instruction; + return ir_const_type(ira, &instruction->base, type); +} + static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstructionTypeId *instruction) { @@ -25295,6 +25467,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction); case IrInstructionIdTypeInfo: return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); + case IrInstructionIdType: + return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction); case IrInstructionIdHasField: return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction); case IrInstructionIdTypeId: @@ -25598,6 +25772,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdByteOffsetOf: case IrInstructionIdBitOffsetOf: case IrInstructionIdTypeInfo: + case IrInstructionIdType: case IrInstructionIdHasField: case IrInstructionIdTypeId: case IrInstructionIdAlignCast: diff --git a/src/ir_print.cpp b/src/ir_print.cpp @@ -280,6 +280,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) { return "BitOffsetOf"; case IrInstructionIdTypeInfo: return "TypeInfo"; + case IrInstructionIdType: + return "Type"; case IrInstructionIdHasField: return "HasField"; case IrInstructionIdTypeId: @@ -1627,6 +1629,12 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) fprintf(irp->f, ")"); } +static void ir_print_type(IrPrint *irp, IrInstructionType *instruction) { + fprintf(irp->f, "@Type("); + ir_print_other_instruction(irp, instruction->type_info); + fprintf(irp->f, ")"); +} + static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) { fprintf(irp->f, "@hasField("); ir_print_other_instruction(irp, instruction->container_type); @@ -2258,6 +2266,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool case IrInstructionIdTypeInfo: ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction); break; + case IrInstructionIdType: + ir_print_type(irp, (IrInstructionType *)instruction); + break; case IrInstructionIdHasField: ir_print_has_field(irp, (IrInstructionHasField *)instruction); break; diff --git a/test/compile_errors.zig b/test/compile_errors.zig @@ -3,6 +3,58 @@ const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( + "attempt to create 17 bit float type", + \\const builtin = @import("builtin"); + \\comptime { + \\ _ = @Type(builtin.TypeInfo { .Float = builtin.TypeInfo.Float { .bits = 17 } }); + \\} + , + "tmp.zig:3:32: error: 17-bit float unsupported", + ); + + cases.add( + "wrong type for @Type", + \\export fn entry() void { + \\ _ = @Type(0); + \\} + , + "tmp.zig:2:15: error: expected type 'builtin.TypeInfo', found 'comptime_int'", + ); + + cases.add( + "@Type with non-constant expression", + \\const builtin = @import("builtin"); + \\var globalTypeInfo : builtin.TypeInfo = undefined; + \\export fn entry() void { + \\ _ = @Type(globalTypeInfo); + \\} + , + "tmp.zig:4:15: error: unable to evaluate constant expression", + ); + + cases.add( + "@Type with TypeInfo.Int", + \\const builtin = @import("builtin"); + \\export fn entry() void { + \\ _ = @Type(builtin.TypeInfo.Int { + \\ .is_signed = true, + \\ .bits = 8, + \\ }); + \\} + , + "tmp.zig:3:36: error: expected type 'builtin.TypeInfo', found 'builtin.Int'", + ); + + cases.add( + "Struct unavailable for @Type", + \\export fn entry() void { + \\ _ = @Type(@typeInfo(struct { })); + \\} + , + "tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'", + ); + + cases.add( "wrong type for result ptr to @asyncCall", \\export fn entry() void { \\ _ = async amain(); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig @@ -93,6 +93,7 @@ comptime { _ = @import("behavior/this.zig"); _ = @import("behavior/truncate.zig"); _ = @import("behavior/try.zig"); + _ = @import("behavior/type.zig"); _ = @import("behavior/type_info.zig"); _ = @import("behavior/typename.zig"); _ = @import("behavior/undefined.zig"); diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig @@ -0,0 +1,107 @@ +const builtin = @import("builtin"); +const TypeInfo = builtin.TypeInfo; + +const std = @import("std"); +const testing = std.testing; + +fn testTypes(comptime types: []const type) void { + inline for (types) |testType| { + testing.expect(testType == @Type(@typeInfo(testType))); + } +} + +test "Type.MetaType" { + testing.expect(type == @Type(TypeInfo { .Type = undefined })); + testTypes([_]type {type}); +} + +test "Type.Void" { + testing.expect(void == @Type(TypeInfo { .Void = undefined })); + testTypes([_]type {void}); +} + +test "Type.Bool" { + testing.expect(bool == @Type(TypeInfo { .Bool = undefined })); + testTypes([_]type {bool}); +} + +test "Type.NoReturn" { + testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined })); + testTypes([_]type {noreturn}); +} + +test "Type.Int" { + testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } })); + testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } })); + testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } })); + testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } })); + testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } })); + testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } })); + testTypes([_]type {u8,u32,i64}); +} + +test "Type.Float" { + testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } })); + testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } })); + testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } })); + testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } })); + testTypes([_]type {f16, f32, f64, f128}); +} + +test "Type.Pointer" { + testTypes([_]type { + // One Value Pointer Types + *u8, *const u8, + *volatile u8, *const volatile u8, + *align(4) u8, *const align(4) u8, + *volatile align(4) u8, *const volatile align(4) u8, + *align(8) u8, *const align(8) u8, + *volatile align(8) u8, *const volatile align(8) u8, + *allowzero u8, *const allowzero u8, + *volatile allowzero u8, *const volatile allowzero u8, + *align(4) allowzero u8, *const align(4) allowzero u8, + *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8, + // Many Values Pointer Types + [*]u8, [*]const u8, + [*]volatile u8, [*]const volatile u8, + [*]align(4) u8, [*]const align(4) u8, + [*]volatile align(4) u8, [*]const volatile align(4) u8, + [*]align(8) u8, [*]const align(8) u8, + [*]volatile align(8) u8, [*]const volatile align(8) u8, + [*]allowzero u8, [*]const allowzero u8, + [*]volatile allowzero u8, [*]const volatile allowzero u8, + [*]align(4) allowzero u8, [*]const align(4) allowzero u8, + [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8, + // Slice Types + []u8, []const u8, + []volatile u8, []const volatile u8, + []align(4) u8, []const align(4) u8, + []volatile align(4) u8, []const volatile align(4) u8, + []align(8) u8, []const align(8) u8, + []volatile align(8) u8, []const volatile align(8) u8, + []allowzero u8, []const allowzero u8, + []volatile allowzero u8, []const volatile allowzero u8, + []align(4) allowzero u8, []const align(4) allowzero u8, + []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8, + // C Pointer Types + [*c]u8, [*c]const u8, + [*c]volatile u8, [*c]const volatile u8, + [*c]align(4) u8, [*c]const align(4) u8, + [*c]volatile align(4) u8, [*c]const volatile align(4) u8, + [*c]align(8) u8, [*c]const align(8) u8, + [*c]volatile align(8) u8, [*c]const volatile align(8) u8, + }); +} + +test "Type.ComptimeFloat" { + testTypes([_]type {comptime_float}); +} +test "Type.ComptimeInt" { + testTypes([_]type {comptime_int}); +} +test "Type.Undefined" { + testTypes([_]type {@typeOf(undefined)}); +} +test "Type.Null" { + testTypes([_]type {@typeOf(null)}); +}