aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-20 15:23:55 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-20 15:41:57 -0700
commit0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4 (patch)
treec3de2205e0bb525d61ee78800c118b13efbf1029 /src/type.zig
parent2f1abd919a8465e515875cd08816778df795aabe (diff)
downloadzig-0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4.tar.gz
zig-0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4.zip
stage2: field type expressions support referencing locals
The big change in this commit is making `semaDecl` resolve the fields if the Decl ends up being a struct or union. It needs to do this while the `Sema` is still in scope, because it will have the resolved AIR instructions that the field type expressions possibly reference. We do this after the decl is populated and set to `complete` so that a `Decl` may reference itself. Everything else is fixes and improvements to make the test suite pass again after making this change. * New AIR instruction: `ptr_elem_ptr` - Implemented for LLVM backend * New Type tag: `type_info` which represents `std.builtin.TypeInfo`. It is used by AstGen for the operand type of `@Type`. * ZIR instruction `set_float_mode` uses `coerced_ty` to avoid superfluous `as` instruction on operand. * ZIR instruction `Type` uses `coerced_ty` to properly handle result location type of operand. * Fix two instances of `enum_nonexhaustive` Value Tag not handled properly - it should generally be handled the same as `enum_full`. * Fix struct and union field resolution not copying Type and Value objects into its Decl arena. * Fix enum tag value resolution discarding the ZIR=>AIR instruction map for the child Sema, when they still needed to be accessed. * Fix `zirResolveInferredAlloc` use-after-free in the AIR instructions data array. * Fix `elemPtrArray` not respecting const/mutable attribute of pointer in the result type. * Fix LLVM backend crashing when `updateDeclExports` is called before `updateDecl`/`updateFunc` (which is, according to the API, perfectly legal for the frontend to do). * Fix LLVM backend handling element pointer of pointer-to-array. It needed another index in the GEP otherwise LLVM saw the wrong type. * Fix LLVM test cases not returning 0 from main, causing test failures. Fixes a regression introduced in 6a5094872f10acc629543cc7f10533b438d0283a. * Implement comptime shift-right. * Implement `@Type` for integers and `@TypeInfo` for integers. * Implement union initialization syntax. * Implement `zirFieldType` for unions. * Implement `elemPtrArray` for a runtime-known operand. * Make `zirLog2IntType` support RHS of shift being `comptime_int`. In this case it returns `comptime_int`. The motivating test case for this commit was originally: ```zig test "example" { var l: List(10) = undefined; l.array[1] = 1; } fn List(comptime L: usize) type { var T = u8; return struct { array: [L]T, }; } ``` However I changed it to: ```zig test "example" { var l: List = undefined; l.array[1] = 1; } const List = blk: { const T = [10]u8; break :blk struct { array: T, }; }; ``` Which ended up being a similar, smaller problem. The former test case will require a similar solution in the implementation of comptime function calls - checking if the result of the function call is a struct or union, and using the child `Sema` before it is destroyed to resolve the fields.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/type.zig b/src/type.zig
index 41f392c04a..467e9c931b 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -133,6 +133,7 @@ pub const Type = extern union {
.@"union",
.union_tagged,
+ .type_info,
=> return .Union,
.var_args_param => unreachable, // can be any type
@@ -248,6 +249,30 @@ pub const Type = extern union {
};
}
+ pub fn ptrIsMutable(ty: Type) bool {
+ return switch (ty.tag()) {
+ .single_const_pointer_to_comptime_int,
+ .const_slice_u8,
+ .single_const_pointer,
+ .many_const_pointer,
+ .manyptr_const_u8,
+ .c_const_pointer,
+ .const_slice,
+ => false,
+
+ .single_mut_pointer,
+ .many_mut_pointer,
+ .manyptr_u8,
+ .c_mut_pointer,
+ .mut_slice,
+ => true,
+
+ .pointer => ty.castTag(.pointer).?.data.mutable,
+
+ else => unreachable,
+ };
+ }
+
pub fn ptrInfo(self: Type) Payload.Pointer {
switch (self.tag()) {
.single_const_pointer_to_comptime_int => return .{ .data = .{
@@ -717,6 +742,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
.@"anyframe",
.generic_poison,
=> unreachable,
@@ -928,6 +954,7 @@ pub const Type = extern union {
.call_options => return writer.writeAll("std.builtin.CallOptions"),
.export_options => return writer.writeAll("std.builtin.ExportOptions"),
.extern_options => return writer.writeAll("std.builtin.ExternOptions"),
+ .type_info => return writer.writeAll("std.builtin.TypeInfo"),
.function => {
const payload = ty.castTag(.function).?.data;
try writer.writeAll("fn(");
@@ -1178,6 +1205,7 @@ pub const Type = extern union {
.comptime_int,
.comptime_float,
.enum_literal,
+ .type_info,
=> true,
.var_args_param => unreachable,
@@ -1269,6 +1297,7 @@ pub const Type = extern union {
.call_options => return Value.initTag(.call_options_type),
.export_options => return Value.initTag(.export_options_type),
.extern_options => return Value.initTag(.extern_options_type),
+ .type_info => return Value.initTag(.type_info_type),
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
else => return Value.Tag.ty.create(allocator, self),
@@ -1409,6 +1438,7 @@ pub const Type = extern union {
.empty_struct,
.empty_struct_literal,
.@"opaque",
+ .type_info,
=> false,
.inferred_alloc_const => unreachable,
@@ -1636,6 +1666,7 @@ pub const Type = extern union {
.inferred_alloc_mut,
.@"opaque",
.var_args_param,
+ .type_info,
=> unreachable,
.generic_poison => unreachable,
@@ -1667,6 +1698,7 @@ pub const Type = extern union {
.@"opaque" => unreachable,
.var_args_param => unreachable,
.generic_poison => unreachable,
+ .type_info => unreachable,
.@"struct" => {
const s = self.castTag(.@"struct").?.data;
@@ -1978,6 +2010,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
=> @panic("TODO at some point we gotta resolve builtin types"),
};
}
@@ -2691,6 +2724,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
.@"anyframe",
.anyframe_T,
.many_const_pointer,
@@ -2778,6 +2812,7 @@ pub const Type = extern union {
return switch (self.tag()) {
.@"struct" => &self.castTag(.@"struct").?.data.namespace,
.enum_full => &self.castTag(.enum_full).?.data.namespace,
+ .enum_nonexhaustive => &self.castTag(.enum_nonexhaustive).?.data.namespace,
.empty_struct => self.castTag(.empty_struct).?.data,
.@"opaque" => &self.castTag(.@"opaque").?.data,
.@"union" => &self.castTag(.@"union").?.data.namespace,
@@ -3022,6 +3057,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@@ -3058,6 +3094,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@@ -3167,6 +3204,7 @@ pub const Type = extern union {
call_options,
export_options,
extern_options,
+ type_info,
manyptr_u8,
manyptr_const_u8,
fn_noreturn_no_args,
@@ -3289,6 +3327,7 @@ pub const Type = extern union {
.call_options,
.export_options,
.extern_options,
+ .type_info,
.@"anyframe",
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),