diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 1624858329cbf..461f0a525ba88 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1125,6 +1125,16 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } 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 @@ -1135,9 +1145,21 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } 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) diff --git a/src/go/types/testdata/cycles.src b/src/go/types/testdata/cycles.src index 621d83c9450a0..b4bd5d8b15769 100644 --- a/src/go/types/testdata/cycles.src +++ b/src/go/types/testdata/cycles.src @@ -140,4 +140,13 @@ func (*T12) m() {} 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 +)