}
case *Array:
+ // Prevent crash if the array referred to is not yet set up.
+ // This is a stop-gap solution; a better approach would use the mechanism of
+ // Checker.ident (typexpr.go) using a path of types. But that would require
+ // passing the path everywhere (all expression-checking methods, not just
+ // type expression checking), and we're not set up for that (quite possibly
+ // an indication that cycle detection needs to be rethought). Was issue #18643.
+ if utyp.elem == nil {
+ check.error(e.Pos(), "illegal cycle in type declaration")
+ goto Error
+ }
n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
// If we have an "open" [...]T array, set the length now that we know it
// and record the type for [...] (usually done by check.typExpr which is
}
case *Slice:
+ // Prevent crash if the slice referred to is not yet set up.
+ // See analogous comment for *Array.
+ if utyp.elem == nil {
+ check.error(e.Pos(), "illegal cycle in type declaration")
+ goto Error
+ }
check.indexedElts(e.Elts, utyp.elem, -1)
case *Map:
+ // Prevent crash if the map referred to is not yet set up.
+ // See analogous comment for *Array.
+ if utyp.key == nil || utyp.elem == nil {
+ check.error(e.Pos(), "illegal cycle in type declaration")
+ goto Error
+ }
visited := make(map[interface{}][]Type, len(e.Elts))
for _, e := range e.Elts {
kv, _ := e.(*ast.KeyValueExpr)
type (
P3 *T13
T13 /* ERROR cycle */ T13
-)
\ No newline at end of file
+)
+
+// test cases for issue 18643
+// (type cycle detection when non-type expressions are involved)
+type (
+ T14 [len(T14 /* ERROR cycle */ {})]int
+ T15 [][len(T15 /* ERROR cycle */ {})]int
+ T16 map[[len(T16 /* ERROR cycle */ {1:2})]int]int
+ T17 map[int][len(T17 /* ERROR cycle */ {1:2})]int
+)