Skip to content

Commit

Permalink
go/types, types2: report type name in comp. literal error, if possible
Browse files Browse the repository at this point in the history
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 golang#68184.

Change-Id: I1f407d5403777948da9a0eca95aacc1389f4bd44
Reviewed-on: https://go-review.googlesource.com/c/go/+/595075
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Robert Griesemer <[email protected]>
Reviewed-by: Robert Griesemer <[email protected]>
Reviewed-by: Tim King <[email protected]>
  • Loading branch information
griesemer authored and gopherbot committed Jul 26, 2024
1 parent 77a3c3b commit 0509936
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 10 deletions.
20 changes: 15 additions & 5 deletions src/cmd/compile/internal/types2/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
20 changes: 15 additions & 5 deletions src/go/types/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/internal/types/testdata/fixedbugs/issue68184.go
Original file line number Diff line number Diff line change
@@ -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}}
}

0 comments on commit 0509936

Please sign in to comment.