cmd/compile: pass type checker error codes in the compiler

Pass type checker error codes to base.ErrorfAt function calls
in the compiler (but don't do anything yet with the code).

Also, provide error codes to base.ErrorfAt calls in the
compiler as needed.

This opens the door towards reporting the error code and/or
providing a link/reference to more detailed explanations
(see internal/types/errors/codes.go).

Change-Id: I0ff9368d8163499ffdac6adfe8331fdc4a19b4b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/475198
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Griesemer 2023-03-09 16:21:22 -08:00 committed by Gopher Robot
parent 3790ceca97
commit 2cbab4e98c
20 changed files with 74 additions and 65 deletions

View file

@ -7,6 +7,7 @@ package base
import ( import (
"fmt" "fmt"
"internal/buildcfg" "internal/buildcfg"
"internal/types/errors"
"os" "os"
"runtime/debug" "runtime/debug"
"sort" "sort"
@ -105,11 +106,11 @@ func sameline(a, b src.XPos) bool {
// Errorf reports a formatted error at the current line. // Errorf reports a formatted error at the current line.
func Errorf(format string, args ...interface{}) { func Errorf(format string, args ...interface{}) {
ErrorfAt(Pos, format, args...) ErrorfAt(Pos, 0, format, args...)
} }
// ErrorfAt reports a formatted error message at pos. // ErrorfAt reports a formatted error message at pos.
func ErrorfAt(pos src.XPos, format string, args ...interface{}) { func ErrorfAt(pos src.XPos, code errors.Code, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) msg := fmt.Sprintf(format, args...)
if strings.HasPrefix(msg, "syntax error") { if strings.HasPrefix(msg, "syntax error") {

View file

@ -303,7 +303,7 @@ func (b *batch) finish(fns []*ir.Func) {
if loc.escapes { if loc.escapes {
if n.Op() == ir.ONAME { if n.Op() == ir.ONAME {
if base.Flag.CompilingRuntime { if base.Flag.CompilingRuntime {
base.ErrorfAt(n.Pos(), "%v escapes to heap, not allowed in runtime", n) base.ErrorfAt(n.Pos(), 0, "%v escapes to heap, not allowed in runtime", n)
} }
if base.Flag.LowerM != 0 { if base.Flag.LowerM != 0 {
base.WarnfAt(n.Pos(), "moved to heap: %v", n) base.WarnfAt(n.Pos(), "moved to heap: %v", n)

View file

@ -218,7 +218,7 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location {
base.Fatalf("e.curfn isn't set") base.Fatalf("e.curfn isn't set")
} }
if n != nil && n.Type() != nil && n.Type().NotInHeap() { if n != nil && n.Type() != nil && n.Type().NotInHeap() {
base.ErrorfAt(n.Pos(), "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type()) base.ErrorfAt(n.Pos(), 0, "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type())
} }
if n != nil && n.Op() == ir.ONAME { if n != nil && n.Op() == ir.ONAME {

View file

@ -331,7 +331,7 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
} }
} }
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap { if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func)) base.ErrorfAt(clo.Pos(), 0, "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
} }
} }

View file

@ -6,6 +6,7 @@ package noder
import ( import (
"fmt" "fmt"
"internal/types/errors"
"regexp" "regexp"
"sort" "sort"
@ -47,7 +48,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
if versionErrorRx.MatchString(msg) { if versionErrorRx.MatchString(msg) {
msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang) msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang)
} }
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", msg) base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg)
}, },
Importer: &importer, Importer: &importer,
Sizes: &gcSizes{}, Sizes: &gcSizes{},
@ -72,7 +73,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
syntax.Inspect(file, func(n syntax.Node) bool { syntax.Inspect(file, func(n syntax.Node) bool {
if n, ok := n.(*syntax.InterfaceType); ok { if n, ok := n.(*syntax.InterfaceType); ok {
if f.hasCycle(n.GetTypeInfo().Type.(*types2.Interface)) { if f.hasCycle(n.GetTypeInfo().Type.(*types2.Interface)) {
base.ErrorfAt(m.makeXPos(n.Pos()), "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)") base.ErrorfAt(m.makeXPos(n.Pos()), errors.InvalidTypeCycle, "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)")
for typ := range f.cyclic { for typ := range f.cyclic {
f.cyclic[typ] = false // suppress duplicate errors f.cyclic[typ] = false // suppress duplicate errors
@ -106,7 +107,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
return ti.pos.Before(tj.pos) return ti.pos.Before(tj.pos)
}) })
for _, targ := range nihTargs { for _, targ := range nihTargs {
base.ErrorfAt(targ.pos, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ) base.ErrorfAt(targ.pos, 0, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ)
} }
} }

View file

@ -65,7 +65,7 @@ func LoadPackage(filenames []string) {
var m posMap var m posMap
for _, p := range noders { for _, p := range noders {
for e := range p.err { for e := range p.err {
base.ErrorfAt(m.makeXPos(e.Pos), "%s", e.Msg) base.ErrorfAt(m.makeXPos(e.Pos), 0, "%s", e.Msg)
} }
if p.file == nil { if p.file == nil {
base.ErrorExit() base.ErrorExit()

View file

@ -108,7 +108,7 @@ func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter {
// errorf reports a user error about thing p. // errorf reports a user error about thing p.
func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) { func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) {
base.ErrorfAt(pw.m.pos(p), msg, args...) base.ErrorfAt(pw.m.pos(p), 0, msg, args...)
} }
// fatalf reports an internal compiler error about thing p. // fatalf reports an internal compiler error about thing p.

View file

@ -7,6 +7,7 @@ package pkginit
import ( import (
"container/heap" "container/heap"
"fmt" "fmt"
"internal/types/errors"
"strings" "strings"
"cmd/compile/internal/base" "cmd/compile/internal/base"
@ -243,7 +244,7 @@ func reportInitLoopAndExit(l []*ir.Name) {
} }
fmt.Fprintf(&msg, "\t%v: %v", ir.Line(l[0]), l[0]) fmt.Fprintf(&msg, "\t%v: %v", ir.Line(l[0]), l[0])
base.ErrorfAt(l[0].Pos(), msg.String()) base.ErrorfAt(l[0].Pos(), errors.InvalidInitCycle, msg.String())
base.ErrorExit() base.ErrorExit()
} }

View file

@ -146,7 +146,7 @@ func (s *SymABIs) GenABIWrappers() {
defABI, hasDefABI := s.defs[symName] defABI, hasDefABI := s.defs[symName]
if hasDefABI { if hasDefABI {
if len(fn.Body) != 0 { if len(fn.Body) != 0 {
base.ErrorfAt(fn.Pos(), "%v defined in both Go and assembly", fn) base.ErrorfAt(fn.Pos(), 0, "%v defined in both Go and assembly", fn)
} }
fn.ABI = defABI fn.ABI = defABI
} }
@ -251,7 +251,7 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) {
// below to handle the receiver. Panic if we see this scenario. // below to handle the receiver. Panic if we see this scenario.
ft := f.Nname.Type() ft := f.Nname.Type()
if ft.NumRecvs() != 0 { if ft.NumRecvs() != 0 {
base.ErrorfAt(f.Pos(), "makeABIWrapper support for wrapping methods not implemented") base.ErrorfAt(f.Pos(), 0, "makeABIWrapper support for wrapping methods not implemented")
return return
} }

View file

@ -154,7 +154,7 @@ func (c *nowritebarrierrecChecker) check() {
} }
// Check go:nowritebarrier functions. // Check go:nowritebarrier functions.
if fn.Pragma&ir.Nowritebarrier != 0 && fn.WBPos.IsKnown() { if fn.Pragma&ir.Nowritebarrier != 0 && fn.WBPos.IsKnown() {
base.ErrorfAt(fn.WBPos, "write barrier prohibited") base.ErrorfAt(fn.WBPos, 0, "write barrier prohibited")
} }
} }
@ -185,7 +185,7 @@ func (c *nowritebarrierrecChecker) check() {
fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Nname) fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Nname)
call = funcs[call.target] call = funcs[call.target]
} }
base.ErrorfAt(fn.WBPos, "write barrier prohibited by caller; %v%s", fn.Nname, err.String()) base.ErrorfAt(fn.WBPos, 0, "write barrier prohibited by caller; %v%s", fn.Nname, err.String())
continue continue
} }

View file

@ -327,9 +327,9 @@ func CheckLargeStacks() {
}) })
for _, large := range largeStackFrames { for _, large := range largeStackFrames {
if large.callee != 0 { if large.callee != 0 {
base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args + %d MB callee", large.locals>>20, large.args>>20, large.callee>>20) base.ErrorfAt(large.pos, 0, "stack frame too large (>1GB): %d MB locals + %d MB args + %d MB callee", large.locals>>20, large.args>>20, large.callee>>20)
} else { } else {
base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20) base.ErrorfAt(large.pos, 0, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
} }
} }
} }

