Commit 927d20b46b
Changed files (42)
test
cases
compile_errors
stage1
obj
src/Sema.zig
@@ -4109,6 +4109,8 @@ fn validateUnionInit(
const union_init = try sema.addConstant(union_ty, union_val);
try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
return;
+ } else if (try sema.typeRequiresComptime(union_ty)) {
+ return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only union must be comptime-known");
}
const new_tag = try sema.addConstant(tag_ty, tag_val);
@@ -4226,6 +4228,7 @@ fn validateStructInit(
var first_block_index = block.instructions.items.len;
var make_runtime = false;
+ const require_comptime = try sema.typeRequiresComptime(struct_ty);
const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data);
@@ -4301,6 +4304,9 @@ fn validateStructInit(
}
if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
field_values[i] = val;
+ } else if (require_comptime) {
+ const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
+ return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
} else {
struct_is_comptime = false;
}
@@ -5402,7 +5408,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
error.NeededSourceLocation => {
_ = try sema.resolveExportOptions(block, options_src, extra.options);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -5429,7 +5435,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
error.NeededSourceLocation => {
_ = try sema.resolveExportOptions(block, options_src, extra.options);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -6512,7 +6518,7 @@ fn analyzeCall(
func_ty_info.param_types,
func,
);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -6674,7 +6680,7 @@ fn analyzeCall(
uncasted_arg,
opts,
);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -6687,7 +6693,7 @@ fn analyzeCall(
uncasted_arg,
Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),
);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -6991,7 +6997,7 @@ fn instantiateGenericCall(
const decl = sema.mod.declPtr(block.src_decl);
const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src);
_ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -7174,7 +7180,7 @@ fn instantiateGenericCall(
const decl = sema.mod.declPtr(block.src_decl);
const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);
_ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -7330,7 +7336,7 @@ fn instantiateGenericCall(
new_fn_info,
&runtime_i,
);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -8417,6 +8423,10 @@ fn funcCommon(
const param_types = try sema.arena.alloc(Type, block.params.items.len);
const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
for (block.params.items) |param, i| {
+ const is_noalias = blk: {
+ const index = std.math.cast(u5, i) orelse break :blk false;
+ break :blk @truncate(u1, noalias_bits >> index) != 0;
+ };
param_types[i] = param.ty;
sema.analyzeParameter(
block,
@@ -8427,6 +8437,7 @@ fn funcCommon(
&is_generic,
cc_resolved,
has_body,
+ is_noalias,
) catch |err| switch (err) {
error.NeededSourceLocation => {
const decl = sema.mod.declPtr(block.src_decl);
@@ -8439,8 +8450,9 @@ fn funcCommon(
&is_generic,
cc_resolved,
has_body,
+ is_noalias,
);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -8689,6 +8701,7 @@ fn analyzeParameter(
is_generic: *bool,
cc: std.builtin.CallingConvention,
has_body: bool,
+ is_noalias: bool,
) !void {
const requires_comptime = try sema.typeRequiresComptime(param.ty);
comptime_params[i] = param.is_comptime or requires_comptime;
@@ -8743,6 +8756,9 @@ fn analyzeParameter(
};
return sema.failWithOwnedErrorMsg(msg);
}
+ if (!this_generic and is_noalias and !param.ty.isPtrAtRuntime()) {
+ return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
+ }
}
fn zirParam(
@@ -10633,7 +10649,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const case_src = Module.SwitchProngSrc{ .range = .{ .prong = multi_i, .item = range_i } };
const decl = sema.mod.declPtr(case_block.src_decl);
try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));
- return error.AnalysisFail;
+ unreachable;
},
else => return err,
};
@@ -10669,7 +10685,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const case_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } };
const decl = sema.mod.declPtr(case_block.src_decl);
try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));
- return error.AnalysisFail;
+ unreachable;
},
else => return err,
};
@@ -11101,10 +11117,8 @@ fn resolveSwitchItemVal(
} else |err| switch (err) {
error.NeededSourceLocation => {
const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand);
- return TypedValue{
- .ty = item_ty,
- .val = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known"),
- };
+ _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
+ unreachable;
},
else => |e| return e,
}
@@ -11618,6 +11632,21 @@ fn zirShl(
});
}
}
+ if (rhs_ty.zigTypeTag() == .Vector) {
+ var i: usize = 0;
+ while (i < rhs_ty.vectorLen()) : (i += 1) {
+ if (rhs_val.indexVectorlike(i).compareHetero(.lt, Value.zero, target)) {
+ return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
+ rhs_val.indexVectorlike(i).fmtValue(scalar_ty, sema.mod),
+ i,
+ });
+ }
+ }
+ } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {
+ return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
+ rhs_val.fmtValue(scalar_ty, sema.mod),
+ });
+ }
}
const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
@@ -11787,6 +11816,21 @@ fn zirShr(
});
}
}
+ if (rhs_ty.zigTypeTag() == .Vector) {
+ var i: usize = 0;
+ while (i < rhs_ty.vectorLen()) : (i += 1) {
+ if (rhs_val.indexVectorlike(i).compareHetero(.lt, Value.zero, target)) {
+ return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
+ rhs_val.indexVectorlike(i).fmtValue(scalar_ty, sema.mod),
+ i,
+ });
+ }
+ }
+ } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {
+ return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
+ rhs_val.fmtValue(scalar_ty, sema.mod),
+ });
+ }
if (maybe_lhs_val) |lhs_val| {
if (lhs_val.isUndef()) {
return sema.addConstUndef(lhs_ty);
@@ -14721,7 +14765,9 @@ fn analyzeCmp(
) CompileError!Air.Inst.Ref {
const lhs_ty = sema.typeOf(lhs);
const rhs_ty = sema.typeOf(rhs);
- try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
+ if (lhs_ty.zigTypeTag() != .Optional and rhs_ty.zigTypeTag() != .Optional) {
+ try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
+ }
if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src);
@@ -15217,12 +15263,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.ty.create(params_anon_decl.arena(), try param_ty.copy(params_anon_decl.arena())),
);
+ const is_noalias = blk: {
+ const index = std.math.cast(u5, i) orelse break :blk false;
+ break :blk @truncate(u1, info.noalias_bits >> index) != 0;
+ };
+
const param_fields = try params_anon_decl.arena().create([3]Value);
param_fields.* = .{
// is_generic: bool,
Value.makeBool(is_generic),
// is_noalias: bool,
- Value.false, // TODO
+ Value.makeBool(is_noalias),
// arg_type: ?type,
param_ty_val,
};
@@ -17409,7 +17460,7 @@ fn zirStructInitAnon(
const decl = sema.mod.declPtr(block.src_decl);
const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);
try sema.requireRuntimeBlock(block, src, field_src);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -17474,25 +17525,31 @@ fn zirArrayInit(
defer gpa.free(resolved_args);
for (args[1..]) |arg, i| {
const resolved_arg = try sema.resolveInst(arg);
- const arg_src = src; // TODO better source location
const elem_ty = if (array_ty.zigTypeTag() == .Struct)
array_ty.structFieldType(i)
else
array_ty.elemType2();
- resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);
+ resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
+ error.NeededSourceLocation => {
+ const decl = sema.mod.declPtr(block.src_decl);
+ const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);
+ _ = try sema.coerce(block, elem_ty, resolved_arg, elem_src);
+ unreachable;
+ },
+ else => return err,
+ };
}
if (sentinel_val) |some| {
resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some);
}
- const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
- const arg_src = src; // TODO better source location
+ const opt_runtime_index: ?u32 = for (resolved_args) |arg, i| {
const comptime_known = try sema.isComptimeKnown(arg);
- if (!comptime_known) break arg_src;
+ if (!comptime_known) break @intCast(u32, i);
} else null;
- const runtime_src = opt_runtime_src orelse {
+ const runtime_index = opt_runtime_index orelse {
const elem_vals = try sema.arena.alloc(Value, resolved_args.len);
for (resolved_args) |arg, i| {
@@ -17504,7 +17561,15 @@ fn zirArrayInit(
return sema.addConstantMaybeRef(block, array_ty, array_val, is_ref);
};
- try sema.requireRuntimeBlock(block, src, runtime_src);
+ sema.requireRuntimeBlock(block, src, .unneeded) catch |err| switch (err) {
+ error.NeededSourceLocation => {
+ const decl = sema.mod.declPtr(block.src_decl);
+ const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);
+ try sema.requireRuntimeBlock(block, src, elem_src);
+ unreachable;
+ },
+ else => return err,
+ };
try sema.queueFullTypeResolution(array_ty);
if (is_ref) {
@@ -18502,10 +18567,47 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
}
var buffer: Value.ToTypeBuffer = undefined;
+ const field_ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator);
gop.value_ptr.* = .{
- .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
+ .ty = field_ty,
.abi_align = @intCast(u32, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?),
};
+
+ if (field_ty.zigTypeTag() == .Opaque) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
+ errdefer msg.destroy(sema.gpa);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
+ if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+ errdefer msg.destroy(sema.gpa);
+
+ const src_decl = sema.mod.declPtr(block.src_decl);
+ try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), field_ty, .union_field);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+ errdefer msg.destroy(sema.gpa);
+
+ const src_decl = sema.mod.declPtr(block.src_decl);
+ try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl), field_ty);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
}
if (tag_ty_field_names) |names| {
@@ -18587,21 +18689,25 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
// is_noalias: bool,
const arg_is_noalias = arg_val[1].toBool();
// arg_type: ?type,
- const param_type_val = arg_val[2];
+ const param_type_opt_val = arg_val[2];
if (arg_is_generic) {
return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});
}
+ const param_type_val = param_type_opt_val.optionalValue() orelse
+ return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
+ const param_type = try param_type_val.toType(&buf).copy(sema.arena);
+
if (arg_is_noalias) {
- noalias_bits = @as(u32, 1) << (std.math.cast(u5, i) orelse
+ if (!param_type.isPtrAtRuntime()) {
+ return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
+ }
+ noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
}
- const param_type = param_type_val.optionalValue() orelse
- return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
-
- param_types[i] = try param_type.toType(&buf).copy(sema.arena);
+ param_types[i] = param_type;
comptime_params[i] = false;
}
@@ -18745,13 +18851,60 @@ fn reifyStruct(
}
var buffer: Value.ToTypeBuffer = undefined;
+ const field_ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator);
gop.value_ptr.* = .{
- .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
+ .ty = field_ty,
.abi_align = abi_align,
.default_val = default_val,
.is_comptime = is_comptime_val.toBool(),
.offset = undefined,
};
+
+ if (field_ty.zigTypeTag() == .Opaque) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
+ errdefer msg.destroy(sema.gpa);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
+ if (field_ty.zigTypeTag() == .NoReturn) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});
+ errdefer msg.destroy(sema.gpa);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
+ if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+ errdefer msg.destroy(sema.gpa);
+
+ const src_decl = sema.mod.declPtr(block.src_decl);
+ try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), field_ty, .struct_field);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty))) {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+ errdefer msg.destroy(sema.gpa);
+
+ const src_decl = sema.mod.declPtr(block.src_decl);
+ try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl), field_ty);
+
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
}
if (layout == .Packed) {
@@ -21544,7 +21697,7 @@ fn zirPrefetch(
const options = sema.resolvePrefetchOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
error.NeededSourceLocation => {
_ = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -21637,7 +21790,7 @@ fn zirBuiltinExtern(
const options = sema.resolveExternOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
error.NeededSourceLocation => {
_ = try sema.resolveExternOptions(block, options_src, extra.rhs);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -24493,7 +24646,7 @@ fn coerceExtra(
}
if (try sema.resolveMaybeUndefVal(inst)) |val| {
const result_val = try val.floatCast(sema.arena, dest_ty, target);
- if (!val.eql(result_val, dest_ty, sema.mod)) {
+ if (!val.eql(result_val, inst_ty, sema.mod)) {
return sema.fail(
block,
inst_src,
@@ -24987,7 +25140,7 @@ const InMemoryCoercionResult = union(enum) {
cur = param.child;
},
.fn_cc => |cc| {
- try sema.errNote(block, src, msg, "calling convention {s} cannot cast into calling convention {s}", .{ @tagName(cc.actual), @tagName(cc.wanted) });
+ try sema.errNote(block, src, msg, "calling convention '{s}' cannot cast into calling convention '{s}'", .{ @tagName(cc.actual), @tagName(cc.wanted) });
break;
},
.fn_return_type => |pair| {
@@ -26842,6 +26995,9 @@ fn coerceCompatiblePtrs(
) !Air.Inst.Ref {
const inst_ty = sema.typeOf(inst);
if (try sema.resolveMaybeUndefVal(inst)) |val| {
+ if (!val.isUndef() and val.isNull() and !dest_ty.isAllowzeroPtr()) {
+ return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
+ }
// The comptime Value representation is compatible with both types.
return sema.addConstant(dest_ty, val);
}
@@ -30177,7 +30333,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
const tree = try sema.getAstTree(&block_scope);
const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
_ = try sema.coerce(&block_scope, field.ty, init, init_src);
- return error.AnalysisFail;
+ unreachable;
},
else => |e| return e,
};
@@ -30304,6 +30460,25 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
if (int_tag_ty.zigTypeTag() != .Int and int_tag_ty.zigTypeTag() != .ComptimeInt) {
return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)});
}
+
+ if (fields_len > 0) {
+ var field_count_val: Value.Payload.U64 = .{
+ .base = .{ .tag = .int_u64 },
+ .data = fields_len - 1,
+ };
+ if (!(try sema.intFitsInType(Value.initPayload(&field_count_val.base), int_tag_ty, null))) {
+ const msg = msg: {
+ const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});
+ errdefer msg.destroy(sema.gpa);
+ try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{
+ int_tag_ty.fmt(sema.mod),
+ fields_len - 1,
+ });
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ }
+ }
union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty, union_obj);
const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;
enum_field_names = &enum_obj.fields;
@@ -30379,7 +30554,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
} else .none;
if (enum_value_map) |map| {
- if (tag_ref != .none) {
+ const copied_val = if (tag_ref != .none) blk: {
const tag_src = src; // TODO better source location
const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);
const val = try sema.resolveConstValue(&block_scope, tag_src, coerced, "enum tag value must be comptime-known");
@@ -30387,23 +30562,31 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
// This puts the memory into the union arena, not the enum arena, but
// it is OK since they share the same lifetime.
- const copied_val = try val.copy(decl_arena_allocator);
- map.putAssumeCapacityContext(copied_val, {}, .{
- .ty = int_tag_ty,
- .mod = mod,
- });
- } else {
+ break :blk try val.copy(decl_arena_allocator);
+ } else blk: {
const val = if (last_tag_val) |val|
try sema.intAdd(val, Value.one, int_tag_ty)
else
Value.zero;
last_tag_val = val;
- const copied_val = try val.copy(decl_arena_allocator);
- map.putAssumeCapacityContext(copied_val, {}, .{
- .ty = int_tag_ty,
- .mod = mod,
- });
+ break :blk try val.copy(decl_arena_allocator);
+ };
+ const gop = map.getOrPutAssumeCapacityContext(copied_val, .{
+ .ty = int_tag_ty,
+ .mod = mod,
+ });
+ if (gop.found_existing) {
+ const tree = try sema.getAstTree(&block_scope);
+ const field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, field_i);
+ const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, gop.index);
+ const msg = msg: {
+ const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
}
}
src/type.zig
@@ -177,9 +177,10 @@ pub const Type = extern union {
.Float,
.ComptimeFloat,
.ComptimeInt,
- .Vector, // TODO some vectors require is_equality_cmp==true
=> true,
+ .Vector => ty.elemType2().isSelfComparable(is_equality_cmp),
+
.Bool,
.Type,
.Void,
test/cases/compile_errors/stage1/obj/bad_alignment_in_implicit_cast_from_array_pointer_to_slice.zig
@@ -1,11 +0,0 @@
-export fn a() void {
- var x: [10]u8 = undefined;
- var y: []align(16) u8 = &x;
- _ = y;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:3:30: error: expected type '[]align(16) u8', found '*[10]u8'
test/cases/compile_errors/stage1/obj/compare_optional_to_non-optional_with_invalid_types.zig
@@ -1,35 +0,0 @@
-export fn inconsistentChildType() void {
- var x: ?i32 = undefined;
- const y: comptime_int = 10;
- _ = (x == y);
-}
-
-export fn optionalToOptional() void {
- var x: ?i32 = undefined;
- var y: ?i32 = undefined;
- _ = (x == y);
-}
-
-export fn optionalVector() void {
- var x: ?@Vector(10, i32) = undefined;
- var y: @Vector(10, i32) = undefined;
- _ = (x == y);
-}
-
-export fn invalidChildType() void {
- var x: ?[3]i32 = undefined;
- var y: [3]i32 = undefined;
- _ = (x == y);
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// :4:12: error: cannot compare types '?i32' and 'comptime_int'
-// :4:12: note: optional child type 'i32' must be the same as non-optional type 'comptime_int'
-// :10:12: error: cannot compare types '?i32' and '?i32'
-// :10:12: note: optional to optional comparison is only supported for optional pointer types
-// :16:12: error: TODO add comparison of optional vector
-// :22:12: error: cannot compare types '?[3]i32' and '[3]i32'
-// :22:12: note: operator not supported for type '[3]i32'
test/cases/compile_errors/stage1/obj/floatToInt_comptime_safety.zig
@@ -1,17 +0,0 @@
-comptime {
- _ = @floatToInt(i8, @as(f32, -129.1));
-}
-comptime {
- _ = @floatToInt(u8, @as(f32, -1.1));
-}
-comptime {
- _ = @floatToInt(u8, @as(f32, 256.1));
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:9: error: integer value '-129' cannot be stored in type 'i8'
-// tmp.zig:5:9: error: integer value '-1' cannot be stored in type 'u8'
-// tmp.zig:8:9: error: integer value '256' cannot be stored in type 'u8'
test/cases/compile_errors/stage1/obj/implicit_casting_too_big_integers_to_C_pointers.zig
@@ -1,16 +0,0 @@
-export fn a() void {
- var ptr: [*c]u8 = (1 << 64) + 1;
- _ = ptr;
-}
-export fn b() void {
- var x: u65 = 0x1234;
- var ptr: [*c]u8 = x;
- _ = ptr;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:33: error: integer value 18446744073709551617 cannot be coerced to type 'usize'
-// tmp.zig:7:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'
test/cases/compile_errors/stage1/obj/implicit_dependency_on_libc.zig
@@ -1,11 +0,0 @@
-extern "c" fn exit(u8) void;
-export fn entry() void {
- exit(0);
-}
-
-// error
-// backend=stage1
-// target=native-linux
-// is_test=1
-//
-// tmp.zig:3:5: error: dependency on libc must be explicitly specified in the build command
test/cases/compile_errors/stage1/obj/libc_headers_note.zig
@@ -1,12 +0,0 @@
-const c = @cImport(@cInclude("stdio.h"));
-export fn entry() void {
- _ = c.printf("hello, world!\n");
-}
-
-// error
-// backend=stage1
-// is_test=1
-// target=native-linux
-//
-// tmp.zig:1:11: error: C import failed
-// tmp.zig:1:11: note: libc headers not available; compilation does not link against libc
test/cases/compile_errors/stage1/obj/passing_an_under-aligned_function_pointer.zig
@@ -1,13 +0,0 @@
-export fn entry() void {
- testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
-}
-fn testImplicitlyDecreaseFnAlign(ptr: fn () align(8) i32, answer: i32) void {
- if (ptr() != answer) unreachable;
-}
-fn alignedSmall() align(4) i32 { return 1234; }
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:35: error: expected type 'fn() align(8) i32', found 'fn() align(4) i32'
test/cases/compile_errors/stage1/obj/shift_amount_has_to_be_an_integer_type.zig
@@ -1,10 +0,0 @@
-export fn entry() void {
- const x = 1 << &@as(u8, 10);
- _ = x;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:21: error: shift amount has to be an integer type, but found '*const u8'
test/cases/compile_errors/stage1/obj/slice_sentinel_mismatch-1.zig
@@ -1,10 +0,0 @@
-export fn entry() void {
- const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
- _ = y;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'
test/cases/compile_errors/stage1/obj/union_with_too_small_explicit_signed_tag_type.zig
@@ -1,16 +0,0 @@
-const U = union(enum(i2)) {
- A: u8,
- B: u8,
- C: u8,
- D: u8,
-};
-export fn entry() void {
- _ = U{ .D = 1 };
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:1:22: error: specified integer tag type cannot represent every field
-// tmp.zig:1:22: note: type i2 cannot fit values in range 0...3
test/cases/compile_errors/bad_alignment_in_implicit_cast_from_array_pointer_to_slice.zig
@@ -0,0 +1,12 @@
+export fn a() void {
+ var x: [10]u8 = undefined;
+ var y: []align(16) u8 = &x;
+ _ = y;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:29: error: expected type '[]align(16) u8', found '*[10]u8'
+// :3:29: note: pointer alignment '1' cannot cast into pointer alignment '16'
test/cases/compile_errors/stage1/obj/bad_alignment_type.zig → test/cases/compile_errors/bad_alignment_type.zig
@@ -8,8 +8,8 @@ export fn entry2() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:20: error: expected type 'u29', found 'bool'
-// tmp.zig:6:19: error: fractional component prevents float value 12.340000 from being casted to type 'u29'
+// :2:20: error: expected type 'u32', found 'bool'
+// :6:19: error: fractional component prevents float value '12.34' from coercion to type 'u32'
test/cases/compile_errors/compare_optional_to_non-optional_with_invalid_types.zig
@@ -0,0 +1,37 @@
+export fn inconsistentChildType() void {
+ var x: ?i32 = undefined;
+ const y: comptime_int = 10;
+ _ = (x == y);
+}
+export fn optionalToOptional() void {
+ var x: ?i32 = undefined;
+ var y: ?i32 = undefined;
+ _ = (x == y);
+}
+export fn optionalVector() void {
+ var x: ?@Vector(10, i32) = undefined;
+ var y: @Vector(10, i32) = undefined;
+ _ = (x == y);
+}
+export fn optionalVector2() void {
+ var x: ?@Vector(10, i32) = undefined;
+ var y: @Vector(11, i32) = undefined;
+ _ = (x == y);
+}
+export fn invalidChildType() void {
+ var x: ?[3]i32 = undefined;
+ var y: [3]i32 = undefined;
+ _ = (x == y);
+}
+
+// error
+// backend=llvm
+// target=native
+//
+// :4:12: error: incompatible types: '?i32' and 'comptime_int'
+// :4:10: note: type '?i32' here
+// :4:15: note: type 'comptime_int' here
+// :19:12: error: incompatible types: '?@Vector(10, i32)' and '@Vector(11, i32)'
+// :19:10: note: type '?@Vector(10, i32)' here
+// :19:15: note: type '@Vector(11, i32)' here
+// :24:12: error: operator == not allowed for type '?[3]i32'
test/cases/compile_errors/stage1/obj/comptime_implicit_cast_f64_to_f32.zig → test/cases/compile_errors/comptime_implicit_cast_f64_to_f32.zig
@@ -5,7 +5,7 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:3:20: error: cast of value 16777217.000000 to type 'f32' loses information
+// :3:20: error: type 'f32' cannot represent float value '16777217'
test/cases/compile_errors/stage1/obj/error_when_evaluating_return_type.zig → test/cases/compile_errors/error_when_evaluating_return_type.zig
@@ -11,7 +11,7 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:19: error: expected type 'i32', found 'type'
+// :2:19: error: expected type 'i32', found 'type'
test/cases/compile_errors/stage1/obj/extern_function_pointer_mismatch.zig → test/cases/compile_errors/extern_function_pointer_mismatch.zig
@@ -6,7 +6,8 @@ export fn c(x: i32) i32 {return x + 2;}
export fn entry() usize { return @sizeOf(@TypeOf(fns)); }
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:1:37: error: expected type 'fn(i32) i32', found 'fn(i32) callconv(.C) i32'
+// :1:37: error: expected type 'fn(i32) i32', found 'fn(i32) callconv(.C) i32'
+// :1:37: note: calling convention 'C' cannot cast into calling convention 'Unspecified'
test/cases/compile_errors/floatToInt_comptime_safety.zig
@@ -0,0 +1,17 @@
+comptime {
+ _ = @floatToInt(i8, @as(f32, -129.1));
+}
+comptime {
+ _ = @floatToInt(u8, @as(f32, -1.1));
+}
+comptime {
+ _ = @floatToInt(u8, @as(f32, 256.1));
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:25: error: float value '-129.10000610351562' cannot be stored in integer type 'i8'
+// :5:25: error: float value '-1.100000023841858' cannot be stored in integer type 'u8'
+// :8:25: error: float value '256.1000061035156' cannot be stored in integer type 'u8'
test/cases/compile_errors/stage1/obj/implicit_casting_null_c_pointer_to_zig_pointer.zig → test/cases/compile_errors/implicit_casting_null_c_pointer_to_zig_pointer.zig
@@ -5,7 +5,7 @@ comptime {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:3:24: error: null pointer casted to type '*u8'
+// :3:24: error: null pointer casted to type '*u8'
test/cases/compile_errors/implicit_dependency_on_libc.zig
@@ -0,0 +1,10 @@
+extern "c" fn exit(u8) void;
+export fn entry() void {
+ exit(0);
+}
+
+// error
+// backend=stage2
+// target=native-linux
+//
+// :1:8: error: dependency on libc must be explicitly specified in the build command
test/cases/compile_errors/stage1/obj/indexing_a_undefined_slice_at_comptime.zig → test/cases/compile_errors/indexing_a_undefined_slice_at_comptime.zig
@@ -4,7 +4,7 @@ comptime {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:3:10: error: index 0 outside slice of size 0
+// :3:10: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/obj/integer_cast_truncates_bits.zig → test/cases/compile_errors/integer_cast_truncates_bits.zig
@@ -20,12 +20,12 @@ export fn entry4() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:3:18: error: cast from 'u16' to 'u8' truncates bits
-// tmp.zig:8:22: error: integer value 300 cannot be coerced to type 'u8'
-// tmp.zig:13:20: error: expected type 'u8', found 'u16'
-// tmp.zig:13:20: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
-// tmp.zig:18:25: error: expected type 'u64', found 'i8'
-// tmp.zig:18:25: note: unsigned 64-bit int cannot represent all possible signed 8-bit values
+// :3:31: error: type 'u8' cannot represent integer value '300'
+// :8:22: error: type 'u8' cannot represent integer value '300'
+// :13:20: error: expected type 'u8', found 'u16'
+// :13:20: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
+// :18:25: error: expected type 'u64', found 'i8'
+// :18:25: note: unsigned 64-bit int cannot represent all possible signed 8-bit values
test/cases/compile_errors/stage1/obj/issue_4207_coerce_from_non-terminated-slice_to_terminated-pointer.zig → test/cases/compile_errors/issue_4207_coerce_from_non-terminated-slice_to_terminated-pointer.zig
@@ -4,8 +4,9 @@ export fn foo() [*:0]const u8 {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
// :3:18: error: expected type '[*:0]const u8', found '*[64]u8'
-// :3:18: note: destination pointer requires a terminating '0' sentinel
+// :3:18: note: destination pointer requires '0' sentinel
+// :1:18: note: function return type declared here
test/cases/compile_errors/stage1/obj/issue_7810-comptime_slice-len_increment_beyond_bounds.zig → test/cases/compile_errors/issue_7810-comptime_slice-len_increment_beyond_bounds.zig
@@ -1,14 +1,14 @@
export fn foo_slice_len_increment_beyond_bounds() void {
comptime {
var buf_storage: [8]u8 = undefined;
- var buf: []const u8 = buf_storage[0..];
+ var buf: []u8 = buf_storage[0..];
buf.len += 1;
buf[8] = 42;
}
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// :6:12: error: out of bounds slice
+// :6:16: error: comptime store of index 8 out of bounds of array length 8
test/cases/compile_errors/stage1/obj/lazy_pointer_with_undefined_element_type.zig → test/cases/compile_errors/lazy_pointer_with_undefined_element_type.zig
@@ -6,7 +6,7 @@ export fn foo() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
// :3:28: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/obj/missing_result_type_for_phi_node.zig → test/cases/compile_errors/missing_result_type_for_phi_node.zig
@@ -6,7 +6,7 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:5:17: error: integer value 0 cannot be coerced to type 'void'
+// :5:11: error: incompatible types: 'void' and 'comptime_int'
test/cases/compile_errors/stage1/obj/noalias_on_non_pointer_param.zig → test/cases/compile_errors/noalias_on_non_pointer_param.zig
@@ -2,7 +2,7 @@ fn f(noalias x: i32) void { _ = x; }
export fn entry() void { f(1234); }
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:1:6: error: noalias on non-pointer parameter
+// :1:6: error: non-pointer parameter declared noalias
test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig
@@ -0,0 +1,14 @@
+export fn entry() void {
+ testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
+}
+fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(8) i32, answer: i32) void {
+ if (ptr() != answer) unreachable;
+}
+fn alignedSmall() align(4) i32 { return 1234; }
+
+// error
+// backend=stage2
+// target=x86_64-linux
+//
+// :2:35: error: expected type '*const fn() align(8) i32', found '*const fn() align(4) i32'
+// :2:35: note: pointer alignment '4' cannot cast into pointer alignment '8'
test/cases/compile_errors/stage1/obj/reify_type_for_union_with_opaque_field.zig → test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig
@@ -13,7 +13,8 @@ export fn entry() usize {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:1:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions
+// :1:18: error: opaque types have unknown size and therefore cannot be directly embedded in unions
+// :6:45: note: opaque declared here
test/cases/compile_errors/stage1/obj/runtime_assignment_to_comptime_struct_type.zig → test/cases/compile_errors/runtime_assignment_to_comptime_struct_type.zig
@@ -9,7 +9,8 @@ export fn f() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:7:23: error: unable to evaluate constant expression
+// :7:30: error: unable to resolve comptime value
+// :7:30: note: initializer of comptime only struct must be comptime-known
test/cases/compile_errors/stage1/obj/runtime_assignment_to_comptime_union_type.zig → test/cases/compile_errors/runtime_assignment_to_comptime_union_type.zig
@@ -9,7 +9,8 @@ export fn f() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:7:23: error: unable to evaluate constant expression
+// :7:30: error: unable to resolve comptime value
+// :7:30: note: initializer of comptime only union must be comptime-known
test/cases/compile_errors/stage1/obj/saturating_shl_assign_does_not_allow_negative_rhs_at_comptime.zig → test/cases/compile_errors/saturating_shl_assign_does_not_allow_negative_rhs_at_comptime.zig
@@ -6,7 +6,7 @@ export fn a() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// error: shift by negative value -2
+// :4:14: error: shift by negative amount '-2'
test/cases/compile_errors/stage1/obj/saturating_shl_does_not_allow_negative_rhs_at_comptime.zig → test/cases/compile_errors/saturating_shl_does_not_allow_negative_rhs_at_comptime.zig
@@ -3,7 +3,7 @@ export fn a() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// error: shift by negative value -2
+// :2:25: error: shift by negative amount '-2'
test/cases/compile_errors/shift_amount_has_to_be_an_integer_type.zig
@@ -0,0 +1,10 @@
+export fn entry() void {
+ const x = 1 << &@as(u8, 10);
+ _ = x;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:20: error: expected type 'comptime_int', found '*const u8'
test/cases/compile_errors/stage1/obj/shift_by_negative_comptime_integer.zig → test/cases/compile_errors/shift_by_negative_comptime_integer.zig
@@ -4,7 +4,7 @@ comptime {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:18: error: shift by negative value -1
+// :2:18: error: shift by negative amount '-1'
test/cases/compile_errors/slice_sentinel_mismatch-1.zig
@@ -0,0 +1,11 @@
+export fn entry() void {
+ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
+ _ = y;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:29: error: expected type '[:1]const u8', found '*const [2:2]u8'
+// :2:29: note: pointer sentinel '2' cannot cast into pointer sentinel '1'
test/cases/compile_errors/stage1/obj/union_auto-enum_value_already_taken.zig → test/cases/compile_errors/union_auto-enum_value_already_taken.zig
@@ -11,8 +11,8 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:6:9: error: enum tag value 60 already taken
-// tmp.zig:4:9: note: other occurrence here
+// :6:5: error: enum tag value 60 already taken
+// :4:5: note: other occurrence here
test/cases/compile_errors/stage1/obj/union_enum_field_does_not_match_enum.zig → test/cases/compile_errors/union_enum_field_does_not_match_enum.zig
@@ -15,8 +15,8 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:10:5: error: enum field not found: 'D'
-// tmp.zig:1:16: note: enum declared here
+// :10:5: error: no field named 'D' in enum 'tmp.Letter'
+// :1:16: note: enum declared here
test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig
@@ -0,0 +1,16 @@
+const U = union(enum(i2)) {
+ A: u8,
+ B: u8,
+ C: u8,
+ D: u8,
+};
+export fn entry() void {
+ _ = U{ .D = 1 };
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :1:22: error: specified integer tag type cannot represent every field
+// :1:22: note: type 'i2' cannot fit values in range 0...3
test/cases/compile_errors/stage1/obj/union_with_too_small_explicit_unsigned_tag_type.zig → test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig
@@ -10,8 +10,8 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:1:22: error: specified integer tag type cannot represent every field
-// tmp.zig:1:22: note: type u2 cannot fit values in range 0...4
+// :1:22: error: specified integer tag type cannot represent every field
+// :1:22: note: type 'u2' cannot fit values in range 0...4
test/cases/compile_errors/stage1/obj/wrong_function_type.zig → test/cases/compile_errors/wrong_function_type.zig
@@ -5,7 +5,8 @@ fn c() i32 {return 2;}
export fn entry() usize { return @sizeOf(@TypeOf(fns)); }
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:1:28: error: expected type 'fn() void', found 'fn() i32'
+// :1:28: error: expected type 'fn() void', found 'fn() i32'
+// :1:28: note: return type 'i32' cannot cast into return type 'void'