diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-08-04 21:11:31 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-08-04 21:11:31 -0700 |
| commit | d4468affb751668e156230c32b29c84684825b4f (patch) | |
| tree | 3394fc54a11c8c6c01783d7e5ee753c87ce0feda /src/type.zig | |
| parent | 382d201781eb57d9e950ad07ce814adc5a68b329 (diff) | |
| download | zig-d4468affb751668e156230c32b29c84684825b4f.tar.gz zig-d4468affb751668e156230c32b29c84684825b4f.zip | |
stage2 generics improvements: anytype and param type exprs
AstGen result locations now have a `coerced_ty` tag which is the same as
`ty` except it assumes that Sema will do a coercion, so it does not
redundantly add an `as` instruction into the ZIR code. This results in
cleaner ZIR and about a 14% reduction of ZIR bytes.
param and param_comptime ZIR instructions now have a block body for
their type expressions. This allows Sema to skip evaluation of the
block in the case that the parameter is comptime-provided. It also
allows a new mechanism to function: when evaluating type expressions of
generic functions, if it would depend on another parameter, it returns
`error.GenericPoison` which bubbles up and then is caught by the
param/param_comptime instruction and then handled.
This allows parameters to be evaluated independently so that the type
info for functions which have comptime or anytype parameters will still
have types populated for parameters that do not depend on values of
previous parameters (because evaluation of their param blocks will return
successfully instead of `error.GenericPoison`).
It also makes iteration over the block that contains function parameters
slightly more efficient since it now only contains the param
instructions.
Finally, it fixes the case where a generic function type expression contains
a function prototype. Formerly, this situation would cause shared state
to clobber each other; now it is in a proper tree structure so that
can't happen. This fix also required adding a field to Sema
`comptime_args_fn_inst` to make sure that the `comptime_args` field
passed into Sema is applied to the correct `func` instruction.
Source location for `node_offset_asm_ret_ty` is fixed; it was pointing at
the asm output name rather than the return type as intended.
Generic function instantiation is fixed, notably with respect to
parameter type expressions that depend on previous parameters, and with
respect to types which must be always comptime-known. This involves
passing all the comptime arguments at a callsite of a generic function,
and allowing the generic function semantic analysis to coerce the values
to the proper types (since it has access to the evaluated parameter type
expressions) and then decide based on the type whether the parameter is
runtime known or not. In the case of explicitly marked `comptime`
parameters, there is a check at the semantic analysis of the `call`
instruction.
Semantic analysis of `call` instructions does type coercion on the
arguments, which is needed both for generic functions and to make up for
using `coerced_ty` result locations (mentioned above).
Tasks left in this branch:
* Implement the memoization table.
* Add test coverage.
* Improve error reporting and source locations for compile errors.
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/type.zig b/src/type.zig index 237614e372..0e99a929f0 100644 --- a/src/type.zig +++ b/src/type.zig @@ -130,6 +130,7 @@ pub const Type = extern union { => return .Union, .var_args_param => unreachable, // can be any type + .generic_poison => unreachable, // must be handled earlier } } @@ -699,6 +700,7 @@ pub const Type = extern union { .export_options, .extern_options, .@"anyframe", + .generic_poison, => unreachable, .array_u8, @@ -1083,11 +1085,117 @@ pub const Type = extern union { }, .inferred_alloc_const => return writer.writeAll("(inferred_alloc_const)"), .inferred_alloc_mut => return writer.writeAll("(inferred_alloc_mut)"), + .generic_poison => return writer.writeAll("(generic poison)"), } unreachable; } } + /// Anything that reports hasCodeGenBits() false returns false here as well. + pub fn requiresComptime(ty: Type) bool { + return switch (ty.tag()) { + .u1, + .u8, + .i8, + .u16, + .i16, + .u32, + .i32, + .u64, + .i64, + .u128, + .i128, + .usize, + .isize, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .f16, + .f32, + .f64, + .f128, + .c_void, + .bool, + .void, + .anyerror, + .noreturn, + .@"anyframe", + .@"null", + .@"undefined", + .atomic_ordering, + .atomic_rmw_op, + .calling_convention, + .float_mode, + .reduce_op, + .call_options, + .export_options, + .extern_options, + .manyptr_u8, + .manyptr_const_u8, + .fn_noreturn_no_args, + .fn_void_no_args, + .fn_naked_noreturn_no_args, + .fn_ccc_void_no_args, + .single_const_pointer_to_comptime_int, + .const_slice_u8, + .anyerror_void_error_union, + .empty_struct_literal, + .function, + .empty_struct, + .error_set, + .error_set_single, + .error_set_inferred, + .@"opaque", + => false, + + .type, + .comptime_int, + .comptime_float, + .enum_literal, + => true, + + .var_args_param => unreachable, + .inferred_alloc_mut => unreachable, + .inferred_alloc_const => unreachable, + .generic_poison => unreachable, + + .array_u8, + .array_u8_sentinel_0, + .array, + .array_sentinel, + .vector, + .pointer, + .single_const_pointer, + .single_mut_pointer, + .many_const_pointer, + .many_mut_pointer, + .c_const_pointer, + .c_mut_pointer, + .const_slice, + .mut_slice, + .int_signed, + .int_unsigned, + .optional, + .optional_single_mut_pointer, + .optional_single_const_pointer, + .error_union, + .anyframe_T, + .@"struct", + .@"union", + .union_tagged, + .enum_simple, + .enum_full, + .enum_nonexhaustive, + => false, // TODO some of these should be `true` depending on their child types + }; + } + pub fn toValue(self: Type, allocator: *Allocator) Allocator.Error!Value { switch (self.tag()) { .u1 => return Value.initTag(.u1_type), @@ -1287,6 +1395,7 @@ pub const Type = extern union { .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, .var_args_param => unreachable, + .generic_poison => unreachable, }; } @@ -1509,6 +1618,8 @@ pub const Type = extern union { .@"opaque", .var_args_param, => unreachable, + + .generic_poison => unreachable, }; } @@ -1536,6 +1647,7 @@ pub const Type = extern union { .inferred_alloc_mut => unreachable, .@"opaque" => unreachable, .var_args_param => unreachable, + .generic_poison => unreachable, .@"struct" => { const s = self.castTag(.@"struct").?.data; @@ -1702,6 +1814,7 @@ pub const Type = extern union { .inferred_alloc_mut => unreachable, .@"opaque" => unreachable, .var_args_param => unreachable, + .generic_poison => unreachable, .@"struct" => { @panic("TODO bitSize struct"); @@ -2626,6 +2739,7 @@ pub const Type = extern union { .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, + .generic_poison => unreachable, }; } @@ -3039,6 +3153,7 @@ pub const Type = extern union { single_const_pointer_to_comptime_int, const_slice_u8, anyerror_void_error_union, + generic_poison, /// This is a special type for variadic parameters of a function call. /// Casts to it will validate that the type can be passed to a c calling convetion function. var_args_param, @@ -3136,6 +3251,7 @@ pub const Type = extern union { .single_const_pointer_to_comptime_int, .anyerror_void_error_union, .const_slice_u8, + .generic_poison, .inferred_alloc_const, .inferred_alloc_mut, .var_args_param, |