View file

@ -214,7 +214,7 @@ func dstringdata(s *obj.LSym, off int, t string, pos src.XPos, what string) int
// causing a cryptic error message by the linker. Check for oversize objects here // causing a cryptic error message by the linker. Check for oversize objects here
// and provide a useful error message instead. // and provide a useful error message instead.
if int64(len(t)) > 2e9 { if int64(len(t)) > 2e9 {
base.ErrorfAt(pos, "%v with length %v is too big", what, len(t)) base.ErrorfAt(pos, 0, "%v with length %v is too big", what, len(t))
return 0 return 0
} }

View file

@ -31,11 +31,11 @@ func embedFileList(v *ir.Name, kind int) []string {
for _, pattern := range e.Patterns { for _, pattern := range e.Patterns {
files, ok := base.Flag.Cfg.Embed.Patterns[pattern] files, ok := base.Flag.Cfg.Embed.Patterns[pattern]
if !ok { if !ok {
base.ErrorfAt(e.Pos, "invalid go:embed: build system did not map pattern: %s", pattern) base.ErrorfAt(e.Pos, 0, "invalid go:embed: build system did not map pattern: %s", pattern)
} }
for _, file := range files { for _, file := range files {
if base.Flag.Cfg.Embed.Files[file] == "" { if base.Flag.Cfg.Embed.Files[file] == "" {
base.ErrorfAt(e.Pos, "invalid go:embed: build system did not map file: %s", file) base.ErrorfAt(e.Pos, 0, "invalid go:embed: build system did not map file: %s", file)
continue continue
} }
if !have[file] { if !have[file] {
@ -57,7 +57,7 @@ func embedFileList(v *ir.Name, kind int) []string {
if kind == embedString || kind == embedBytes { if kind == embedString || kind == embedBytes {
if len(list) > 1 { if len(list) > 1 {
base.ErrorfAt(v.Pos(), "invalid go:embed: multiple files for type %v", v.Type()) base.ErrorfAt(v.Pos(), 0, "invalid go:embed: multiple files for type %v", v.Type())
return nil return nil
} }
} }
@ -109,12 +109,12 @@ func WriteEmbed(v *ir.Name) {
commentPos := (*v.Embed)[0].Pos commentPos := (*v.Embed)[0].Pos
if base.Flag.Cfg.Embed.Patterns == nil { if base.Flag.Cfg.Embed.Patterns == nil {
base.ErrorfAt(commentPos, "invalid go:embed: build system did not supply embed configuration") base.ErrorfAt(commentPos, 0, "invalid go:embed: build system did not supply embed configuration")
return return
} }
kind := embedKind(v.Type()) kind := embedKind(v.Type())
if kind == embedUnknown { if kind == embedUnknown {
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type()) base.ErrorfAt(v.Pos(), 0, "go:embed cannot apply to var of type %v", v.Type())
return return
} }
@ -124,7 +124,7 @@ func WriteEmbed(v *ir.Name) {
file := files[0] file := files[0]
fsym, size, err := fileStringSym(v.Pos(), base.Flag.Cfg.Embed.Files[file], kind == embedString, nil) fsym, size, err := fileStringSym(v.Pos(), base.Flag.Cfg.Embed.Files[file], kind == embedString, nil)
if err != nil { if err != nil {
base.ErrorfAt(v.Pos(), "embed %s: %v", file, err) base.ErrorfAt(v.Pos(), 0, "embed %s: %v", file, err)
} }
sym := v.Linksym() sym := v.Linksym()
off := 0 off := 0
@ -160,7 +160,7 @@ func WriteEmbed(v *ir.Name) {
} else { } else {
fsym, size, err := fileStringSym(v.Pos(), base.Flag.Cfg.Embed.Files[file], true, hash) fsym, size, err := fileStringSym(v.Pos(), base.Flag.Cfg.Embed.Files[file], true, hash)
if err != nil { if err != nil {
base.ErrorfAt(v.Pos(), "embed %s: %v", file, err) base.ErrorfAt(v.Pos(), 0, "embed %s: %v", file, err)
} }
off = objw.SymPtr(slicedata, off, fsym, 0) // data string off = objw.SymPtr(slicedata, off, fsym, 0) // data string
off = objw.Uintptr(slicedata, off, uint64(size)) off = objw.Uintptr(slicedata, off, uint64(size))

View file

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"go/constant" "go/constant"
"go/token" "go/token"
"internal/types/errors"
"math" "math"
"math/big" "math/big"
"strings" "strings"
@ -567,7 +568,7 @@ func OrigConst(n ir.Node, v constant.Value) ir.Node {
if what == "" { if what == "" {
base.Fatalf("unexpected overflow: %v", n.Op()) base.Fatalf("unexpected overflow: %v", n.Op())
} }
base.ErrorfAt(n.Pos(), "constant %v overflow", what) base.ErrorfAt(n.Pos(), errors.NumericOverflow, "constant %v overflow", what)
n.SetType(nil) n.SetType(nil)
return n return n
} }

View file

@ -6,6 +6,7 @@ package typecheck
import ( import (
"fmt" "fmt"
"internal/types/errors"
"sync" "sync"
"cmd/compile/internal/base" "cmd/compile/internal/base"
@ -48,15 +49,15 @@ func Declare(n *ir.Name, ctxt ir.Class) {
// kludgy: TypecheckAllowed means we're past parsing. Eg reflectdata.methodWrapper may declare out of package names later. // kludgy: TypecheckAllowed means we're past parsing. Eg reflectdata.methodWrapper may declare out of package names later.
if !inimport && !TypecheckAllowed && s.Pkg != types.LocalPkg { if !inimport && !TypecheckAllowed && s.Pkg != types.LocalPkg {
base.ErrorfAt(n.Pos(), "cannot declare name %v", s) base.ErrorfAt(n.Pos(), 0, "cannot declare name %v", s)
} }
if ctxt == ir.PEXTERN { if ctxt == ir.PEXTERN {
if s.Name == "init" { if s.Name == "init" {
base.ErrorfAt(n.Pos(), "cannot declare init - must be func") base.ErrorfAt(n.Pos(), errors.InvalidInitDecl, "cannot declare init - must be func")
} }
if s.Name == "main" && s.Pkg.Name == "main" { if s.Name == "main" && s.Pkg.Name == "main" {
base.ErrorfAt(n.Pos(), "cannot declare main - must be func") base.ErrorfAt(n.Pos(), errors.InvalidMainDecl, "cannot declare main - must be func")
} }
Target.Externs = append(Target.Externs, n) Target.Externs = append(Target.Externs, n)
s.Def = n s.Def = n
@ -154,7 +155,7 @@ func checkdupfields(what string, fss ...[]*types.Field) {
continue continue
} }
if seen[f.Sym] { if seen[f.Sym] {
base.ErrorfAt(f.Pos, "duplicate %s %s", what, f.Sym.Name) base.ErrorfAt(f.Pos, errors.DuplicateFieldAndMethod, "duplicate %s %s", what, f.Sym.Name)
continue continue
} }
seen[f.Sym] = true seen[f.Sym] = true

View file

@ -9,6 +9,7 @@ import (
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/src" "cmd/internal/src"
"internal/types/errors"
) )
func RangeExprType(t *types.Type) *types.Type { func RangeExprType(t *types.Type) *types.Type {
@ -37,7 +38,7 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
toomany := false toomany := false
switch t.Kind() { switch t.Kind() {
default: default:
base.ErrorfAt(n.Pos(), "cannot range over %L", n.X) base.ErrorfAt(n.Pos(), errors.InvalidRangeExpr, "cannot range over %L", n.X)
return return
case types.TARRAY, types.TSLICE: case types.TARRAY, types.TSLICE:
@ -50,7 +51,7 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
case types.TCHAN: case types.TCHAN:
if !t.ChanDir().CanRecv() { if !t.ChanDir().CanRecv() {
base.ErrorfAt(n.Pos(), "invalid operation: range %v (receive from send-only type %v)", n.X, n.X.Type()) base.ErrorfAt(n.Pos(), errors.InvalidRangeExpr, "invalid operation: range %v (receive from send-only type %v)", n.X, n.X.Type())
return return
} }
@ -66,7 +67,7 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
} }
if toomany { if toomany {
base.ErrorfAt(n.Pos(), "too many variables in range") base.ErrorfAt(n.Pos(), errors.InvalidIterVar, "too many variables in range")
} }
do := func(nn ir.Node, t *types.Type) { do := func(nn ir.Node, t *types.Type) {
@ -75,7 +76,7 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
nn.SetType(t) nn.SetType(t)
} else if nn.Type() != nil { } else if nn.Type() != nil {
if op, why := Assignop(t, nn.Type()); op == ir.OXXX { if op, why := Assignop(t, nn.Type()); op == ir.OXXX {
base.ErrorfAt(n.Pos(), "cannot assign type %v to %L in range%s", t, nn, why) base.ErrorfAt(n.Pos(), errors.InvalidIterVar, "cannot assign type %v to %L in range%s", t, nn, why)
} }
} }
checkassign(nn) checkassign(nn)
@ -185,10 +186,10 @@ assignOK:
if len(lhs) != cr { if len(lhs) != cr {
if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 { if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
if r.Type() != nil { if r.Type() != nil {
base.ErrorfAt(stmt.Pos(), "assignment mismatch: %d variable%s but %v returns %d value%s", len(lhs), plural(len(lhs)), r.X, cr, plural(cr)) base.ErrorfAt(stmt.Pos(), errors.WrongAssignCount, "assignment mismatch: %d variable%s but %v returns %d value%s", len(lhs), plural(len(lhs)), r.X, cr, plural(cr))
} }
} else { } else {
base.ErrorfAt(stmt.Pos(), "assignment mismatch: %d variable%s but %v value%s", len(lhs), plural(len(lhs)), len(rhs), plural(len(rhs))) base.ErrorfAt(stmt.Pos(), errors.WrongAssignCount, "assignment mismatch: %d variable%s but %v value%s", len(lhs), plural(len(lhs)), len(rhs), plural(len(rhs)))
} }
for i := range lhs { for i := range lhs {
@ -298,7 +299,7 @@ func tcGoDefer(n *ir.GoDeferStmt) {
if orig := ir.Orig(n.Call); orig.Op() == ir.OCONV { if orig := ir.Orig(n.Call); orig.Op() == ir.OCONV {
break break
} }
base.ErrorfAt(n.Pos(), "%s discards result of %v", what, n.Call) base.ErrorfAt(n.Pos(), errors.UnusedResults, "%s discards result of %v", what, n.Call)
return return
} }
@ -379,7 +380,7 @@ func tcSelect(sel *ir.SelectStmt) {
if ncase.Comm == nil { if ncase.Comm == nil {
// default // default
if def != nil { if def != nil {
base.ErrorfAt(ncase.Pos(), "multiple defaults in select (first at %v)", ir.Line(def)) base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in select (first at %v)", ir.Line(def))
} else { } else {
def = ncase def = ncase
} }
@ -403,7 +404,7 @@ func tcSelect(sel *ir.SelectStmt) {
// on the same line). This matches the approach before 1.10. // on the same line). This matches the approach before 1.10.
pos = ncase.Pos() pos = ncase.Pos()
} }
base.ErrorfAt(pos, "select case must be receive, send or assign recv") base.ErrorfAt(pos, errors.InvalidSelectCase, "select case must be receive, send or assign recv")
case ir.OAS: case ir.OAS:
// convert x = <-c into x, _ = <-c // convert x = <-c into x, _ = <-c
@ -417,7 +418,7 @@ func tcSelect(sel *ir.SelectStmt) {
} }
} }
if n.Y.Op() != ir.ORECV { if n.Y.Op() != ir.ORECV {
base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
break break
} }
oselrecv2(n.X, n.Y, n.Def) oselrecv2(n.X, n.Y, n.Def)
@ -425,7 +426,7 @@ func tcSelect(sel *ir.SelectStmt) {
case ir.OAS2RECV: case ir.OAS2RECV:
n := n.(*ir.AssignListStmt) n := n.(*ir.AssignListStmt)
if n.Rhs[0].Op() != ir.ORECV { if n.Rhs[0].Op() != ir.ORECV {
base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
break break
} }
n.SetOp(ir.OSELRECV2) n.SetOp(ir.OSELRECV2)
@ -502,9 +503,9 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
case !types.IsComparable(t): case !types.IsComparable(t):
if t.IsStruct() { if t.IsStruct() {
base.ErrorfAt(n.Pos(), "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type) base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
} else { } else {
base.ErrorfAt(n.Pos(), "cannot switch on %L", n.Tag) base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L", n.Tag)
} }
t = nil t = nil
} }
@ -515,7 +516,7 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
ls := ncase.List ls := ncase.List
if len(ls) == 0 { // default: if len(ls) == 0 { // default:
if defCase != nil { if defCase != nil {
base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase)) base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
} else { } else {
defCase = ncase defCase = ncase
} }
@ -531,17 +532,17 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
} }
if nilonly != "" && !ir.IsNil(n1) { if nilonly != "" && !ir.IsNil(n1) {
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag) base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag)
} else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) { } else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) {
base.ErrorfAt(ncase.Pos(), "invalid case %L in switch (incomparable type)", n1) base.ErrorfAt(ncase.Pos(), errors.UndefinedOp, "invalid case %L in switch (incomparable type)", n1)
} else { } else {
op1, _ := Assignop(n1.Type(), t) op1, _ := Assignop(n1.Type(), t)
op2, _ := Assignop(t, n1.Type()) op2, _ := Assignop(t, n1.Type())
if op1 == ir.OXXX && op2 == ir.OXXX { if op1 == ir.OXXX && op2 == ir.OXXX {
if n.Tag != nil { if n.Tag != nil {
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t) base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t)
} else { } else {
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type()) base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
} }
} }
} }
@ -556,7 +557,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
guard.X = Expr(guard.X) guard.X = Expr(guard.X)
t := guard.X.Type() t := guard.X.Type()
if t != nil && !t.IsInterface() { if t != nil && !t.IsInterface() {
base.ErrorfAt(n.Pos(), "cannot type switch on non-interface value %L", guard.X) base.ErrorfAt(n.Pos(), errors.InvalidTypeSwitch, "cannot type switch on non-interface value %L", guard.X)
t = nil t = nil
} }
@ -564,7 +565,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
// declaration itself. So if there are no cases, we won't // declaration itself. So if there are no cases, we won't
// notice that it went unused. // notice that it went unused.
if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 { if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 {
base.ErrorfAt(v.Pos(), "%v declared but not used", v.Sym()) base.ErrorfAt(v.Pos(), errors.UnusedVar, "%v declared but not used", v.Sym())
} }
var defCase, nilCase ir.Node var defCase, nilCase ir.Node
@ -573,7 +574,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
ls := ncase.List ls := ncase.List
if len(ls) == 0 { // default: if len(ls) == 0 { // default:
if defCase != nil { if defCase != nil {
base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase)) base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
} else { } else {
defCase = ncase defCase = ncase
} }
@ -590,7 +591,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
var ptr int var ptr int
if ir.IsNil(n1) { // case nil: if ir.IsNil(n1) { // case nil:
if nilCase != nil { if nilCase != nil {
base.ErrorfAt(ncase.Pos(), "multiple nil cases in type switch (first at %v)", ir.Line(nilCase)) base.ErrorfAt(ncase.Pos(), errors.DuplicateCase, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
} else { } else {
nilCase = ncase nilCase = ncase
} }
@ -600,18 +601,18 @@ func tcSwitchType(n *ir.SwitchStmt) {
continue continue
} }
if n1.Op() != ir.OTYPE { if n1.Op() != ir.OTYPE {
base.ErrorfAt(ncase.Pos(), "%L is not a type", n1) base.ErrorfAt(ncase.Pos(), errors.NotAType, "%L is not a type", n1)
continue continue
} }
if !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) { if !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) {
if have != nil { if have != nil {
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+ base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v"+
" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", guard.X, n1.Type(), missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) " (wrong type for %v method)\n\thave %v%S\n\twant %v%S", guard.X, n1.Type(), missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 { } else if ptr != 0 {
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+ base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v"+
" (%v method has pointer receiver)", guard.X, n1.Type(), missing.Sym) " (%v method has pointer receiver)", guard.X, n1.Type(), missing.Sym)
} else { } else {
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+ base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v"+
" (missing %v method)", guard.X, n1.Type(), missing.Sym) " (missing %v method)", guard.X, n1.Type(), missing.Sym)
} }
continue continue
@ -659,7 +660,7 @@ func (s *typeSet) add(pos src.XPos, typ *types.Type) {
ls := typ.LinkString() ls := typ.LinkString()
if prev, ok := s.m[ls]; ok { if prev, ok := s.m[ls]; ok {
base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev)) base.ErrorfAt(pos, errors.DuplicateCase, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
return return
} }
s.m[ls] = pos s.m[ls] = pos

View file

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"go/constant" "go/constant"
"go/token" "go/token"
"internal/types/errors"
"strings" "strings"
"cmd/compile/internal/base" "cmd/compile/internal/base"
@ -286,7 +287,7 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
return n return n
} }
} }
base.ErrorfAt(n.Pos(), "invalid recursive type alias %v%s", n, cycleTrace(cycle)) base.ErrorfAt(n.Pos(), errors.InvalidDeclCycle, "invalid recursive type alias %v%s", n, cycleTrace(cycle))
} }
case ir.OLITERAL: case ir.OLITERAL:
@ -294,7 +295,7 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
base.Errorf("%v is not a type", n) base.Errorf("%v is not a type", n)
break break
} }
base.ErrorfAt(n.Pos(), "constant definition loop%s", cycleTrace(cycleFor(n))) base.ErrorfAt(n.Pos(), errors.InvalidInitCycle, "constant definition loop%s", cycleTrace(cycleFor(n)))
} }
if base.Errors() == 0 { if base.Errors() == 0 {

View file

@ -9,6 +9,7 @@ import (
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/internal/src" "cmd/internal/src"
"internal/types/errors"
) )
var PtrSize int var PtrSize int
@ -84,7 +85,7 @@ func expandiface(t *Type) {
case !explicit && Identical(m.Type, prev.Type): case !explicit && Identical(m.Type, prev.Type):
return return
default: default:
base.ErrorfAt(m.Pos, "duplicate method %s", m.Sym.Name) base.ErrorfAt(m.Pos, errors.DuplicateDecl, "duplicate method %s", m.Sym.Name)
} }
methods = append(methods, m) methods = append(methods, m)
} }
@ -147,7 +148,7 @@ func expandiface(t *Type) {
sort.Sort(MethodsByName(methods)) sort.Sort(MethodsByName(methods))
if int64(len(methods)) >= MaxWidth/int64(PtrSize) { if int64(len(methods)) >= MaxWidth/int64(PtrSize) {
base.ErrorfAt(typePos(t), "interface too large") base.ErrorfAt(typePos(t), 0, "interface too large")
} }
for i, m := range methods { for i, m := range methods {
m.Offset = int64(i) * int64(PtrSize) m.Offset = int64(i) * int64(PtrSize)
@ -212,7 +213,7 @@ func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 {
maxwidth = 1<<31 - 1 maxwidth = 1<<31 - 1
} }
if o >= maxwidth { if o >= maxwidth {
base.ErrorfAt(typePos(errtype), "type %L too large", errtype) base.ErrorfAt(typePos(errtype), 0, "type %L too large", errtype)
o = 8 // small but nonzero o = 8 // small but nonzero
} }
} }

