authorgravatar for der.teufel.mail@gmail.comKrzysztof Wolicki <der.teufel.mail@gmail.com> 2022-08-18 14:10:47+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-18 14:10:47+02:00
log3ed9cdc1cc848119d857c8e88b17cc3698eaedac
treefb191657475cbee057f017f7c55e411a0740c8b2
parent656b9429d05c4aad2d514e6d4df15326d903e3f4
parentdf507edffe6c1087b5f4786cb64ccaffd02b6848
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge branch 'ziglang:master' into master


21 files changed, 249 insertions(+), 134 deletions(-)

ci/azure/pipelines.yml+1-1
......@@ -103,7 +103,7 @@ jobs:
103103 #& "$ZIGINSTALLDIR\bin\zig.exe" test "..\test\behavior.zig" -fno-stage1 -fLLVM -I "..\test" 2>&1
104104 #CheckLastExitCode
105105
106 & "$ZIGINSTALLDIR\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests 2>&1
106 & "$ZIGINSTALLDIR\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests -Domit-stage2 2>&1
107107 CheckLastExitCode
108108 & "$ZIGINSTALLDIR\bin\zig.exe" build test-std -Dskip-non-native 2>&1
109109 CheckLastExitCode
lib/std/os.zig+1
......@@ -2651,6 +2651,7 @@ pub fn renameatW(
26512651 .creation = windows.FILE_OPEN,
26522652 .io_mode = .blocking,
26532653 .filter = .any, // This function is supposed to rename both files and directories.
2654 .follow_symlinks = false,
26542655 }) catch |err| switch (err) {
26552656 error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
26562657 else => |e| return e,
lib/std/pdb.zig+6-3
......@@ -310,6 +310,10 @@ pub const SymbolKind = enum(u16) {
310310
311311pub const TypeIndex = u32;
312312
313// TODO According to this header:
314// https://github.com/microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/include/cvinfo.h#L3722
315// we should define RecordPrefix as part of the ProcSym structure.
316// This might be important when we start generating PDB in self-hosted with our own PE linker.
313317pub const ProcSym = extern struct {
314318 Parent: u32,
315319 End: u32,
......@@ -321,8 +325,7 @@ pub const ProcSym = extern struct {
321325 CodeOffset: u32,
322326 Segment: u16,
323327 Flags: ProcSymFlags,
324 // following is a null terminated string
325 // Name: [*]u8,
328 Name: [1]u8, // null-terminated
326329};
327330
328331pub const ProcSymFlags = packed struct {
......@@ -693,7 +696,7 @@ pub const Pdb = struct {
693696 .S_LPROC32, .S_GPROC32 => {
694697 const proc_sym = @ptrCast(*align(1) ProcSym, &module.symbols[symbol_i + @sizeOf(RecordPrefix)]);
695698 if (address >= proc_sym.CodeOffset and address < proc_sym.CodeOffset + proc_sym.CodeSize) {
696 return mem.sliceTo(@ptrCast([*:0]u8, proc_sym) + @sizeOf(ProcSym), 0);
699 return mem.sliceTo(@ptrCast([*:0]u8, &proc_sym.Name[0]), 0);
697700 }
698701 },
699702 else => {},
lib/std/zig/system/NativePaths.zig+2
......@@ -109,6 +109,8 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
109109
110110 if (native_target.os.tag != .windows) {
111111 const triple = try native_target.linuxTriple(allocator);
112 defer allocator.free(triple);
113
112114 const qual = native_target.cpu.arch.ptrBitWidth();
113115
114116 // TODO: $ ld --verbose | grep SEARCH_DIR
src/Sema.zig+52-19
......@@ -1495,7 +1495,8 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
14951495
14961496 // Finally, the last section of indexes refers to the map of ZIR=>AIR.
14971497 const inst = sema.inst_map.get(@intCast(u32, i)).?;
1498 if (sema.typeOf(inst).tag() == .generic_poison) return error.GenericPoison;
1498 const ty = sema.typeOf(inst);
1499 if (ty.tag() == .generic_poison) return error.GenericPoison;
14991500 return inst;
15001501}
15011502
......@@ -5570,11 +5571,15 @@ const GenericCallAdapter = struct {
55705571 generic_fn: *Module.Fn,
55715572 precomputed_hash: u64,
55725573 func_ty_info: Type.Payload.Function.Data,
5573 /// Unlike comptime_args, the Type here is not always present.
5574 /// .generic_poison is used to communicate non-anytype parameters.
5575 comptime_tvs: []const TypedValue,
5574 args: []const Arg,
55765575 module: *Module,
55775576
5577 const Arg = struct {
5578 ty: Type,
5579 val: Value,
5580 is_anytype: bool,
5581 };
5582
55785583 pub fn eql(ctx: @This(), adapted_key: void, other_key: *Module.Fn) bool {
55795584 _ = adapted_key;
55805585 // The generic function Decl is guaranteed to be the first dependency
......@@ -5585,10 +5590,10 @@ const GenericCallAdapter = struct {
55855590
55865591 const other_comptime_args = other_key.comptime_args.?;
55875592 for (other_comptime_args[0..ctx.func_ty_info.param_types.len]) |other_arg, i| {
5588 const this_arg = ctx.comptime_tvs[i];
5593 const this_arg = ctx.args[i];
55895594 const this_is_comptime = this_arg.val.tag() != .generic_poison;
55905595 const other_is_comptime = other_arg.val.tag() != .generic_poison;
5591 const this_is_anytype = this_arg.ty.tag() != .generic_poison;
5596 const this_is_anytype = this_arg.is_anytype;
55925597 const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i));
55935598
55945599 if (other_is_anytype != this_is_anytype) return false;
......@@ -5607,7 +5612,17 @@ const GenericCallAdapter = struct {
56075612 }
56085613 } else if (this_is_comptime) {
56095614 // Both are comptime parameters but not anytype parameters.
5610 if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.module)) {
5615 // We assert no error is possible here because any lazy values must be resolved
5616 // before inserting into the generic function hash map.
5617 const is_eql = Value.eqlAdvanced(
5618 this_arg.val,
5619 this_arg.ty,
5620 other_arg.val,
5621 other_arg.ty,
5622 ctx.module,
5623 null,
5624 ) catch unreachable;
5625 if (!is_eql) {
56115626 return false;
56125627 }
56135628 }
......@@ -6258,8 +6273,7 @@ fn instantiateGenericCall(
62586273 var hasher = std.hash.Wyhash.init(0);
62596274 std.hash.autoHash(&hasher, @ptrToInt(module_fn));
62606275
6261 const comptime_tvs = try sema.arena.alloc(TypedValue, func_ty_info.param_types.len);
6262
6276 const generic_args = try sema.arena.alloc(GenericCallAdapter.Arg, func_ty_info.param_types.len);
62636277 {
62646278 var i: usize = 0;
62656279 for (fn_info.param_body) |inst| {
......@@ -6283,8 +6297,9 @@ fn instantiateGenericCall(
62836297 else => continue,
62846298 }
62856299
6300 const arg_ty = sema.typeOf(uncasted_args[i]);
6301
62866302 if (is_comptime) {
6287 const arg_ty = sema.typeOf(uncasted_args[i]);
62886303 const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {
62896304 error.NeededSourceLocation => {
62906305 const decl = sema.mod.declPtr(block.src_decl);
......@@ -6297,27 +6312,30 @@ fn instantiateGenericCall(
62976312 arg_val.hash(arg_ty, &hasher, mod);
62986313 if (is_anytype) {
62996314 arg_ty.hashWithHasher(&hasher, mod);
6300 comptime_tvs[i] = .{
6315 generic_args[i] = .{
63016316 .ty = arg_ty,
63026317 .val = arg_val,
6318 .is_anytype = true,
63036319 };
63046320 } else {
6305 comptime_tvs[i] = .{
6306 .ty = Type.initTag(.generic_poison),
6321 generic_args[i] = .{
6322 .ty = arg_ty,
63076323 .val = arg_val,
6324 .is_anytype = false,
63086325 };
63096326 }
63106327 } else if (is_anytype) {
6311 const arg_ty = sema.typeOf(uncasted_args[i]);
63126328 arg_ty.hashWithHasher(&hasher, mod);
6313 comptime_tvs[i] = .{
6329 generic_args[i] = .{
63146330 .ty = arg_ty,
63156331 .val = Value.initTag(.generic_poison),
6332 .is_anytype = true,
63166333 };
63176334 } else {
6318 comptime_tvs[i] = .{
6319 .ty = Type.initTag(.generic_poison),
6335 generic_args[i] = .{
6336 .ty = arg_ty,
63206337 .val = Value.initTag(.generic_poison),
6338 .is_anytype = false,
63216339 };
63226340 }
63236341
......@@ -6331,7 +6349,7 @@ fn instantiateGenericCall(
63316349 .generic_fn = module_fn,
63326350 .precomputed_hash = precomputed_hash,
63336351 .func_ty_info = func_ty_info,
6334 .comptime_tvs = comptime_tvs,
6352 .args = generic_args,
63356353 .module = mod,
63366354 };
63376355 const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);
......@@ -11184,6 +11202,21 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1118411202 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
1118511203 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
1118611204
11205 if ((lhs_ty.zigTypeTag() == .ComptimeFloat and rhs_ty.zigTypeTag() == .ComptimeInt) or
11206 (lhs_ty.zigTypeTag() == .ComptimeInt and rhs_ty.zigTypeTag() == .ComptimeFloat))
11207 {
11208 // If it makes a difference whether we coerce to ints or floats before doing the division, error.
11209 // If lhs % rhs is 0, it doesn't matter.
11210 const lhs_val = maybe_lhs_val orelse unreachable;
11211 const rhs_val = maybe_rhs_val orelse unreachable;
11212 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable;
11213 if (rem.compareWithZero(.neq)) {
11214 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
11215 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
11216 });
11217 }
11218 }
11219
1118711220 // TODO: emit compile error when .div is used on integers and there would be an
1118811221 // ambiguous result between div_floor and div_trunc.
1118911222
......@@ -30124,7 +30157,7 @@ fn valuesEqual(
3012430157 rhs: Value,
3012530158 ty: Type,
3012630159) CompileError!bool {
30127 return Value.eqlAdvanced(lhs, rhs, ty, sema.mod, sema.kit(block, src));
30160 return Value.eqlAdvanced(lhs, ty, rhs, ty, sema.mod, sema.kit(block, src));
3012830161}
3012930162
3013030163/// Asserts the values are comparable vectors of type `ty`.
src/value.zig+54-23
......@@ -2004,6 +2004,10 @@ pub const Value = extern union {
20042004 return (try orderAgainstZeroAdvanced(lhs, sema_kit)).compare(op);
20052005 }
20062006
2007 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
2008 return eqlAdvanced(a, ty, b, ty, mod, null) catch unreachable;
2009 }
2010
20072011 /// This function is used by hash maps and so treats floating-point NaNs as equal
20082012 /// to each other, and not equal to other floating-point values.
20092013 /// Similarly, it treats `undef` as a distinct value from all other values.
......@@ -2012,13 +2016,10 @@ pub const Value = extern union {
20122016 /// for `a`. This function must act *as if* `a` has been coerced to `ty`. This complication
20132017 /// is required in order to make generic function instantiation efficient - specifically
20142018 /// the insertion into the monomorphized function table.
2015 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
2016 return eqlAdvanced(a, b, ty, mod, null) catch unreachable;
2017 }
2018
20192019 /// If `null` is provided for `sema_kit` then it is guaranteed no error will be returned.
20202020 pub fn eqlAdvanced(
20212021 a: Value,
2022 a_ty: Type,
20222023 b: Value,
20232024 ty: Type,
20242025 mod: *Module,
......@@ -2044,33 +2045,34 @@ pub const Value = extern union {
20442045 const a_payload = a.castTag(.opt_payload).?.data;
20452046 const b_payload = b.castTag(.opt_payload).?.data;
20462047 var buffer: Type.Payload.ElemType = undefined;
2047 return eqlAdvanced(a_payload, b_payload, ty.optionalChild(&buffer), mod, sema_kit);
2048 const payload_ty = ty.optionalChild(&buffer);
2049 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, sema_kit);
20482050 },
20492051 .slice => {
20502052 const a_payload = a.castTag(.slice).?.data;
20512053 const b_payload = b.castTag(.slice).?.data;
2052 if (!(try eqlAdvanced(a_payload.len, b_payload.len, Type.usize, mod, sema_kit))) {
2054 if (!(try eqlAdvanced(a_payload.len, Type.usize, b_payload.len, Type.usize, mod, sema_kit))) {
20532055 return false;
20542056 }
20552057
20562058 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
20572059 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
20582060
2059 return eqlAdvanced(a_payload.ptr, b_payload.ptr, ptr_ty, mod, sema_kit);
2061 return eqlAdvanced(a_payload.ptr, ptr_ty, b_payload.ptr, ptr_ty, mod, sema_kit);
20602062 },
20612063 .elem_ptr => {
20622064 const a_payload = a.castTag(.elem_ptr).?.data;
20632065 const b_payload = b.castTag(.elem_ptr).?.data;
20642066 if (a_payload.index != b_payload.index) return false;
20652067
2066 return eqlAdvanced(a_payload.array_ptr, b_payload.array_ptr, ty, mod, sema_kit);
2068 return eqlAdvanced(a_payload.array_ptr, ty, b_payload.array_ptr, ty, mod, sema_kit);
20672069 },
20682070 .field_ptr => {
20692071 const a_payload = a.castTag(.field_ptr).?.data;
20702072 const b_payload = b.castTag(.field_ptr).?.data;
20712073 if (a_payload.field_index != b_payload.field_index) return false;
20722074
2073 return eqlAdvanced(a_payload.container_ptr, b_payload.container_ptr, ty, mod, sema_kit);
2075 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, sema_kit);
20742076 },
20752077 .@"error" => {
20762078 const a_name = a.castTag(.@"error").?.data.name;
......@@ -2080,7 +2082,8 @@ pub const Value = extern union {
20802082 .eu_payload => {
20812083 const a_payload = a.castTag(.eu_payload).?.data;
20822084 const b_payload = b.castTag(.eu_payload).?.data;
2083 return eqlAdvanced(a_payload, b_payload, ty.errorUnionPayload(), mod, sema_kit);
2085 const payload_ty = ty.errorUnionPayload();
2086 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, sema_kit);
20842087 },
20852088 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
20862089 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
......@@ -2098,7 +2101,7 @@ pub const Value = extern union {
20982101 const types = ty.tupleFields().types;
20992102 assert(types.len == a_field_vals.len);
21002103 for (types) |field_ty, i| {
2101 if (!(try eqlAdvanced(a_field_vals[i], b_field_vals[i], field_ty, mod, sema_kit))) {
2104 if (!(try eqlAdvanced(a_field_vals[i], field_ty, b_field_vals[i], field_ty, mod, sema_kit))) {
21022105 return false;
21032106 }
21042107 }
......@@ -2109,7 +2112,7 @@ pub const Value = extern union {
21092112 const fields = ty.structFields().values();
21102113 assert(fields.len == a_field_vals.len);
21112114 for (fields) |field, i| {
2112 if (!(try eqlAdvanced(a_field_vals[i], b_field_vals[i], field.ty, mod, sema_kit))) {
2115 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, sema_kit))) {
21132116 return false;
21142117 }
21152118 }
......@@ -2120,7 +2123,7 @@ pub const Value = extern union {
21202123 for (a_field_vals) |a_elem, i| {
21212124 const b_elem = b_field_vals[i];
21222125
2123 if (!(try eqlAdvanced(a_elem, b_elem, elem_ty, mod, sema_kit))) {
2126 if (!(try eqlAdvanced(a_elem, elem_ty, b_elem, elem_ty, mod, sema_kit))) {
21242127 return false;
21252128 }
21262129 }
......@@ -2132,7 +2135,7 @@ pub const Value = extern union {
21322135 switch (ty.containerLayout()) {
21332136 .Packed, .Extern => {
21342137 const tag_ty = ty.unionTagTypeHypothetical();
2135 if (!(try a_union.tag.eqlAdvanced(b_union.tag, tag_ty, mod, sema_kit))) {
2138 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, sema_kit))) {
21362139 // In this case, we must disregard mismatching tags and compare
21372140 // based on the in-memory bytes of the payloads.
21382141 @panic("TODO comptime comparison of extern union values with mismatching tags");
......@@ -2140,13 +2143,13 @@ pub const Value = extern union {
21402143 },
21412144 .Auto => {
21422145 const tag_ty = ty.unionTagTypeHypothetical();
2143 if (!(try a_union.tag.eqlAdvanced(b_union.tag, tag_ty, mod, sema_kit))) {
2146 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, sema_kit))) {
21442147 return false;
21452148 }
21462149 },
21472150 }
21482151 const active_field_ty = ty.unionFieldType(a_union.tag, mod);
2149 return a_union.val.eqlAdvanced(b_union.val, active_field_ty, mod, sema_kit);
2152 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, sema_kit);
21502153 },
21512154 else => {},
21522155 } else if (a_tag == .null_value or b_tag == .null_value) {
......@@ -2180,7 +2183,7 @@ pub const Value = extern union {
21802183 const b_val = b.enumToInt(ty, &buf_b);
21812184 var buf_ty: Type.Payload.Bits = undefined;
21822185 const int_ty = ty.intTagType(&buf_ty);
2183 return eqlAdvanced(a_val, b_val, int_ty, mod, sema_kit);
2186 return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, sema_kit);
21842187 },
21852188 .Array, .Vector => {
21862189 const len = ty.arrayLen();
......@@ -2191,17 +2194,44 @@ pub const Value = extern union {
21912194 while (i < len) : (i += 1) {
21922195 const a_elem = elemValueBuffer(a, mod, i, &a_buf);
21932196 const b_elem = elemValueBuffer(b, mod, i, &b_buf);
2194 if (!(try eqlAdvanced(a_elem, b_elem, elem_ty, mod, sema_kit))) {
2197 if (!(try eqlAdvanced(a_elem, elem_ty, b_elem, elem_ty, mod, sema_kit))) {
21952198 return false;
21962199 }
21972200 }
21982201 return true;
21992202 },
22002203 .Struct => {
2201 // A tuple can be represented with .empty_struct_value,
2202 // the_one_possible_value, .aggregate in which case we could
2203 // end up here and the values are equal if the type has zero fields.
2204 return ty.isTupleOrAnonStruct() and ty.structFieldCount() != 0;
2204 // A struct can be represented with one of:
2205 // .empty_struct_value,
2206 // .the_one_possible_value,
2207 // .aggregate,
2208 // Note that we already checked above for matching tags, e.g. both .aggregate.
2209 return ty.onePossibleValue() != null;
2210 },
2211 .Union => {
2212 // Here we have to check for value equality, as-if `a` has been coerced to `ty`.
2213 if (ty.onePossibleValue() != null) {
2214 return true;
2215 }
2216 if (a_ty.castTag(.anon_struct)) |payload| {
2217 const tuple = payload.data;
2218 if (tuple.values.len != 1) {
2219 return false;
2220 }
2221 const field_name = tuple.names[0];
2222 const union_obj = ty.cast(Type.Payload.Union).?.data;
2223 const field_index = union_obj.fields.getIndex(field_name) orelse return false;
2224 const tag_and_val = b.castTag(.@"union").?.data;
2225 var field_tag_buf: Value.Payload.U32 = .{
2226 .base = .{ .tag = .enum_field_index },
2227 .data = @intCast(u32, field_index),
2228 };
2229 const field_tag = Value.initPayload(&field_tag_buf.base);
2230 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, mod);
2231 if (!tag_matches) return false;
2232 return eqlAdvanced(tag_and_val.val, union_obj.tag_ty, tuple.values[0], tuple.types[0], mod, sema_kit);
2233 }
2234 return false;
22052235 },
22062236 .Float => {
22072237 switch (ty.floatBits(target)) {
......@@ -2230,7 +2260,8 @@ pub const Value = extern union {
22302260 .base = .{ .tag = .opt_payload },
22312261 .data = a,
22322262 };
2233 return eqlAdvanced(Value.initPayload(&buffer.base), b, ty, mod, sema_kit);
2263 const opt_val = Value.initPayload(&buffer.base);
2264 return eqlAdvanced(opt_val, ty, b, ty, mod, sema_kit);
22342265 }
22352266 },
22362267 else => {},
test/behavior/floatop.zig+4-4
......@@ -194,8 +194,8 @@ fn testSin() !void {
194194 const eps = epsForType(ty);
195195 try expect(@sin(@as(ty, 0)) == 0);
196196 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));
197 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps));
198 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
197 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2.0)), 1, eps));
198 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
199199 }
200200
201201 {
......@@ -228,8 +228,8 @@ fn testCos() !void {
228228 const eps = epsForType(ty);
229229 try expect(@cos(@as(ty, 0)) == 1);
230230 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));
231 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps));
232 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
231 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2.0)), 0, eps));
232 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
233233 }
234234
235235 {
test/behavior/generics.zig+19
......@@ -323,3 +323,22 @@ test "generic function instantiation non-duplicates" {
323323 S.copy(u8, &buffer, "hello");
324324 S.copy(u8, &buffer, "hello2");
325325}
326
327test "generic instantiation of tagged union with only one field" {
328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
330 if (builtin.os.tag == .wasi) return error.SkipZigTest;
331
332 const S = struct {
333 const U = union(enum) {
334 s: []const u8,
335 };
336
337 fn foo(comptime u: U) usize {
338 return u.s.len;
339 }
340 };
341
342 try expect(S.foo(.{ .s = "a" }) == 1);
343 try expect(S.foo(.{ .s = "ab" }) == 2);
344}
test/cases/compile_errors/ambiguous_coercion_of_division_operands.zig created+23
......@@ -0,0 +1,23 @@
1export fn entry1() void {
2 var f: f32 = 54.0 / 5;
3 _ = f;
4}
5export fn entry2() void {
6 var f: f32 = 54 / 5.0;
7 _ = f;
8}
9export fn entry3() void {
10 var f: f32 = 55.0 / 5;
11 _ = f;
12}
13export fn entry4() void {
14 var f: f32 = 55 / 5.0;
15 _ = f;
16}
17
18// error
19// backend=stage2
20// target=native
21//
22// :2:23: error: ambiguous coercion of division operands 'comptime_float' and 'comptime_int'; non-zero remainder '4'
23// :6:21: error: ambiguous coercion of division operands 'comptime_int' and 'comptime_float'; non-zero remainder '4'
test/link.zig+30-30
......@@ -3,11 +3,6 @@ const builtin = @import("builtin");
33const tests = @import("tests.zig");
44
55pub fn addCases(cases: *tests.StandaloneContext) void {
6 if (builtin.os.tag == .windows) {
7 // https://github.com/ziglang/zig/issues/12421
8 return;
9 }
10
116 cases.addBuildFile("test/link/bss/build.zig", .{
127 .build_modes = false, // we only guarantee zerofill for undefined in Debug
138 });
......@@ -28,11 +23,12 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
2823 .build_modes = true,
2924 });
3025
31 cases.addBuildFile("test/link/tls/build.zig", .{
32 .build_modes = true,
33 });
26 addWasmCases(cases);
27 addMachOCases(cases);
28}
3429
35 cases.addBuildFile("test/link/wasm/type/build.zig", .{
30fn addWasmCases(cases: *tests.StandaloneContext) void {
31 cases.addBuildFile("test/link/wasm/bss/build.zig", .{
3632 .build_modes = true,
3733 .requires_stage2 = true,
3834 });
......@@ -47,23 +43,13 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
4743 .requires_stage2 = true,
4844 });
4945
50 cases.addBuildFile("test/link/wasm/bss/build.zig", .{
46 cases.addBuildFile("test/link/wasm/type/build.zig", .{
5147 .build_modes = true,
5248 .requires_stage2 = true,
5349 });
50}
5451
55 cases.addBuildFile("test/link/macho/entry/build.zig", .{
56 .build_modes = true,
57 });
58
59 cases.addBuildFile("test/link/macho/pagezero/build.zig", .{
60 .build_modes = false,
61 });
62
63 cases.addBuildFile("test/link/macho/dylib/build.zig", .{
64 .build_modes = true,
65 });
66
52fn addMachOCases(cases: *tests.StandaloneContext) void {
6753 cases.addBuildFile("test/link/macho/dead_strip/build.zig", .{
6854 .build_modes = false,
6955 });
......@@ -73,45 +59,59 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
7359 .requires_macos_sdk = true,
7460 });
7561
76 cases.addBuildFile("test/link/macho/needed_library/build.zig", .{
62 cases.addBuildFile("test/link/macho/dylib/build.zig", .{
7763 .build_modes = true,
7864 });
7965
80 cases.addBuildFile("test/link/macho/weak_library/build.zig", .{
66 cases.addBuildFile("test/link/macho/entry/build.zig", .{
8167 .build_modes = true,
8268 });
8369
84 cases.addBuildFile("test/link/macho/needed_framework/build.zig", .{
70 cases.addBuildFile("test/link/macho/headerpad/build.zig", .{
8571 .build_modes = true,
8672 .requires_macos_sdk = true,
8773 });
8874
89 cases.addBuildFile("test/link/macho/weak_framework/build.zig", .{
75 cases.addBuildFile("test/link/macho/needed_framework/build.zig", .{
9076 .build_modes = true,
9177 .requires_macos_sdk = true,
9278 });
9379
94 // Try to build and run an Objective-C executable.
80 cases.addBuildFile("test/link/macho/needed_library/build.zig", .{
81 .build_modes = true,
82 });
83
9584 cases.addBuildFile("test/link/macho/objc/build.zig", .{
9685 .build_modes = true,
9786 .requires_macos_sdk = true,
9887 });
9988
100 // Try to build and run an Objective-C++ executable.
10189 cases.addBuildFile("test/link/macho/objcpp/build.zig", .{
10290 .build_modes = true,
10391 .requires_macos_sdk = true,
10492 });
10593
94 cases.addBuildFile("test/link/macho/pagezero/build.zig", .{
95 .build_modes = false,
96 });
97
98 cases.addBuildFile("test/link/macho/search_strategy/build.zig", .{
99 .build_modes = true,
100 });
101
106102 cases.addBuildFile("test/link/macho/stack_size/build.zig", .{
107103 .build_modes = true,
108104 });
109105
110 cases.addBuildFile("test/link/macho/search_strategy/build.zig", .{
106 cases.addBuildFile("test/link/macho/tls/build.zig", .{
111107 .build_modes = true,
112108 });
113109
114 cases.addBuildFile("test/link/macho/headerpad/build.zig", .{
110 cases.addBuildFile("test/link/macho/weak_library/build.zig", .{
111 .build_modes = true,
112 });
113
114 cases.addBuildFile("test/link/macho/weak_framework/build.zig", .{
115115 .build_modes = true,
116116 .requires_macos_sdk = true,
117117 });
test/link/macho/dead_strip/build.zig+5-3
......@@ -4,13 +4,14 @@ const LibExeObjectStep = std.build.LibExeObjStep;
44
55pub fn build(b: *Builder) void {
66 const mode = b.standardReleaseOptions();
7 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
78
89 const test_step = b.step("test", "Test the program");
910 test_step.dependOn(b.getInstallStep());
1011
1112 {
1213 // Without -dead_strip, we expect `iAmUnused` symbol present
13 const exe = createScenario(b, mode);
14 const exe = createScenario(b, mode, target);
1415
1516 const check = exe.checkObject(.macho);
1617 check.checkInSymtab();
......@@ -23,7 +24,7 @@ pub fn build(b: *Builder) void {
2324
2425 {
2526 // With -dead_strip, no `iAmUnused` symbol should be present
26 const exe = createScenario(b, mode);
27 const exe = createScenario(b, mode, target);
2728 exe.link_gc_sections = true;
2829
2930 const check = exe.checkObject(.macho);
......@@ -36,10 +37,11 @@ pub fn build(b: *Builder) void {
3637 }
3738}
3839
39fn createScenario(b: *Builder, mode: std.builtin.Mode) *LibExeObjectStep {
40fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
4041 const exe = b.addExecutable("test", null);
4142 exe.addCSourceFile("main.c", &[0][]const u8{});
4243 exe.setBuildMode(mode);
44 exe.setTarget(target);
4345 exe.linkLibC();
4446 return exe;
4547}
test/link/macho/pagezero/build.zig+3-2
......@@ -3,13 +3,14 @@ const Builder = std.build.Builder;
33
44pub fn build(b: *Builder) void {
55 const mode = b.standardReleaseOptions();
6 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
67
78 const test_step = b.step("test", "Test");
89 test_step.dependOn(b.getInstallStep());
910
1011 {
1112 const exe = b.addExecutable("pagezero", null);
12 exe.setTarget(.{ .os_tag = .macos });
13 exe.setTarget(target);
1314 exe.setBuildMode(mode);
1415 exe.addCSourceFile("main.c", &.{});
1516 exe.linkLibC();
......@@ -29,7 +30,7 @@ pub fn build(b: *Builder) void {
2930
3031 {
3132 const exe = b.addExecutable("no_pagezero", null);
32 exe.setTarget(.{ .os_tag = .macos });
33 exe.setTarget(target);
3334 exe.setBuildMode(mode);
3435 exe.addCSourceFile("main.c", &.{});
3536 exe.linkLibC();
test/link/macho/search_strategy/build.zig+4-4
......@@ -1,17 +1,17 @@
11const std = @import("std");
22const Builder = std.build.Builder;
33const LibExeObjectStep = std.build.LibExeObjStep;
4const target: std.zig.CrossTarget = .{ .os_tag = .macos };
54
65pub fn build(b: *Builder) void {
76 const mode = b.standardReleaseOptions();
7 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
88
99 const test_step = b.step("test", "Test");
1010 test_step.dependOn(b.getInstallStep());
1111
1212 {
1313 // -search_dylibs_first
14 const exe = createScenario(b, mode);
14 const exe = createScenario(b, mode, target);
1515 exe.search_strategy = .dylibs_first;
1616
1717 const check = exe.checkObject(.macho);
......@@ -26,7 +26,7 @@ pub fn build(b: *Builder) void {
2626
2727 {
2828 // -search_paths_first
29 const exe = createScenario(b, mode);
29 const exe = createScenario(b, mode, target);
3030 exe.search_strategy = .paths_first;
3131
3232 const run = std.build.EmulatableRunStep.create(b, "run", exe);
......@@ -36,7 +36,7 @@ pub fn build(b: *Builder) void {
3636 }
3737}
3838
39fn createScenario(b: *Builder, mode: std.builtin.Mode) *LibExeObjectStep {
39fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
4040 const static = b.addStaticLibrary("a", null);
4141 static.setTarget(target);
4242 static.setBuildMode(mode);
test/link/macho/stack_size/build.zig+2-1
......@@ -3,12 +3,13 @@ const Builder = std.build.Builder;
33
44pub fn build(b: *Builder) void {
55 const mode = b.standardReleaseOptions();
6 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
67
78 const test_step = b.step("test", "Test");
89 test_step.dependOn(b.getInstallStep());
910
1011 const exe = b.addExecutable("main", null);
11 exe.setTarget(.{ .os_tag = .macos });
12 exe.setTarget(target);
1213 exe.setBuildMode(mode);
1314 exe.addCSourceFile("main.c", &.{});
1415 exe.linkLibC();
test/link/macho/tls/a.c created+5
......@@ -0,0 +1,5 @@
1_Thread_local int a;
2
3int getA() {
4 return a;
5}
test/link/macho/tls/build.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2const Builder = std.build.Builder;
3
4pub fn build(b: *Builder) void {
5 const mode = b.standardReleaseOptions();
6 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
7
8 const lib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
9 lib.setBuildMode(mode);
10 lib.setTarget(target);
11 lib.addCSourceFile("a.c", &.{});
12 lib.linkLibC();
13
14 const test_exe = b.addTest("main.zig");
15 test_exe.setBuildMode(mode);
16 test_exe.setTarget(target);
17 test_exe.linkLibrary(lib);
18 test_exe.linkLibC();
19
20 const test_step = b.step("test", "Test it");
21 test_step.dependOn(&test_exe.step);
22}
test/link/macho/tls/main.zig created+15
......@@ -0,0 +1,15 @@
1const std = @import("std");
2
3extern threadlocal var a: i32;
4extern fn getA() i32;
5
6fn getA2() i32 {
7 return a;
8}
9
10test {
11 a = 2;
12 try std.testing.expect(getA() == 2);
13 try std.testing.expect(2 == getA2());
14 try std.testing.expect(getA() == getA2());
15}
test/link/tls/a.c deleted-5
......@@ -1,5 +0,0 @@
1_Thread_local int a;
2
3int getA() {
4 return a;
5}
test/link/tls/build.zig deleted-18
......@@ -1,18 +0,0 @@
1const Builder = @import("std").build.Builder;
2
3pub fn build(b: *Builder) void {
4 const mode = b.standardReleaseOptions();
5
6 const lib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
7 lib.setBuildMode(mode);
8 lib.addCSourceFile("a.c", &.{});
9 lib.linkLibC();
10
11 const test_exe = b.addTest("main.zig");
12 test_exe.setBuildMode(mode);
13 test_exe.linkLibrary(lib);
14 test_exe.linkLibC();
15
16 const test_step = b.step("test", "Test it");
17 test_step.dependOn(&test_exe.step);
18}
test/link/tls/main.zig deleted-15
......@@ -1,15 +0,0 @@
1const std = @import("std");
2
3extern threadlocal var a: i32;
4extern fn getA() i32;
5
6fn getA2() i32 {
7 return a;
8}
9
10test {
11 a = 2;
12 try std.testing.expect(getA() == 2);
13 try std.testing.expect(2 == getA2());
14 try std.testing.expect(getA() == getA2());
15}
test/stack_traces.zig+1-6
......@@ -3,11 +3,6 @@ const os = std.os;
33const tests = @import("tests.zig");
44
55pub fn addCases(cases: *tests.StackTracesContext) void {
6 if (@import("builtin").os.tag == .windows) {
7 // https://github.com/ziglang/zig/issues/12422
8 return;
9 }
10
116 cases.addCase(.{
127 .name = "return",
138 .source =
......@@ -178,7 +173,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
178173 cases.addCase(.{
179174 .exclude_os = .{
180175 .openbsd, // integer overflow
181 .windows,
176 .windows, // TODO intermittent failures
182177 },
183178 .name = "dumpCurrentStackTrace",
184179 .source =