diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-08-20 15:23:55 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-08-20 15:41:57 -0700 |
| commit | 0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4 (patch) | |
| tree | c3de2205e0bb525d61ee78800c118b13efbf1029 /src/type.zig | |
| parent | 2f1abd919a8465e515875cd08816778df795aabe (diff) | |
| download | zig-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.zig | 39 |
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"), |