View file

@ -8,6 +8,7 @@ import (
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/internal/src" "cmd/internal/src"
"fmt" "fmt"
"internal/types/errors"
"sync" "sync"
) )
@ -1663,7 +1664,7 @@ func (t *Type) SetUnderlying(underlying *Type) {
// Double-check use of type as embedded type. // Double-check use of type as embedded type.
if ft.Embedlineno.IsKnown() { if ft.Embedlineno.IsKnown() {
if t.IsPtr() || t.IsUnsafePtr() { if t.IsPtr() || t.IsUnsafePtr() {
base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer") base.ErrorfAt(ft.Embedlineno, errors.InvalidPtrEmbed, "embedded type cannot be a pointer")
} }
} }
} }

View file

@ -560,7 +560,7 @@ func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
fn := arg.(*ir.ConvExpr).X.(*ir.Name) fn := arg.(*ir.ConvExpr).X.(*ir.Name)
abi := fn.Func.ABI abi := fn.Func.ABI
if abi != wantABI { if abi != wantABI {
base.ErrorfAt(n.Pos(), "internal/abi.%s expects an %v function, %s is defined as %v", name, wantABI, fn.Sym().Name, abi) base.ErrorfAt(n.Pos(), 0, "internal/abi.%s expects an %v function, %s is defined as %v", name, wantABI, fn.Sym().Name, abi)
} }
var e ir.Node = ir.NewLinksymExpr(n.Pos(), fn.Sym().LinksymABI(abi), types.Types[types.TUINTPTR]) var e ir.Node = ir.NewLinksymExpr(n.Pos(), fn.Sym().LinksymABI(abi), types.Types[types.TUINTPTR])
e = ir.NewAddrExpr(n.Pos(), e) e = ir.NewAddrExpr(n.Pos(), e)
@ -570,7 +570,7 @@ func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
// fn is not a defined function. It must be ABIInternal. // fn is not a defined function. It must be ABIInternal.
// Read the address from func value, i.e. *(*uintptr)(idata(fn)). // Read the address from func value, i.e. *(*uintptr)(idata(fn)).
if wantABI != obj.ABIInternal { if wantABI != obj.ABIInternal {
base.ErrorfAt(n.Pos(), "internal/abi.%s does not accept func expression, which is ABIInternal", name) base.ErrorfAt(n.Pos(), 0, "internal/abi.%s does not accept func expression, which is ABIInternal", name)
} }
arg = walkExpr(arg, init) arg = walkExpr(arg, init)
var e ir.Node = ir.NewUnaryExpr(n.Pos(), ir.OIDATA, arg) var e ir.Node = ir.NewUnaryExpr(n.Pos(), ir.OIDATA, arg)