From: Robert Griesemer Date: Wed, 5 Oct 2022 01:18:01 +0000 (-0700) Subject: go/types, types2: use consistent error messages for invalid struct literals X-Git-Tag: go1.20rc1~730 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=97d38f300273a3eb7af100d3943decaa433fd28f;p=gostls13.git go/types, types2: use consistent error messages for invalid struct literals Fixes #51879. Change-Id: Ic7ac892b82a0fe4ad6f95ff8ae84e6d30c52c111 Reviewed-on: https://go-review.googlesource.com/c/go/+/438855 Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer TryBot-Result: Gopher Robot --- diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 6abd9ca311..23592a86c7 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1385,6 +1385,9 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin if len(e.ElemList) == 0 { break } + // Convention for error messages on invalid struct literals: + // we mention the struct type only if it clarifies the error + // (e.g., a duplicate field error doesn't need the struct type). fields := utyp.fields if _, ok := e.ElemList[0].(*syntax.KeyValueExpr); ok { // all elements must have keys @@ -1428,20 +1431,20 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin } check.expr(x, e) if i >= len(fields) { - check.errorf(x, _InvalidStructLit, "too many values in %s{…}", base) + check.errorf(x, _InvalidStructLit, "too many values in struct literal of type %s", base) break // cannot continue } // i < len(fields) fld := fields[i] if !fld.Exported() && fld.pkg != check.pkg { - check.errorf(x, _UnexportedLitField, "implicit assignment to unexported field %s in %s literal", fld.name, typ) + check.errorf(x, _UnexportedLitField, "implicit assignment to unexported field %s in struct literal of type %s", fld.name, base) continue } etyp := fld.typ check.assignment(x, etyp, "struct literal") } if len(e.ElemList) < len(fields) { - check.errorf(e.Rbrace, _InvalidStructLit, "too few values in %s{…}", base) + check.errorf(e.Rbrace, _InvalidStructLit, "too few values in struct literal of type %s", base) // ok to continue } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 958082a962..dbc446f47b 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1364,6 +1364,9 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { if len(e.Elts) == 0 { break } + // Convention for error messages on invalid struct literals: + // we mention the struct type only if it clarifies the error + // (e.g., a duplicate field error doesn't need the struct type). fields := utyp.fields if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok { // all elements must have keys @@ -1407,7 +1410,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } check.expr(x, e) if i >= len(fields) { - check.errorf(x, _InvalidStructLit, "too many values in %s{…}", base) + check.errorf(x, _InvalidStructLit, "too many values in struct literal of type %s", base) break // cannot continue } // i < len(fields) @@ -1415,14 +1418,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { if !fld.Exported() && fld.pkg != check.pkg { check.errorf(x, _UnexportedLitField, - "implicit assignment to unexported field %s in %s literal", fld.name, typ) + "implicit assignment to unexported field %s in struct literal of type %s", fld.name, base) continue } etyp := fld.typ check.assignment(x, etyp, "struct literal") } if len(e.Elts) < len(fields) { - check.errorf(inNode(e, e.Rbrace), _InvalidStructLit, "too few values in %s{…}", base) + check.errorf(inNode(e, e.Rbrace), _InvalidStructLit, "too few values in struct literal of type %s", base) // ok to continue } } diff --git a/src/internal/types/testdata/check/expr3.go b/src/internal/types/testdata/check/expr3.go index a28d119f4e..2ca39866fc 100644 --- a/src/internal/types/testdata/check/expr3.go +++ b/src/internal/types/testdata/check/expr3.go @@ -209,7 +209,7 @@ func struct_literals() { _ = time.Time{} _ = time.Time{sec /* ERROR "unknown field" */ : 0} _ = time.Time{ - 0 /* ERROR implicit assignment to unexported field wall in time.Time literal */, + 0 /* ERROR implicit assignment to unexported field wall in struct literal */, 0 /* ERROR implicit assignment */ , nil /* ERROR implicit assignment */ , } diff --git a/src/internal/types/testdata/fixedbugs/issue51877.go b/src/internal/types/testdata/fixedbugs/issue51877.go index 06f054b257..c93242adce 100644 --- a/src/internal/types/testdata/fixedbugs/issue51877.go +++ b/src/internal/types/testdata/fixedbugs/issue51877.go @@ -10,9 +10,9 @@ type S struct { } var ( - _ = S{0} /* ERROR too few values in S{…} */ - _ = struct{ f1, f2 int }{0} /* ERROR too few values in struct{f1 int; f2 int}{…} */ + _ = S{0} /* ERROR too few values in struct literal */ + _ = struct{ f1, f2 int }{0} /* ERROR too few values in struct literal */ - _ = S{0, true, "foo" /* ERROR too many values in S{…} */} - _ = struct{ f1, f2 int }{0, 1, 2 /* ERROR too many values in struct{f1 int; f2 int}{…} */} + _ = S{0, true, "foo" /* ERROR too many values in struct literal */} + _ = struct{ f1, f2 int }{0, 1, 2 /* ERROR too many values in struct literal */} )