]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: report type name in comp. literal error, if possible
authorRobert Griesemer <gri@golang.org>
Tue, 25 Jun 2024 22:31:06 +0000 (15:31 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 26 Jul 2024 20:11:56 +0000 (20:11 +0000)
When reporting an error for the element type of a struct literal, use
the element type's type name rather than it's underlying/core type.

Also, combine error reporting for invalid composite literal types in
one place, at the end.

Fixes #68184.

Change-Id: I1f407d5403777948da9a0eca95aacc1389f4bd44
Reviewed-on: https://go-review.googlesource.com/c/go/+/595075
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Tim King <taking@google.com>
src/cmd/compile/internal/types2/expr.go
src/go/types/expr.go
src/internal/types/testdata/fixedbugs/issue68184.go [new file with mode: 0644]

index b25cf89fb4efa88014fb501645ba33a2fd896224..2be8716d44815144cf87ed7294468c2f2b5b9506 100644 (file)
@@ -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
                        }
                }
index ac125c666b6c51d49d0167e1962a4b05bb775f1a..ea680b8504df3b74e916199e4bc5ca64c1b93c28 100644 (file)
@@ -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 (file)
index 0000000..9c77365
--- /dev/null
@@ -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}}
+}