]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/types2/errors.go
[dev.typeparams] merge master into dev.typeparams
[gostls13.git] / src / cmd / compile / internal / types2 / errors.go
1 // UNREVIEWED
2 // Copyright 2012 The Go Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 // This file implements various error reporters.
7
8 package types2
9
10 import (
11         "cmd/compile/internal/syntax"
12         "fmt"
13         "strconv"
14         "strings"
15 )
16
17 func unimplemented() {
18         panic("unimplemented")
19 }
20
21 func assert(p bool) {
22         if !p {
23                 panic("assertion failed")
24         }
25 }
26
27 func unreachable() {
28         panic("unreachable")
29 }
30
31 func (check *Checker) qualifier(pkg *Package) string {
32         // Qualify the package unless it's the package being type-checked.
33         if pkg != check.pkg {
34                 // If the same package name was used by multiple packages, display the full path.
35                 if check.pkgCnt[pkg.name] > 1 {
36                         return strconv.Quote(pkg.path)
37                 }
38                 return pkg.name
39         }
40         return ""
41 }
42
43 func (check *Checker) sprintf(format string, args ...interface{}) string {
44         for i, arg := range args {
45                 switch a := arg.(type) {
46                 case nil:
47                         arg = "<nil>"
48                 case operand:
49                         panic("internal error: should always pass *operand")
50                 case *operand:
51                         arg = operandString(a, check.qualifier)
52                 case syntax.Pos:
53                         arg = a.String()
54                 case syntax.Expr:
55                         arg = ExprString(a)
56                 case Object:
57                         arg = ObjectString(a, check.qualifier)
58                 case Type:
59                         arg = TypeString(a, check.qualifier)
60                 }
61                 args[i] = arg
62         }
63         return fmt.Sprintf(format, args...)
64 }
65
66 func (check *Checker) trace(pos syntax.Pos, format string, args ...interface{}) {
67         fmt.Printf("%s:\t%s%s\n",
68                 pos,
69                 strings.Repeat(".  ", check.indent),
70                 check.sprintf(format, args...),
71         )
72 }
73
74 // dump is only needed for debugging
75 func (check *Checker) dump(format string, args ...interface{}) {
76         fmt.Println(check.sprintf(format, args...))
77 }
78
79 func (check *Checker) err(pos syntax.Pos, msg string, soft bool) {
80         // Cheap trick: Don't report errors with messages containing
81         // "invalid operand" or "invalid type" as those tend to be
82         // follow-on errors which don't add useful information. Only
83         // exclude them if these strings are not at the beginning,
84         // and only if we have at least one error already reported.
85         if check.firstErr != nil && (strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0) {
86                 return
87         }
88
89         err := Error{pos, stripAnnotations(msg), msg, soft}
90         if check.firstErr == nil {
91                 check.firstErr = err
92         }
93
94         if check.conf.Trace {
95                 check.trace(pos, "ERROR: %s", msg)
96         }
97
98         f := check.conf.Error
99         if f == nil {
100                 panic(bailout{}) // report only first error
101         }
102         f(err)
103 }
104
105 type poser interface {
106         Pos() syntax.Pos
107 }
108
109 func (check *Checker) error(at poser, msg string) {
110         check.err(posFor(at), msg, false)
111 }
112
113 func (check *Checker) errorf(at poser, format string, args ...interface{}) {
114         check.err(posFor(at), check.sprintf(format, args...), false)
115 }
116
117 func (check *Checker) softErrorf(at poser, format string, args ...interface{}) {
118         check.err(posFor(at), check.sprintf(format, args...), true)
119 }
120
121 func (check *Checker) invalidASTf(at poser, format string, args ...interface{}) {
122         check.errorf(at, "invalid AST: "+format, args...)
123 }
124
125 func (check *Checker) invalidArgf(at poser, format string, args ...interface{}) {
126         check.errorf(at, "invalid argument: "+format, args...)
127 }
128
129 func (check *Checker) invalidOpf(at poser, format string, args ...interface{}) {
130         check.errorf(at, "invalid operation: "+format, args...)
131 }
132
133 // posFor reports the left (= start) position of at.
134 func posFor(at poser) syntax.Pos {
135         switch x := at.(type) {
136         case *operand:
137                 if x.expr != nil {
138                         return startPos(x.expr)
139                 }
140         case syntax.Node:
141                 return startPos(x)
142         }
143         return at.Pos()
144 }
145
146 // stripAnnotations removes internal (type) annotations from s.
147 func stripAnnotations(s string) string {
148         var b strings.Builder
149         for _, r := range s {
150                 // strip #'s and subscript digits
151                 if r != instanceMarker && !('₀' <= r && r < '₀'+10) { // '₀' == U+2080
152                         b.WriteRune(r)
153                 }
154         }
155         if b.Len() < len(s) {
156                 return b.String()
157         }
158         return s
159 }