Skip to content

Commit a02bd81

Browse files
Make @typeInfo return null-terminated strings
Changes the types of `std.builtin.Type` `name` fields from `[]const u8` to `[:0]const u8`, which should make them easier to pass to C APIs expecting null-terminated strings. This will break code that reifies types using `[]const u8` strings, such as code that uses `std.mem.tokenize()` to construct types from strings at comptime. Luckily, the fix is simple: simply concatenate the `[]const u8` string with an empty string literal (`name ++ ""`) to explicitly coerce it to `[:0]const u8`. Co-authored-by: Krzysztof Wolicki <[email protected]>
1 parent 804cee3 commit a02bd81

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

lib/std/builtin.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ pub const Type = union(enum) {
314314
/// This data structure is used by the Zig language code generation and
315315
/// therefore must be kept in sync with the compiler implementation.
316316
pub const StructField = struct {
317-
name: []const u8,
317+
name: [:0]const u8,
318318
type: type,
319319
default_value: ?*const anyopaque,
320320
is_comptime: bool,
@@ -348,7 +348,7 @@ pub const Type = union(enum) {
348348
/// This data structure is used by the Zig language code generation and
349349
/// therefore must be kept in sync with the compiler implementation.
350350
pub const Error = struct {
351-
name: []const u8,
351+
name: [:0]const u8,
352352
};
353353

354354
/// This data structure is used by the Zig language code generation and
@@ -358,7 +358,7 @@ pub const Type = union(enum) {
358358
/// This data structure is used by the Zig language code generation and
359359
/// therefore must be kept in sync with the compiler implementation.
360360
pub const EnumField = struct {
361-
name: []const u8,
361+
name: [:0]const u8,
362362
value: comptime_int,
363363
};
364364

@@ -374,7 +374,7 @@ pub const Type = union(enum) {
374374
/// This data structure is used by the Zig language code generation and
375375
/// therefore must be kept in sync with the compiler implementation.
376376
pub const UnionField = struct {
377-
name: []const u8,
377+
name: [:0]const u8,
378378
type: type,
379379
alignment: comptime_int,
380380
};
@@ -436,7 +436,7 @@ pub const Type = union(enum) {
436436
/// This data structure is used by the Zig language code generation and
437437
/// therefore must be kept in sync with the compiler implementation.
438438
pub const Declaration = struct {
439-
name: []const u8,
439+
name: [:0]const u8,
440440
};
441441
};
442442

src/Sema.zig

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17259,28 +17259,29 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1725917259
const vals = try sema.arena.alloc(InternPool.Index, names.len);
1726017260
for (vals, 0..) |*field_val, i| {
1726117261
// TODO: write something like getCoercedInts to avoid needing to dupe
17262-
const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i]));
17262+
const name = try sema.arena.dupeZ(u8, ip.stringToSlice(names.get(ip)[i]));
1726317263
const name_val = v: {
1726417264
const new_decl_ty = try mod.arrayType(.{
1726517265
.len = name.len,
17266+
.sentinel = .zero_u8,
1726617267
.child = .u8_type,
1726717268
});
1726817269
const new_decl_val = try mod.intern(.{ .aggregate = .{
1726917270
.ty = new_decl_ty.toIntern(),
1727017271
.storage = .{ .bytes = name },
1727117272
} });
1727217273
break :v try mod.intern(.{ .ptr = .{
17273-
.ty = .slice_const_u8_type,
17274+
.ty = .slice_const_u8_sentinel_0_type,
1727417275
.addr = .{ .anon_decl = .{
1727517276
.val = new_decl_val,
17276-
.orig_ty = .slice_const_u8_type,
17277+
.orig_ty = .slice_const_u8_sentinel_0_type,
1727717278
} },
1727817279
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1727917280
} });
1728017281
};
1728117282

1728217283
const error_field_fields = .{
17283-
// name: []const u8,
17284+
// name: [:0]const u8,
1728417285
name_val,
1728517286
};
1728617287
field_val.* = try mod.intern(.{ .aggregate = .{
@@ -17387,28 +17388,29 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1738717388
else
1738817389
(try mod.intValue(Type.comptime_int, i)).toIntern();
1738917390
// TODO: write something like getCoercedInts to avoid needing to dupe
17390-
const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names.get(ip)[i]));
17391+
const name = try sema.arena.dupeZ(u8, ip.stringToSlice(enum_type.names.get(ip)[i]));
1739117392
const name_val = v: {
1739217393
const new_decl_ty = try mod.arrayType(.{
1739317394
.len = name.len,
17395+
.sentinel = .zero_u8,
1739417396
.child = .u8_type,
1739517397
});
1739617398
const new_decl_val = try mod.intern(.{ .aggregate = .{
1739717399
.ty = new_decl_ty.toIntern(),
1739817400
.storage = .{ .bytes = name },
1739917401
} });
1740017402
break :v try mod.intern(.{ .ptr = .{
17401-
.ty = .slice_const_u8_type,
17403+
.ty = .slice_const_u8_sentinel_0_type,
1740217404
.addr = .{ .anon_decl = .{
1740317405
.val = new_decl_val,
17404-
.orig_ty = .slice_const_u8_type,
17406+
.orig_ty = .slice_const_u8_sentinel_0_type,
1740517407
} },
1740617408
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1740717409
} });
1740817410
};
1740917411

1741017412
const enum_field_fields = .{
17411-
// name: []const u8,
17413+
// name: [:0]const u8,
1741217414
name_val,
1741317415
// value: comptime_int,
1741417416
value_val,
@@ -17512,21 +17514,22 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1751217514

1751317515
for (union_field_vals, 0..) |*field_val, i| {
1751417516
// TODO: write something like getCoercedInts to avoid needing to dupe
17515-
const name = try sema.arena.dupe(u8, ip.stringToSlice(union_obj.field_names.get(ip)[i]));
17517+
const name = try sema.arena.dupeZ(u8, ip.stringToSlice(union_obj.field_names.get(ip)[i]));
1751617518
const name_val = v: {
1751717519
const new_decl_ty = try mod.arrayType(.{
1751817520
.len = name.len,
17521+
.sentinel = .zero_u8,
1751917522
.child = .u8_type,
1752017523
});
1752117524
const new_decl_val = try mod.intern(.{ .aggregate = .{
1752217525
.ty = new_decl_ty.toIntern(),
1752317526
.storage = .{ .bytes = name },
1752417527
} });
1752517528
break :v try mod.intern(.{ .ptr = .{
17526-
.ty = .slice_const_u8_type,
17529+
.ty = .slice_const_u8_sentinel_0_type,
1752717530
.addr = .{ .anon_decl = .{
1752817531
.val = new_decl_val,
17529-
.orig_ty = .slice_const_u8_type,
17532+
.orig_ty = .slice_const_u8_sentinel_0_type,
1753017533
} },
1753117534
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1753217535
} });
@@ -17539,7 +17542,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1753917542

1754017543
const field_ty = union_obj.field_types.get(ip)[i];
1754117544
const union_field_fields = .{
17542-
// name: []const u8,
17545+
// name: [:0]const u8,
1754317546
name_val,
1754417547
// type: type,
1754517548
field_ty,
@@ -17658,22 +17661,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1765817661
// TODO: write something like getCoercedInts to avoid needing to dupe
1765917662
const bytes = if (tuple.names.len != 0)
1766017663
// https://github.com/ziglang/zig/issues/15709
17661-
try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip)[i]))
17664+
try sema.arena.dupeZ(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip)[i]))
1766217665
else
17663-
try std.fmt.allocPrint(sema.arena, "{d}", .{i});
17666+
try std.fmt.allocPrintZ(sema.arena, "{d}", .{i});
1766417667
const new_decl_ty = try mod.arrayType(.{
1766517668
.len = bytes.len,
17669+
.sentinel = .zero_u8,
1766617670
.child = .u8_type,
1766717671
});
1766817672
const new_decl_val = try mod.intern(.{ .aggregate = .{
1766917673
.ty = new_decl_ty.toIntern(),
1767017674
.storage = .{ .bytes = bytes },
1767117675
} });
1767217676
break :v try mod.intern(.{ .ptr = .{
17673-
.ty = .slice_const_u8_type,
17677+
.ty = .slice_const_u8_sentinel_0_type,
1767417678
.addr = .{ .anon_decl = .{
1767517679
.val = new_decl_val,
17676-
.orig_ty = .slice_const_u8_type,
17680+
.orig_ty = .slice_const_u8_sentinel_0_type,
1767717681
} },
1767817682
.len = (try mod.intValue(Type.usize, bytes.len)).toIntern(),
1767917683
} });
@@ -17685,7 +17689,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1768517689
const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null;
1768617690
const default_val_ptr = try sema.optRefValue(opt_default_val);
1768717691
const struct_field_fields = .{
17688-
// name: []const u8,
17692+
// name: [:0]const u8,
1768917693
name_val,
1769017694
// type: type,
1769117695
field_ty,
@@ -17713,7 +17717,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1771317717
for (struct_field_vals, 0..) |*field_val, i| {
1771417718
// TODO: write something like getCoercedInts to avoid needing to dupe
1771517719
const name = if (struct_type.fieldName(ip, i).unwrap()) |name_nts|
17716-
try sema.arena.dupe(u8, ip.stringToSlice(name_nts))
17720+
try sema.arena.dupeZ(u8, ip.stringToSlice(name_nts))
1771717721
else
1771817722
try std.fmt.allocPrintZ(sema.arena, "{d}", .{i});
1771917723
const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
@@ -17722,17 +17726,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1772217726
const name_val = v: {
1772317727
const new_decl_ty = try mod.arrayType(.{
1772417728
.len = name.len,
17729+
.sentinel = .zero_u8,
1772517730
.child = .u8_type,
1772617731
});
1772717732
const new_decl_val = try mod.intern(.{ .aggregate = .{
1772817733
.ty = new_decl_ty.toIntern(),
1772917734
.storage = .{ .bytes = name },
1773017735
} });
1773117736
break :v try mod.intern(.{ .ptr = .{
17732-
.ty = .slice_const_u8_type,
17737+
.ty = .slice_const_u8_sentinel_0_type,
1773317738
.addr = .{ .anon_decl = .{
1773417739
.val = new_decl_val,
17735-
.orig_ty = .slice_const_u8_type,
17740+
.orig_ty = .slice_const_u8_sentinel_0_type,
1773617741
} },
1773717742
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1773817743
} });
@@ -17750,7 +17755,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1775017755
};
1775117756

1775217757
const struct_field_fields = .{
17753-
// name: []const u8,
17758+
// name: [:0]const u8,
1775417759
name_val,
1775517760
// type: type,
1775617761
field_ty.toIntern(),
@@ -17957,27 +17962,28 @@ fn typeInfoNamespaceDecls(
1795717962
if (decl.kind != .named or !decl.is_pub) continue;
1795817963
const name_val = v: {
1795917964
// TODO: write something like getCoercedInts to avoid needing to dupe
17960-
const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
17965+
const name = try sema.arena.dupeZ(u8, ip.stringToSlice(decl.name));
1796117966
const new_decl_ty = try mod.arrayType(.{
1796217967
.len = name.len,
17968+
.sentinel = .zero_u8,
1796317969
.child = .u8_type,
1796417970
});
1796517971
const new_decl_val = try mod.intern(.{ .aggregate = .{
1796617972
.ty = new_decl_ty.toIntern(),
1796717973
.storage = .{ .bytes = name },
1796817974
} });
1796917975
break :v try mod.intern(.{ .ptr = .{
17970-
.ty = .slice_const_u8_type,
17976+
.ty = .slice_const_u8_sentinel_0_type,
1797117977
.addr = .{ .anon_decl = .{
17972-
.orig_ty = .slice_const_u8_type,
17978+
.orig_ty = .slice_const_u8_sentinel_0_type,
1797317979
.val = new_decl_val,
1797417980
} },
1797517981
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1797617982
} });
1797717983
};
1797817984

1797917985
const fields = .{
17980-
//name: []const u8,
17986+
//name: [:0]const u8,
1798117987
name_val,
1798217988
};
1798317989
try decl_vals.append(try mod.intern(.{ .aggregate = .{

0 commit comments

Comments
 (0)