Given:

package p

type s struct { i i }
type i interface { s | any }

go/types currently reports:

/tmp/y.go:3:6: invalid recursive type s
/tmp/y.go:3:6:  s refers to
/tmp/y.go:4:6:  i refers to
/tmp/y.go:3:6:  s

Notably, changing the field type from i to *i makes the error go away. I don't see any fundamental reason why that should make a difference though.

Synthetic test case, constructed while trying to write additional test cases for #60117.

/cc @adonovan @findleyr @griesemer @ianlancetaylor

Comment From: adonovan

Seems pretty clearly disallowed by the current spec wording:

https://go.dev/ref/spec#Interface_types:

An interface type T may not embed a type element that is, contains, or embeds T, directly or indirectly.

// illegal: Bad3 may not embed a union containing Bad3 type Bad3 interface { ~int | ~string | Bad3 }

But I don't see the technical reason why the restriction is necessary in this case, as s.i is an ordinary named field.

Comment From: griesemer

The spec rule seems not sufficiently precisely spelled out. And there's probably a bug in the cycle check. Not urgent but added to my plate. Thanks for reporting.

Comment From: griesemer

Too late for 1.21.

Comment From: griesemer

Too late for 1.23. Moving to 1.24.

Comment From: gopherbot

This issue is currently labeled as early-in-cycle for Go 1.24. That time is now, so a friendly reminder to look at it again.

Comment From: griesemer

Too late for 1.24. Moving to 1.25.

Comment From: gopherbot

This issue is currently labeled as early-in-cycle for Go 1.25. That time is now, so a friendly reminder to look at it again.