Explain why debug printing this struct produces an error

Why does this cause an error?
Should I not be able to debug print any Struct?

const std = @import("std");
pub fn main() !void {
    const s = @typeInfo(struct { usize });
    std.debug.print("{?}", .{s});

It does not give an error on creating the struct.
Any ideas?

C:\Program Files\zig\lib\std\fmt.zig:640:22: error: values of type '[]const builtin.Type.StructField' must be comptime-known, but index value is runtime-known
                for (value, 0..) |elem, i| {
C:\Program Files\zig\lib\std\builtin.zig:346:15: note: struct requires comptime because of this field
        type: type,
C:\Program Files\zig\lib\std\builtin.zig:346:15: note: types are not available at runtime
        type: type,
C:\Program Files\zig\lib\std\builtin.zig:349:20: note: struct requires comptime because of this field
        alignment: comptime_int,
referenced by:
    formatType__anon_6887: C:\Program Files\zig\lib\std\fmt.zig:608:31
    formatType__anon_4004: C:\Program Files\zig\lib\std\fmt.zig:569:39
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

You aren’t debug printing the struct, you are debug printing the typeinfo of the struct, which is a type that contains type and comptime_int which makes it a comptime type. That is why you can’t use std.debug.print directly to print it, because that is for printing runtime values, but you want to print a comptime value.

Usually the debug workflow for printing these values is to use @compileLog(s) look at the value and continue working on your code and then remove the compileLogs again. (Because the program won’t run and instead the compile will output the logs and then stop)

If you want to use std.debug.print to output the formatted representation of the typeinfo at runtime you can do so in two steps:

  1. convert the typeinfo to a string literal at comptime via std.fmt.comptimePrint
  2. use std.debug.print to print the string
const std = @import("std");
pub fn main() !void {
    const s = @typeInfo(struct { usize });
    std.debug.print("{s}\n", .{std.fmt.comptimePrint("{}", .{s})});

Excellent! Thanks!

As a side note, why do we have two totally different ways to debug print?
It seems to me that @compileLog and std.debug.print have the same basic function, that is, to help debug a program by printing.

@compileLog is for printing comptime known arguments - you can print values during your compilation. std.debug.print and similar utilities are for runtime.

More info: Documentation - The Zig Programming Language