mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
stage2: compile error for invalid var type
This commit is contained in:
parent
79a9391414
commit
982acc22fd
@ -1,2 +0,0 @@
|
||||
* compile error for "variable of type '{}' must be const or comptime" after resolving types
|
||||
* test with branches
|
||||
@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 } };
|
||||
};
|
||||
|
||||
102
src/type.zig
102
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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1322,4 +1322,13 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\}
|
||||
, &[_][]const u8{":2:5: error: unused for label"});
|
||||
}
|
||||
|
||||
{
|
||||
var case = ctx.exe("bad inferred variable type", linux_x64);
|
||||
case.addError(
|
||||
\\export fn foo() void {
|
||||
\\ var x = null;
|
||||
\\}
|
||||
, &[_][]const u8{":2:9: error: variable of type '@Type(.Null)' must be const or comptime"});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user