diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index b25cf89fb4e..2be8716d448 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1151,6 +1151,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty case *syntax.CompositeLit: var typ, base Type + var isElem bool // true if composite literal is an element of an enclosing composite literal switch { case e.Type != nil: @@ -1171,11 +1172,12 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty case hint != nil: // no composite literal type present - use hint (element type of enclosing type) typ = hint - base, _ = deref(coreType(typ)) // *T implies &T{} - if base == nil { - check.errorf(e, InvalidLit, "invalid composite literal element type %s (no core type)", typ) - goto Error + base = typ + // *T implies &T{} + if b, ok := deref(coreType(base)); ok { + base = b } + isElem = true default: // TODO(gri) provide better error messages depending on context @@ -1361,7 +1363,15 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty } // if utyp is invalid, an error was reported before if isValid(utyp) { - check.errorf(e, InvalidLit, "invalid composite literal type %s", typ) + var qualifier string + if isElem { + qualifier = " element" + } + var cause string + if utyp == nil { + cause = " (no core type)" + } + check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause) goto Error } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index ac125c666b6..ea680b8504d 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1129,6 +1129,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type) case *ast.CompositeLit: var typ, base Type + var isElem bool // true if composite literal is an element of an enclosing composite literal switch { case e.Type != nil: @@ -1151,11 +1152,12 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type) case hint != nil: // no composite literal type present - use hint (element type of enclosing type) typ = hint - base, _ = deref(coreType(typ)) // *T implies &T{} - if base == nil { - check.errorf(e, InvalidLit, "invalid composite literal element type %s (no core type)", typ) - goto Error + base = typ + // *T implies &T{} + if b, ok := deref(coreType(base)); ok { + base = b } + isElem = true default: // TODO(gri) provide better error messages depending on context @@ -1343,7 +1345,15 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type) } // if utyp is invalid, an error was reported before if isValid(utyp) { - check.errorf(e, InvalidLit, "invalid composite literal type %s", typ) + var qualifier string + if isElem { + qualifier = " element" + } + var cause string + if utyp == nil { + cause = " (no core type)" + } + check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause) goto Error } } diff --git a/src/internal/types/testdata/fixedbugs/issue68184.go b/src/internal/types/testdata/fixedbugs/issue68184.go new file mode 100644 index 00000000000..9c77365aa9a --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue68184.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type VeryLongStruct struct { + A1 int + A2 int + A3 int + A4 int + A5 int + A6 int + A7 int + A8 int + A9 int + A10 int + A11 int + A12 int + A13 int + A14 int + A15 int + A16 int + A17 int + A18 int + A19 int + A20 int +} + +func _() { + // The error messages in both these cases should print the + // struct name rather than the struct's underlying type. + + var x VeryLongStruct + x.B2 /* ERROR "x.B2 undefined (type VeryLongStruct has no field or method B2)" */ = false + + _ = []VeryLongStruct{{B2 /* ERROR "unknown field B2 in struct literal of type VeryLongStruct" */ : false}} +}