diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Module.zig | 6 | ||||
| -rw-r--r-- | src/astgen.zig | 2 | ||||
| -rw-r--r-- | src/type.zig | 102 | ||||
| -rw-r--r-- | src/zir_sema.zig | 46 |
4 files changed, 108 insertions, 48 deletions
diff --git a/src/Module.zig b/src/Module.zig index 884b5fb8d4..5ea78d06d1 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3421,3 +3421,9 @@ pub fn getTarget(self: Module) Target { pub fn optimizeMode(self: Module) std.builtin.Mode { return self.comp.bin_file.options.optimize_mode; } + +pub fn validateVarType(mod: *Module, scope: *Scope, src: usize, ty: Type) !void { + if (!ty.isValidVarType(false)) { + return mod.fail(scope, src, "variable of type '{}' must be const or comptime", .{ty}); + } +} diff --git a/src/astgen.zig b/src/astgen.zig index 1142907faf..5cf8e12587 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -625,7 +625,7 @@ fn varDecl( const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst); break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; } else a: { - const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred); + const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred_mut); resolve_inferred_alloc = &alloc.base; break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } }; }; diff --git a/src/type.zig b/src/type.zig index 5e4182b1b6..7d35200727 100644 --- a/src/type.zig +++ b/src/type.zig @@ -78,7 +78,8 @@ pub const Type = extern union { .const_slice, .mut_slice, .pointer, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => return .Pointer, .optional, @@ -159,7 +160,8 @@ pub const Type = extern union { .optional_single_mut_pointer, => self.cast(Payload.ElemType), - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, else => null, }; @@ -387,7 +389,8 @@ pub const Type = extern union { .enum_literal, .anyerror_void_error_union, .@"anyframe", - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, .array_u8, @@ -690,7 +693,8 @@ pub const Type = extern union { const name = ty.castTag(.error_set_single).?.data; return out_stream.print("error{{{s}}}", .{name}); }, - .inferred_alloc => return out_stream.writeAll("(inferred allocation type)"), + .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"), + .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"), } unreachable; } @@ -738,7 +742,8 @@ pub const Type = extern union { .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), .const_slice_u8 => return Value.initTag(.const_slice_u8_type), .enum_literal => return Value.initTag(.enum_literal_type), - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, else => return Value.Tag.ty.create(allocator, self), } } @@ -810,7 +815,8 @@ pub const Type = extern union { .empty_struct, => false, - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, }; } @@ -928,7 +934,8 @@ pub const Type = extern union { .@"undefined", .enum_literal, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, }; } @@ -952,7 +959,8 @@ pub const Type = extern union { .enum_literal => unreachable, .single_const_pointer_to_comptime_int => unreachable, .empty_struct => unreachable, - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, .u8, .i8, @@ -1131,7 +1139,8 @@ pub const Type = extern union { .single_const_pointer, .single_mut_pointer, .single_const_pointer_to_comptime_int, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => true, .pointer => self.castTag(.pointer).?.data.size == .One, @@ -1214,7 +1223,8 @@ pub const Type = extern union { .single_const_pointer, .single_mut_pointer, .single_const_pointer_to_comptime_int, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => .One, .pointer => self.castTag(.pointer).?.data.size, @@ -1285,7 +1295,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .const_slice, @@ -1358,7 +1369,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .single_const_pointer, @@ -1440,7 +1452,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .pointer => { @@ -1517,7 +1530,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .pointer => { @@ -1636,7 +1650,8 @@ pub const Type = extern union { .error_set => unreachable, .error_set_single => unreachable, .empty_struct => unreachable, - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, .array => self.castTag(.array).?.data.elem_type, .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, @@ -1758,7 +1773,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, .array => self.castTag(.array).?.data.len, @@ -1825,7 +1841,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, .single_const_pointer, @@ -1909,7 +1926,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .int_signed, @@ -1985,7 +2003,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .int_unsigned, @@ -2051,7 +2070,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, .int_unsigned => .{ @@ -2141,7 +2161,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, .usize, @@ -2254,7 +2275,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, }; } @@ -2333,7 +2355,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, } } @@ -2411,7 +2434,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, } } @@ -2489,7 +2513,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, }; } @@ -2564,7 +2589,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, }; } @@ -2639,7 +2665,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, }; } @@ -2714,7 +2741,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => false, }; } @@ -2807,7 +2835,8 @@ pub const Type = extern union { ty = ty.castTag(.pointer).?.data.pointee_type; continue; }, - .inferred_alloc => unreachable, + .inferred_alloc_const => unreachable, + .inferred_alloc_mut => unreachable, }; } @@ -2876,7 +2905,8 @@ pub const Type = extern union { .error_set, .error_set_single, .empty_struct, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => return false, .c_const_pointer, @@ -2962,7 +2992,8 @@ pub const Type = extern union { .c_const_pointer, .c_mut_pointer, .pointer, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => unreachable, .empty_struct => self.castTag(.empty_struct).?.data, @@ -3077,7 +3108,9 @@ pub const Type = extern union { /// This is a special value that tracks a set of types that have been stored /// to an inferred allocation. It does not support most of the normal type queries. /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. - inferred_alloc, // See last_no_payload_tag below. + inferred_alloc_mut, + /// Same as `inferred_alloc_mut` but the local is `var` not `const`. + inferred_alloc_const, // See last_no_payload_tag below. // After this, the tag requires a payload. array_u8, @@ -3105,7 +3138,7 @@ pub const Type = extern union { error_set_single, empty_struct, - pub const last_no_payload_tag = Tag.inferred_alloc; + pub const last_no_payload_tag = Tag.inferred_alloc_const; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; pub fn Type(comptime t: Tag) type { @@ -3152,7 +3185,8 @@ pub const Type = extern union { .anyerror_void_error_union, .@"anyframe", .const_slice_u8, - .inferred_alloc, + .inferred_alloc_const, + .inferred_alloc_mut, => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), .array_u8, diff --git a/src/zir_sema.zig b/src/zir_sema.zig index 87b96825f9..629dfa0c9a 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -30,8 +30,18 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! switch (old_inst.tag) { .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?), .alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?), - .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?), - .alloc_inferred_mut => return analyzeInstAllocInferredMut(mod, scope, old_inst.castTag(.alloc_inferred_mut).?), + .alloc_inferred => return analyzeInstAllocInferred( + mod, + scope, + old_inst.castTag(.alloc_inferred).?, + .inferred_alloc_const, + ), + .alloc_inferred_mut => return analyzeInstAllocInferred( + mod, + scope, + old_inst.castTag(.alloc_inferred_mut).?, + .inferred_alloc_mut, + ), .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?), .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?), .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?), @@ -423,15 +433,18 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { const var_type = try resolveType(mod, scope, inst.positionals.operand); - if (!var_type.isValidVarType(false)) { - return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type}); - } + try mod.validateVarType(scope, inst.base.src, var_type); const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One); const b = try mod.requireRuntimeBlock(scope, inst.base.src); return mod.addNoOp(b, inst.base.src, ptr_type, .alloc); } -fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { +fn analyzeInstAllocInferred( + mod: *Module, + scope: *Scope, + inst: *zir.Inst.NoOp, + mut_tag: Type.Tag, +) InnerError!*Inst { const val_payload = try scope.arena().create(Value.Payload.InferredAlloc); val_payload.* = .{ .data = .{}, @@ -441,7 +454,11 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I // to a normal instruction when we hit `resolve_inferred_alloc`. So we append // to the block even though it is currently a `.constant`. const result = try mod.constInst(scope, inst.base.src, .{ - .ty = Type.initTag(.inferred_alloc), + .ty = switch (mut_tag) { + .inferred_alloc_const => Type.initTag(.inferred_alloc_const), + .inferred_alloc_mut => Type.initTag(.inferred_alloc_mut), + else => unreachable, + }, .val = Value.initPayload(&val_payload.base), }); const block = try mod.requireFunctionBlock(scope, inst.base.src); @@ -449,10 +466,6 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I return result; } -fn analyzeInstAllocInferredMut(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { - return mod.fail(scope, inst.base.src, "TODO implement analyzeInstAllocInferredMut", .{}); -} - fn analyzeInstResolveInferredAlloc( mod: *Module, scope: *Scope, @@ -463,8 +476,15 @@ fn analyzeInstResolveInferredAlloc( const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; const peer_inst_list = inferred_alloc.data.stored_inst_list.items; const final_elem_ty = try mod.resolvePeerTypes(scope, peer_inst_list); - const is_mut = true; - const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, is_mut, .One); + const var_is_mut = switch (ptr.ty.tag()) { + .inferred_alloc_const => false, + .inferred_alloc_mut => true, + else => unreachable, + }; + if (var_is_mut) { + try mod.validateVarType(scope, inst.base.src, final_elem_ty); + } + const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, true, .One); // Change it to a normal alloc. ptr.ty = final_ptr_ty; |
