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