// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file implements various error reporters.
+// This file implements error reporting.
package types2
import (
- "bytes"
"cmd/compile/internal/syntax"
"fmt"
. "internal/types/errors"
"runtime"
- "strconv"
"strings"
)
return &error_{check: check, code: code}
}
+// addf adds formatted error information to err.
+// It may be called multiple times to provide additional information.
+// The position of the first call to addf determines the position of the reported Error.
+// Subsequent calls to addf provide additional information in the form of additional lines
+// in the error message (types2) or continuation errors identified by a tab-indented error
+// message (go/types).
+func (err *error_) addf(at poser, format string, args ...interface{}) {
+ err.desc = append(err.desc, errorDesc{atPos(at), err.check.sprintf(format, args...)})
+}
+
func (err *error_) empty() bool {
return err.desc == nil
}
return buf.String()
}
-// addf adds formatted error information to err.
-// It may be called multiple times to provide additional information.
-// The position of the first call to addf determines the position of the reported Error.
-// Subsequent calls to addf provide additional information in the form of additional lines
-// in the error message (types2) or continuation errors identified by a tab-indented error
-// message (go/types).
-func (err *error_) addf(at poser, format string, args ...interface{}) {
- err.desc = append(err.desc, errorDesc{atPos(at), err.check.sprintf(format, args...)})
-}
-
-func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...any) string {
- for i, arg := range args {
- switch a := arg.(type) {
- case nil:
- arg = "<nil>"
- case operand:
- panic("got operand instead of *operand")
- case *operand:
- arg = operandString(a, qf)
- case syntax.Pos:
- arg = a.String()
- case syntax.Expr:
- arg = ExprString(a)
- case []syntax.Expr:
- var buf strings.Builder
- buf.WriteByte('[')
- for i, x := range a {
- if i > 0 {
- buf.WriteString(", ")
- }
- buf.WriteString(ExprString(x))
- }
- buf.WriteByte(']')
- arg = buf.String()
- case Object:
- arg = ObjectString(a, qf)
- case Type:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- w.typ(a)
- arg = buf.String()
- case []Type:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- buf.WriteByte('[')
- for i, x := range a {
- if i > 0 {
- buf.WriteString(", ")
- }
- w.typ(x)
- }
- buf.WriteByte(']')
- arg = buf.String()
- case []*TypeParam:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- buf.WriteByte('[')
- for i, x := range a {
- if i > 0 {
- buf.WriteString(", ")
- }
- w.typ(x)
- }
- buf.WriteByte(']')
- arg = buf.String()
- }
- args[i] = arg
- }
- return fmt.Sprintf(format, args...)
-}
-
-func (check *Checker) qualifier(pkg *Package) string {
- // Qualify the package unless it's the package being type-checked.
- if pkg != check.pkg {
- if check.pkgPathMap == nil {
- check.pkgPathMap = make(map[string]map[string]bool)
- check.seenPkgMap = make(map[*Package]bool)
- check.markImports(check.pkg)
- }
- // If the same package name was used by multiple packages, display the full path.
- if len(check.pkgPathMap[pkg.name]) > 1 {
- return strconv.Quote(pkg.path)
- }
- return pkg.name
- }
- return ""
-}
-
-// markImports recursively walks pkg and its imports, to record unique import
-// paths in pkgPathMap.
-func (check *Checker) markImports(pkg *Package) {
- if check.seenPkgMap[pkg] {
- return
- }
- check.seenPkgMap[pkg] = true
-
- forName, ok := check.pkgPathMap[pkg.name]
- if !ok {
- forName = make(map[string]bool)
- check.pkgPathMap[pkg.name] = forName
- }
- forName[pkg.path] = true
-
- for _, imp := range pkg.imports {
- check.markImports(imp)
- }
-}
-
-// check may be nil.
-func (check *Checker) sprintf(format string, args ...any) string {
- var qf Qualifier
- if check != nil {
- qf = check.qualifier
- }
- return sprintf(qf, false, format, args...)
-}
-
-func (check *Checker) trace(pos syntax.Pos, format string, args ...any) {
- fmt.Printf("%s:\t%s%s\n",
- pos,
- strings.Repeat(". ", check.indent),
- sprintf(check.qualifier, true, format, args...),
- )
-}
-
-// dump is only needed for debugging
-func (check *Checker) dump(format string, args ...any) {
- fmt.Println(sprintf(check.qualifier, true, format, args...))
-}
-
// report reports the error err, setting check.firstError if necessary.
func (err *error_) report() {
if err.empty() {
invalidOp = "invalid operation: "
)
+// The poser interface is used to extract the position of type-checker errors.
type poser interface {
Pos() syntax.Pos
}
}
return at.Pos()
}
-
-// stripAnnotations removes internal (type) annotations from s.
-func stripAnnotations(s string) string {
- var buf strings.Builder
- for _, r := range s {
- // strip #'s and subscript digits
- if r < '₀' || '₀'+10 <= r { // '₀' == U+2080
- buf.WriteRune(r)
- }
- }
- if buf.Len() < len(s) {
- return buf.String()
- }
- return s
-}
--- /dev/null
+// 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.
+
+// This file implements (error and trace) message formatting support.
+
+package types2
+
+import (
+ "bytes"
+ "cmd/compile/internal/syntax"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...any) string {
+ for i, arg := range args {
+ switch a := arg.(type) {
+ case nil:
+ arg = "<nil>"
+ case operand:
+ panic("got operand instead of *operand")
+ case *operand:
+ arg = operandString(a, qf)
+ case syntax.Pos:
+ arg = a.String()
+ case syntax.Expr:
+ arg = ExprString(a)
+ case []syntax.Expr:
+ var buf strings.Builder
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(ExprString(x))
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ case Object:
+ arg = ObjectString(a, qf)
+ case Type:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ w.typ(a)
+ arg = buf.String()
+ case []Type:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ w.typ(x)
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ case []*TypeParam:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ w.typ(x)
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ }
+ args[i] = arg
+ }
+ return fmt.Sprintf(format, args...)
+}
+
+// check may be nil.
+func (check *Checker) sprintf(format string, args ...any) string {
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ return sprintf(qf, false, format, args...)
+}
+
+func (check *Checker) trace(pos syntax.Pos, format string, args ...any) {
+ fmt.Printf("%s:\t%s%s\n",
+ pos,
+ strings.Repeat(". ", check.indent),
+ sprintf(check.qualifier, true, format, args...),
+ )
+}
+
+// dump is only needed for debugging
+func (check *Checker) dump(format string, args ...any) {
+ fmt.Println(sprintf(check.qualifier, true, format, args...))
+}
+
+func (check *Checker) qualifier(pkg *Package) string {
+ // Qualify the package unless it's the package being type-checked.
+ if pkg != check.pkg {
+ if check.pkgPathMap == nil {
+ check.pkgPathMap = make(map[string]map[string]bool)
+ check.seenPkgMap = make(map[*Package]bool)
+ check.markImports(check.pkg)
+ }
+ // If the same package name was used by multiple packages, display the full path.
+ if len(check.pkgPathMap[pkg.name]) > 1 {
+ return strconv.Quote(pkg.path)
+ }
+ return pkg.name
+ }
+ return ""
+}
+
+// markImports recursively walks pkg and its imports, to record unique import
+// paths in pkgPathMap.
+func (check *Checker) markImports(pkg *Package) {
+ if check.seenPkgMap[pkg] {
+ return
+ }
+ check.seenPkgMap[pkg] = true
+
+ forName, ok := check.pkgPathMap[pkg.name]
+ if !ok {
+ forName = make(map[string]bool)
+ check.pkgPathMap[pkg.name] = forName
+ }
+ forName[pkg.path] = true
+
+ for _, imp := range pkg.imports {
+ check.markImports(imp)
+ }
+}
+
+// stripAnnotations removes internal (type) annotations from s.
+func stripAnnotations(s string) string {
+ var buf strings.Builder
+ for _, r := range s {
+ // strip #'s and subscript digits
+ if r < '₀' || '₀'+10 <= r { // '₀' == U+2080
+ buf.WriteRune(r)
+ }
+ }
+ if buf.Len() < len(s) {
+ return buf.String()
+ }
+ return s
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file implements various error reporters.
+// This file implements error reporting.
package types
import (
- "bytes"
"fmt"
"go/ast"
"go/token"
. "internal/types/errors"
"runtime"
- "strconv"
"strings"
)
return &error_{check: check, code: code}
}
+// addf adds formatted error information to err.
+// It may be called multiple times to provide additional information.
+// The position of the first call to addf determines the position of the reported Error.
+// Subsequent calls to addf provide additional information in the form of additional lines
+// in the error message (types2) or continuation errors identified by a tab-indented error
+// message (go/types).
+func (err *error_) addf(at positioner, format string, args ...interface{}) {
+ err.desc = append(err.desc, errorDesc{at, err.check.sprintf(format, args...)})
+}
+
func (err *error_) empty() bool {
return err.desc == nil
}
return buf.String()
}
-// addf adds formatted error information to err.
-// It may be called multiple times to provide additional information.
-// The position of the first call to addf determines the position of the reported Error.
-// Subsequent calls to addf provide additional information in the form of additional lines
-// in the error message (types2) or continuation errors identified by a tab-indented error
-// message (go/types).
-func (err *error_) addf(at positioner, format string, args ...interface{}) {
- err.desc = append(err.desc, errorDesc{at, err.check.sprintf(format, args...)})
-}
-
-func (check *Checker) qualifier(pkg *Package) string {
- // Qualify the package unless it's the package being type-checked.
- if pkg != check.pkg {
- if check.pkgPathMap == nil {
- check.pkgPathMap = make(map[string]map[string]bool)
- check.seenPkgMap = make(map[*Package]bool)
- check.markImports(check.pkg)
- }
- // If the same package name was used by multiple packages, display the full path.
- if len(check.pkgPathMap[pkg.name]) > 1 {
- return strconv.Quote(pkg.path)
- }
- return pkg.name
- }
- return ""
-}
-
-// markImports recursively walks pkg and its imports, to record unique import
-// paths in pkgPathMap.
-func (check *Checker) markImports(pkg *Package) {
- if check.seenPkgMap[pkg] {
- return
- }
- check.seenPkgMap[pkg] = true
-
- forName, ok := check.pkgPathMap[pkg.name]
- if !ok {
- forName = make(map[string]bool)
- check.pkgPathMap[pkg.name] = forName
- }
- forName[pkg.path] = true
-
- for _, imp := range pkg.imports {
- check.markImports(imp)
- }
-}
-
-// check may be nil.
-func (check *Checker) sprintf(format string, args ...any) string {
- var fset *token.FileSet
- var qf Qualifier
- if check != nil {
- fset = check.fset
- qf = check.qualifier
- }
- return sprintf(fset, qf, false, format, args...)
-}
-
-func sprintf(fset *token.FileSet, qf Qualifier, tpSubscripts bool, format string, args ...any) string {
- for i, arg := range args {
- switch a := arg.(type) {
- case nil:
- arg = "<nil>"
- case operand:
- panic("got operand instead of *operand")
- case *operand:
- arg = operandString(a, qf)
- case token.Pos:
- if fset != nil {
- arg = fset.Position(a).String()
- }
- case ast.Expr:
- arg = ExprString(a)
- case []ast.Expr:
- var buf bytes.Buffer
- buf.WriteByte('[')
- writeExprList(&buf, a)
- buf.WriteByte(']')
- arg = buf.String()
- case Object:
- arg = ObjectString(a, qf)
- case Type:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- w.typ(a)
- arg = buf.String()
- case []Type:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- buf.WriteByte('[')
- for i, x := range a {
- if i > 0 {
- buf.WriteString(", ")
- }
- w.typ(x)
- }
- buf.WriteByte(']')
- arg = buf.String()
- case []*TypeParam:
- var buf bytes.Buffer
- w := newTypeWriter(&buf, qf)
- w.tpSubscripts = tpSubscripts
- buf.WriteByte('[')
- for i, x := range a {
- if i > 0 {
- buf.WriteString(", ")
- }
- w.typ(x)
- }
- buf.WriteByte(']')
- arg = buf.String()
- }
- args[i] = arg
- }
- return fmt.Sprintf(format, args...)
-}
-
-func (check *Checker) trace(pos token.Pos, format string, args ...any) {
- fmt.Printf("%s:\t%s%s\n",
- check.fset.Position(pos),
- strings.Repeat(". ", check.indent),
- sprintf(check.fset, check.qualifier, true, format, args...),
- )
-}
-
-// dump is only needed for debugging
-func (check *Checker) dump(format string, args ...any) {
- fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...))
-}
-
// report reports the error err, setting check.firstError if necessary.
func (err *error_) report() {
if err.empty() {
invalidOp = "invalid operation: "
)
-// The positioner interface is used to extract the position of type-checker
-// errors.
+// The positioner interface is used to extract the position of type-checker errors.
type positioner interface {
Pos() token.Pos
}
err.report()
}
+// atPos wraps a token.Pos to implement the positioner interface.
+type atPos token.Pos
+
+func (s atPos) Pos() token.Pos {
+ return token.Pos(s)
+}
+
// posSpan holds a position range along with a highlighted position within that
// range. This is used for positioning errors, with pos by convention being the
// first position in the source where the error is known to exist, and start
return posSpan{start, pos, end}
}
-// atPos wraps a token.Pos to implement the positioner interface.
-type atPos token.Pos
-
-func (s atPos) Pos() token.Pos {
- return token.Pos(s)
-}
-
// spanOf extracts an error span from the given positioner. By default this is
// the trivial span starting and ending at pos, but this span is expanded when
// the argument naturally corresponds to a span of source code.
return posSpan{pos, pos, pos}
}
}
-
-// stripAnnotations removes internal (type) annotations from s.
-func stripAnnotations(s string) string {
- var buf strings.Builder
- for _, r := range s {
- // strip #'s and subscript digits
- if r < '₀' || '₀'+10 <= r { // '₀' == U+2080
- buf.WriteRune(r)
- }
- }
- if buf.Len() < len(s) {
- return buf.String()
- }
- return s
-}
--- /dev/null
+// 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.
+
+// This file implements (error and trace) message formatting support.
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "strconv"
+ "strings"
+)
+
+func sprintf(fset *token.FileSet, qf Qualifier, tpSubscripts bool, format string, args ...any) string {
+ for i, arg := range args {
+ switch a := arg.(type) {
+ case nil:
+ arg = "<nil>"
+ case operand:
+ panic("got operand instead of *operand")
+ case *operand:
+ arg = operandString(a, qf)
+ case token.Pos:
+ if fset != nil {
+ arg = fset.Position(a).String()
+ }
+ case ast.Expr:
+ arg = ExprString(a)
+ case []ast.Expr:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ writeExprList(&buf, a)
+ buf.WriteByte(']')
+ arg = buf.String()
+ case Object:
+ arg = ObjectString(a, qf)
+ case Type:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ w.typ(a)
+ arg = buf.String()
+ case []Type:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ w.typ(x)
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ case []*TypeParam:
+ var buf bytes.Buffer
+ w := newTypeWriter(&buf, qf)
+ w.tpSubscripts = tpSubscripts
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ w.typ(x)
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ }
+ args[i] = arg
+ }
+ return fmt.Sprintf(format, args...)
+}
+
+// check may be nil.
+func (check *Checker) sprintf(format string, args ...any) string {
+ var fset *token.FileSet
+ var qf Qualifier
+ if check != nil {
+ fset = check.fset
+ qf = check.qualifier
+ }
+ return sprintf(fset, qf, false, format, args...)
+}
+
+func (check *Checker) trace(pos token.Pos, format string, args ...any) {
+ fmt.Printf("%s:\t%s%s\n",
+ check.fset.Position(pos),
+ strings.Repeat(". ", check.indent),
+ sprintf(check.fset, check.qualifier, true, format, args...),
+ )
+}
+
+// dump is only needed for debugging
+func (check *Checker) dump(format string, args ...any) {
+ fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...))
+}
+
+func (check *Checker) qualifier(pkg *Package) string {
+ // Qualify the package unless it's the package being type-checked.
+ if pkg != check.pkg {
+ if check.pkgPathMap == nil {
+ check.pkgPathMap = make(map[string]map[string]bool)
+ check.seenPkgMap = make(map[*Package]bool)
+ check.markImports(check.pkg)
+ }
+ // If the same package name was used by multiple packages, display the full path.
+ if len(check.pkgPathMap[pkg.name]) > 1 {
+ return strconv.Quote(pkg.path)
+ }
+ return pkg.name
+ }
+ return ""
+}
+
+// markImports recursively walks pkg and its imports, to record unique import
+// paths in pkgPathMap.
+func (check *Checker) markImports(pkg *Package) {
+ if check.seenPkgMap[pkg] {
+ return
+ }
+ check.seenPkgMap[pkg] = true
+
+ forName, ok := check.pkgPathMap[pkg.name]
+ if !ok {
+ forName = make(map[string]bool)
+ check.pkgPathMap[pkg.name] = forName
+ }
+ forName[pkg.path] = true
+
+ for _, imp := range pkg.imports {
+ check.markImports(imp)
+ }
+}
+
+// stripAnnotations removes internal (type) annotations from s.
+func stripAnnotations(s string) string {
+ var buf strings.Builder
+ for _, r := range s {
+ // strip #'s and subscript digits
+ if r < '₀' || '₀'+10 <= r { // '₀' == U+2080
+ buf.WriteRune(r)
+ }
+ }
+ if buf.Len() < len(s) {
+ return buf.String()
+ }
+ return s
+}