TBH I find it rather surprising that the spec does not mention why `type X X` is *not* allowed. It's obvious that it can't be, but from what I can tell, the spec doesn't forbid it. Otherwise I would've chalked up the validity of `type X *X` for "anything that's not forbidden, is allowed". A type definition <https://go.dev/ref/spec#Type_definitions> is
TypeDef = identifier Type . > Type = TypeName | TypeLit | "(" Type ")" . > TypeName = identifier | QualifiedIdent . > TypeLit = … | PointerType | … . PointerType = "*" BaseType . BaseType = Type . So `type X *X` is obviously valid (after taking scope into account <https://go.dev/ref/spec#Declarations_and_scope>, as Jam mentions). But so would `type X X` be. On Thu, Mar 10, 2022 at 2:04 PM Jan Mercl <0xj...@gmail.com> wrote: > On Thu, Mar 10, 2022 at 1:40 PM 'wagner riffel' via golang-nuts < > golang-nuts@googlegroups.com> wrote: > > > I don't think it's mentioned in the specification, my bet is that > > unless your type requires inifnity amout of memory (eg: `type t struct > > {t}`) or the type is an interface and break its rules, (eg: `type > > iface interface{ iface }`) you can use self-reference. > > The validity of `type T *T` in Go is based on two things: 1) The > visibility of the identifier in `type T ...` is specified to start right > after the identifier, 2) It's possible, in this case, to compute the size > of type T. So no problem here. > > > You're correct, C doesn't allow self reference in type decl, more ... > > In `typedef self *self;` the visibility of the second instance of > identifier `self` starts only after it, ie. preceding the final `;'. So the > first identifier `self`, the one after `typedef` is undefined and that's > the real reason it does not work. However: > > ---- > jnml@e5-1650:~/tmp$ cat main.c > typedef int T; > typedef T T; > > int main() {} > jnml@e5-1650:~/tmp$ gcc -Wall main.c > jnml@e5-1650:~/tmp$ > ---- > > This works because typedef is equal to Go type aliases. But the full Go > thing cannot work: > > ---- > jnml@e5-1650:~/tmp$ cat main.c > typedef int T; > typedef T *T; > > int main() {} > jnml@e5-1650:~/tmp$ gcc -Wall main.c > main.c:2:12: error: conflicting types for ‘T’ > 2 | typedef T *T; > | ^ > main.c:1:13: note: previous declaration of ‘T’ was here > 1 | typedef int T; > | > ---- > > Here the problem is that we define T to be two different types, the first > it's an int and the second is a pointer to int. > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CAA40n-VotEGgVupaJ6S1zRF%3D3hDHDKAz0V5_enaD9EfYfL7t-Q%40mail.gmail.com > <https://groups.google.com/d/msgid/golang-nuts/CAA40n-VotEGgVupaJ6S1zRF%3D3hDHDKAz0V5_enaD9EfYfL7t-Q%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfFDr%2BJ5Z79%2BTY_-Yjj5cNniPWRH7ccyK0vSyaHsBcayKA%40mail.gmail.com.