In other languages, defining types in terms of themselves is unproblematic, because the type identifier is just a symbol and the whole thing amounts to a graph with a backreference.
However, here it's supposed to represent actual executable code, which is run by the compiler and "produces" a type in the end. But how would the compiler execute this function without getting stuck in a loop?
It's not actually about `*` -- for instance, declaring `const T = *T;` emits an error. The thing that makes this okay is that field types (for structs and unions) are evaluated in the "lazy" way you describe.
However, here it's supposed to represent actual executable code, which is run by the compiler and "produces" a type in the end. But how would the compiler execute this function without getting stuck in a loop?