Skip to content

Commit a3f2f60

Browse files
committed
std: remove meta.trait
In general, I don't like the idea of std.meta.trait, and so I am providing some guidance by deleting the entire namespace from the standard library and compiler codebase. My main criticism is that it's overcomplicated machinery that bloats compile times and is ultimately unnecessary given the existence of Zig's strong type system and reference traces. Users who want this can create a third party package that provides this functionality. closes #18051
1 parent 994e191 commit a3f2f60

23 files changed

+380
-965
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ set(ZIG_STAGE2_SOURCES
290290
"${CMAKE_SOURCE_DIR}/lib/std/mem/Allocator.zig"
291291
"${CMAKE_SOURCE_DIR}/lib/std/meta.zig"
292292
"${CMAKE_SOURCE_DIR}/lib/std/meta/trailer_flags.zig"
293-
"${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig"
294293
"${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig"
295294
"${CMAKE_SOURCE_DIR}/lib/std/os.zig"
296295
"${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig"

lib/std/array_hash_map.zig

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ const assert = debug.assert;
44
const testing = std.testing;
55
const math = std.math;
66
const mem = std.mem;
7-
const meta = std.meta;
8-
const trait = meta.trait;
97
const autoHash = std.hash.autoHash;
108
const Wyhash = std.hash.Wyhash;
119
const Allocator = mem.Allocator;
@@ -2341,13 +2339,13 @@ test "reIndex" {
23412339
test "auto store_hash" {
23422340
const HasCheapEql = AutoArrayHashMap(i32, i32);
23432341
const HasExpensiveEql = AutoArrayHashMap([32]i32, i32);
2344-
try testing.expect(meta.fieldInfo(HasCheapEql.Data, .hash).type == void);
2345-
try testing.expect(meta.fieldInfo(HasExpensiveEql.Data, .hash).type != void);
2342+
try testing.expect(std.meta.fieldInfo(HasCheapEql.Data, .hash).type == void);
2343+
try testing.expect(std.meta.fieldInfo(HasExpensiveEql.Data, .hash).type != void);
23462344

23472345
const HasCheapEqlUn = AutoArrayHashMapUnmanaged(i32, i32);
23482346
const HasExpensiveEqlUn = AutoArrayHashMapUnmanaged([32]i32, i32);
2349-
try testing.expect(meta.fieldInfo(HasCheapEqlUn.Data, .hash).type == void);
2350-
try testing.expect(meta.fieldInfo(HasExpensiveEqlUn.Data, .hash).type != void);
2347+
try testing.expect(std.meta.fieldInfo(HasCheapEqlUn.Data, .hash).type == void);
2348+
try testing.expect(std.meta.fieldInfo(HasExpensiveEqlUn.Data, .hash).type != void);
23512349
}
23522350

23532351
test "sort" {
@@ -2434,12 +2432,12 @@ pub fn getAutoHashFn(comptime K: type, comptime Context: type) (fn (Context, K)
24342432
return struct {
24352433
fn hash(ctx: Context, key: K) u32 {
24362434
_ = ctx;
2437-
if (comptime trait.hasUniqueRepresentation(K)) {
2438-
return @as(u32, @truncate(Wyhash.hash(0, std.mem.asBytes(&key))));
2435+
if (std.meta.hasUniqueRepresentation(K)) {
2436+
return @truncate(Wyhash.hash(0, std.mem.asBytes(&key)));
24392437
} else {
24402438
var hasher = Wyhash.init(0);
24412439
autoHash(&hasher, key);
2442-
return @as(u32, @truncate(hasher.final()));
2440+
return @truncate(hasher.final());
24432441
}
24442442
}
24452443
}.hash;
@@ -2450,7 +2448,7 @@ pub fn getAutoEqlFn(comptime K: type, comptime Context: type) (fn (Context, K, K
24502448
fn eql(ctx: Context, a: K, b: K, b_index: usize) bool {
24512449
_ = b_index;
24522450
_ = ctx;
2453-
return meta.eql(a, b);
2451+
return std.meta.eql(a, b);
24542452
}
24552453
}.eql;
24562454
}

lib/std/atomic/Atomic.zig

Lines changed: 130 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -153,163 +153,155 @@ pub fn Atomic(comptime T: type) type {
153153
return @atomicRmw(T, &self.value, op, value, ordering);
154154
}
155155

156-
fn exportWhen(comptime condition: bool, comptime functions: type) type {
157-
return if (condition) functions else struct {};
156+
pub inline fn fetchAdd(self: *Self, value: T, comptime ordering: Ordering) T {
157+
return self.rmw(.Add, value, ordering);
158158
}
159159

160-
pub usingnamespace exportWhen(std.meta.trait.isNumber(T), struct {
161-
pub inline fn fetchAdd(self: *Self, value: T, comptime ordering: Ordering) T {
162-
return self.rmw(.Add, value, ordering);
163-
}
164-
165-
pub inline fn fetchSub(self: *Self, value: T, comptime ordering: Ordering) T {
166-
return self.rmw(.Sub, value, ordering);
167-
}
160+
pub inline fn fetchSub(self: *Self, value: T, comptime ordering: Ordering) T {
161+
return self.rmw(.Sub, value, ordering);
162+
}
168163

169-
pub inline fn fetchMin(self: *Self, value: T, comptime ordering: Ordering) T {
170-
return self.rmw(.Min, value, ordering);
171-
}
164+
pub inline fn fetchMin(self: *Self, value: T, comptime ordering: Ordering) T {
165+
return self.rmw(.Min, value, ordering);
166+
}
172167

173-
pub inline fn fetchMax(self: *Self, value: T, comptime ordering: Ordering) T {
174-
return self.rmw(.Max, value, ordering);
175-
}
176-
});
168+
pub inline fn fetchMax(self: *Self, value: T, comptime ordering: Ordering) T {
169+
return self.rmw(.Max, value, ordering);
170+
}
177171

178-
pub usingnamespace exportWhen(std.meta.trait.isIntegral(T), struct {
179-
pub inline fn fetchAnd(self: *Self, value: T, comptime ordering: Ordering) T {
180-
return self.rmw(.And, value, ordering);
181-
}
172+
pub inline fn fetchAnd(self: *Self, value: T, comptime ordering: Ordering) T {
173+
return self.rmw(.And, value, ordering);
174+
}
182175

183-
pub inline fn fetchNand(self: *Self, value: T, comptime ordering: Ordering) T {
184-
return self.rmw(.Nand, value, ordering);
185-
}
176+
pub inline fn fetchNand(self: *Self, value: T, comptime ordering: Ordering) T {
177+
return self.rmw(.Nand, value, ordering);
178+
}
186179

187-
pub inline fn fetchOr(self: *Self, value: T, comptime ordering: Ordering) T {
188-
return self.rmw(.Or, value, ordering);
189-
}
180+
pub inline fn fetchOr(self: *Self, value: T, comptime ordering: Ordering) T {
181+
return self.rmw(.Or, value, ordering);
182+
}
190183

191-
pub inline fn fetchXor(self: *Self, value: T, comptime ordering: Ordering) T {
192-
return self.rmw(.Xor, value, ordering);
193-
}
184+
pub inline fn fetchXor(self: *Self, value: T, comptime ordering: Ordering) T {
185+
return self.rmw(.Xor, value, ordering);
186+
}
194187

195-
const Bit = std.math.Log2Int(T);
196-
const BitRmwOp = enum {
197-
Set,
198-
Reset,
199-
Toggle,
200-
};
188+
const Bit = std.math.Log2Int(T);
189+
const BitRmwOp = enum {
190+
Set,
191+
Reset,
192+
Toggle,
193+
};
201194

202-
pub inline fn bitSet(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
203-
return bitRmw(self, .Set, bit, ordering);
204-
}
195+
pub inline fn bitSet(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
196+
return bitRmw(self, .Set, bit, ordering);
197+
}
205198

206-
pub inline fn bitReset(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
207-
return bitRmw(self, .Reset, bit, ordering);
208-
}
199+
pub inline fn bitReset(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
200+
return bitRmw(self, .Reset, bit, ordering);
201+
}
209202

210-
pub inline fn bitToggle(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
211-
return bitRmw(self, .Toggle, bit, ordering);
212-
}
203+
pub inline fn bitToggle(self: *Self, bit: Bit, comptime ordering: Ordering) u1 {
204+
return bitRmw(self, .Toggle, bit, ordering);
205+
}
213206

214-
inline fn bitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 {
215-
// x86 supports dedicated bitwise instructions
216-
if (comptime builtin.target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) {
217-
// TODO: this causes std lib test failures when enabled
218-
if (false) {
219-
return x86BitRmw(self, op, bit, ordering);
220-
}
207+
inline fn bitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 {
208+
// x86 supports dedicated bitwise instructions
209+
if (comptime builtin.target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) {
210+
// TODO: this causes std lib test failures when enabled
211+
if (false) {
212+
return x86BitRmw(self, op, bit, ordering);
221213
}
214+
}
222215

223-
const mask = @as(T, 1) << bit;
224-
const value = switch (op) {
225-
.Set => self.fetchOr(mask, ordering),
226-
.Reset => self.fetchAnd(~mask, ordering),
227-
.Toggle => self.fetchXor(mask, ordering),
228-
};
216+
const mask = @as(T, 1) << bit;
217+
const value = switch (op) {
218+
.Set => self.fetchOr(mask, ordering),
219+
.Reset => self.fetchAnd(~mask, ordering),
220+
.Toggle => self.fetchXor(mask, ordering),
221+
};
229222

230-
return @intFromBool(value & mask != 0);
231-
}
223+
return @intFromBool(value & mask != 0);
224+
}
232225

233-
inline fn x86BitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 {
234-
const old_bit: u8 = switch (@sizeOf(T)) {
235-
2 => switch (op) {
236-
.Set => asm volatile ("lock btsw %[bit], %[ptr]"
237-
// LLVM doesn't support u1 flag register return values
238-
: [result] "={@ccc}" (-> u8),
239-
: [ptr] "*m" (&self.value),
240-
[bit] "X" (@as(T, bit)),
241-
: "cc", "memory"
242-
),
243-
.Reset => asm volatile ("lock btrw %[bit], %[ptr]"
244-
// LLVM doesn't support u1 flag register return values
245-
: [result] "={@ccc}" (-> u8),
246-
: [ptr] "*m" (&self.value),
247-
[bit] "X" (@as(T, bit)),
248-
: "cc", "memory"
249-
),
250-
.Toggle => asm volatile ("lock btcw %[bit], %[ptr]"
251-
// LLVM doesn't support u1 flag register return values
252-
: [result] "={@ccc}" (-> u8),
253-
: [ptr] "*m" (&self.value),
254-
[bit] "X" (@as(T, bit)),
255-
: "cc", "memory"
256-
),
257-
},
258-
4 => switch (op) {
259-
.Set => asm volatile ("lock btsl %[bit], %[ptr]"
260-
// LLVM doesn't support u1 flag register return values
261-
: [result] "={@ccc}" (-> u8),
262-
: [ptr] "*m" (&self.value),
263-
[bit] "X" (@as(T, bit)),
264-
: "cc", "memory"
265-
),
266-
.Reset => asm volatile ("lock btrl %[bit], %[ptr]"
267-
// LLVM doesn't support u1 flag register return values
268-
: [result] "={@ccc}" (-> u8),
269-
: [ptr] "*m" (&self.value),
270-
[bit] "X" (@as(T, bit)),
271-
: "cc", "memory"
272-
),
273-
.Toggle => asm volatile ("lock btcl %[bit], %[ptr]"
274-
// LLVM doesn't support u1 flag register return values
275-
: [result] "={@ccc}" (-> u8),
276-
: [ptr] "*m" (&self.value),
277-
[bit] "X" (@as(T, bit)),
278-
: "cc", "memory"
279-
),
280-
},
281-
8 => switch (op) {
282-
.Set => asm volatile ("lock btsq %[bit], %[ptr]"
283-
// LLVM doesn't support u1 flag register return values
284-
: [result] "={@ccc}" (-> u8),
285-
: [ptr] "*m" (&self.value),
286-
[bit] "X" (@as(T, bit)),
287-
: "cc", "memory"
288-
),
289-
.Reset => asm volatile ("lock btrq %[bit], %[ptr]"
290-
// LLVM doesn't support u1 flag register return values
291-
: [result] "={@ccc}" (-> u8),
292-
: [ptr] "*m" (&self.value),
293-
[bit] "X" (@as(T, bit)),
294-
: "cc", "memory"
295-
),
296-
.Toggle => asm volatile ("lock btcq %[bit], %[ptr]"
297-
// LLVM doesn't support u1 flag register return values
298-
: [result] "={@ccc}" (-> u8),
299-
: [ptr] "*m" (&self.value),
300-
[bit] "X" (@as(T, bit)),
301-
: "cc", "memory"
302-
),
303-
},
304-
else => @compileError("Invalid atomic type " ++ @typeName(T)),
305-
};
226+
inline fn x86BitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 {
227+
const old_bit: u8 = switch (@sizeOf(T)) {
228+
2 => switch (op) {
229+
.Set => asm volatile ("lock btsw %[bit], %[ptr]"
230+
// LLVM doesn't support u1 flag register return values
231+
: [result] "={@ccc}" (-> u8),
232+
: [ptr] "*m" (&self.value),
233+
[bit] "X" (@as(T, bit)),
234+
: "cc", "memory"
235+
),
236+
.Reset => asm volatile ("lock btrw %[bit], %[ptr]"
237+
// LLVM doesn't support u1 flag register return values
238+
: [result] "={@ccc}" (-> u8),
239+
: [ptr] "*m" (&self.value),
240+
[bit] "X" (@as(T, bit)),
241+
: "cc", "memory"
242+
),
243+
.Toggle => asm volatile ("lock btcw %[bit], %[ptr]"
244+
// LLVM doesn't support u1 flag register return values
245+
: [result] "={@ccc}" (-> u8),
246+
: [ptr] "*m" (&self.value),
247+
[bit] "X" (@as(T, bit)),
248+
: "cc", "memory"
249+
),
250+
},
251+
4 => switch (op) {
252+
.Set => asm volatile ("lock btsl %[bit], %[ptr]"
253+
// LLVM doesn't support u1 flag register return values
254+
: [result] "={@ccc}" (-> u8),
255+
: [ptr] "*m" (&self.value),
256+
[bit] "X" (@as(T, bit)),
257+
: "cc", "memory"
258+
),
259+
.Reset => asm volatile ("lock btrl %[bit], %[ptr]"
260+
// LLVM doesn't support u1 flag register return values
261+
: [result] "={@ccc}" (-> u8),
262+
: [ptr] "*m" (&self.value),
263+
[bit] "X" (@as(T, bit)),
264+
: "cc", "memory"
265+
),
266+
.Toggle => asm volatile ("lock btcl %[bit], %[ptr]"
267+
// LLVM doesn't support u1 flag register return values
268+
: [result] "={@ccc}" (-> u8),
269+
: [ptr] "*m" (&self.value),
270+
[bit] "X" (@as(T, bit)),
271+
: "cc", "memory"
272+
),
273+
},
274+
8 => switch (op) {
275+
.Set => asm volatile ("lock btsq %[bit], %[ptr]"
276+
// LLVM doesn't support u1 flag register return values
277+
: [result] "={@ccc}" (-> u8),
278+
: [ptr] "*m" (&self.value),
279+
[bit] "X" (@as(T, bit)),
280+
: "cc", "memory"
281+
),
282+
.Reset => asm volatile ("lock btrq %[bit], %[ptr]"
283+
// LLVM doesn't support u1 flag register return values
284+
: [result] "={@ccc}" (-> u8),
285+
: [ptr] "*m" (&self.value),
286+
[bit] "X" (@as(T, bit)),
287+
: "cc", "memory"
288+
),
289+
.Toggle => asm volatile ("lock btcq %[bit], %[ptr]"
290+
// LLVM doesn't support u1 flag register return values
291+
: [result] "={@ccc}" (-> u8),
292+
: [ptr] "*m" (&self.value),
293+
[bit] "X" (@as(T, bit)),
294+
: "cc", "memory"
295+
),
296+
},
297+
else => @compileError("Invalid atomic type " ++ @typeName(T)),
298+
};
306299

307-
// TODO: emit appropriate tsan fence if compiling with tsan
308-
_ = ordering;
300+
// TODO: emit appropriate tsan fence if compiling with tsan
301+
_ = ordering;
309302

310-
return @as(u1, @intCast(old_bit));
311-
}
312-
});
303+
return @intCast(old_bit);
304+
}
313305
};
314306
}
315307

lib/std/enums.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E {
201201
if (V == E) break :blk value;
202202
const name: ?[]const u8 = switch (@typeInfo(V)) {
203203
.EnumLiteral, .Enum => @tagName(value),
204-
.Pointer => if (std.meta.trait.isZigString(V)) value else null,
204+
.Pointer => value,
205205
else => null,
206206
};
207207
if (name) |n| {

lib/std/fmt.zig

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ pub fn formatType(
478478
return formatAddress(value, options, writer);
479479
}
480480

481-
if (comptime std.meta.trait.hasFn("format")(T)) {
481+
if (std.meta.hasFn(T, "format")) {
482482
return try value.format(actual_fmt, options, writer);
483483
}
484484

@@ -611,15 +611,12 @@ pub fn formatType(
611611
else => {},
612612
}
613613
}
614-
if (comptime std.meta.trait.isZigString(info.child)) {
615-
for (value, 0..) |item, i| {
616-
comptime checkTextFmt(actual_fmt);
617-
if (i != 0) try formatBuf(", ", options, writer);
618-
try formatBuf(item, options, writer);
619-
}
620-
return;
614+
for (value, 0..) |item, i| {
615+
comptime checkTextFmt(actual_fmt);
616+
if (i != 0) try formatBuf(", ", options, writer);
617+
try formatBuf(item, options, writer);
621618
}
622-
invalidFmtError(fmt, value);
619+
return;
623620
},
624621
.Enum, .Union, .Struct => {
625622
return formatType(value.*, actual_fmt, options, writer, max_depth);

0 commit comments

Comments
 (0)