Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(10)

Delta Between Two Patch Sets: src/pkg/go/types/builtins.go

Issue 7129046: code review 7129046: go/types: correct result type for append (bug fix) (Closed)
Left Patch Set: diff -r 9a3e56fe880c https://code.google.com/p/go/ Created 12 years, 2 months ago
Right Patch Set: diff -r 39f95f46bdac https://code.google.com/p/go/ Created 12 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // This file implements typechecking of builtin function calls. 5 // This file implements typechecking of builtin function calls.
6 6
7 package types 7 package types
8 8
9 import ( 9 import (
10 "go/ast" 10 "go/ast"
11 "go/token" 11 "go/token"
12 ) 12 )
13 13
14 // builtin typechecks a built-in call. The built-in type is bin, and iota is the current 14 // builtin typechecks a built-in call. The built-in type is bin, and iota is the current
15 // value of iota or -1 if iota doesn't have a value in the current context. The result 15 // value of iota or -1 if iota doesn't have a value in the current context. The result
16 // of the call is returned via x. If the call has type errors, the returned x is marked 16 // of the call is returned via x. If the call has type errors, the returned x is marked
17 // as invalid (x.mode == invalid). 17 // as invalid (x.mode == invalid).
18 // 18 //
19 func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota int) { 19 func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota int) {
20 args := call.Args 20 args := call.Args
21 id := bin.id 21 id := bin.id
22 22
23 // declare before goto's 23 // declare before goto's
24 var arg0 ast.Expr // first argument, if present 24 var arg0 ast.Expr // first argument, if present
25 var utyp0 Type // underlying type of first argument (nil for _Make, _ New, _Trace)
26 25
27 // check argument count 26 // check argument count
28 n := len(args) 27 n := len(args)
29 msg := "" 28 msg := ""
30 if n < bin.nargs { 29 if n < bin.nargs {
31 msg = "not enough" 30 msg = "not enough"
32 } else if !bin.isVariadic && n > bin.nargs { 31 } else if !bin.isVariadic && n > bin.nargs {
33 msg = "too many" 32 msg = "too many"
34 } 33 }
35 if msg != "" { 34 if msg != "" {
36 check.invalidOp(call.Pos(), msg+" arguments for %s (expected %d, found %d)", call, bin.nargs, n) 35 check.invalidOp(call.Pos(), msg+" arguments for %s (expected %d, found %d)", call, bin.nargs, n)
37 goto Error 36 goto Error
38 } 37 }
39 38
40 // common case: evaluate first argument if present; 39 // common case: evaluate first argument if present;
41 // if it is an expression, x has the expression value 40 // if it is an expression, x has the expression value
42 if n > 0 { 41 if n > 0 {
43 arg0 = args[0] 42 arg0 = args[0]
44 switch id { 43 switch id {
45 case _Make, _New, _Trace: 44 case _Make, _New, _Trace:
46 // respective cases below do the work 45 // respective cases below do the work
47 default: 46 default:
48 // argument must be an expression 47 // argument must be an expression
49 check.expr(x, arg0, nil, iota) 48 check.expr(x, arg0, nil, iota)
50 if x.mode == invalid { 49 if x.mode == invalid {
51 goto Error 50 goto Error
52 } 51 }
53 utyp0 = underlying(x.typ)
54 } 52 }
55 } 53 }
56 54
57 switch id { 55 switch id {
58 case _Append: 56 case _Append:
59 » » if _, ok := utyp0.(*Slice); !ok { 57 » » if _, ok := underlying(x.typ).(*Slice); !ok {
60 check.invalidArg(x.pos(), "%s is not a typed slice", x) 58 check.invalidArg(x.pos(), "%s is not a typed slice", x)
61 goto Error 59 goto Error
62 } 60 }
63 resultTyp := x.typ 61 resultTyp := x.typ
64 for _, arg := range args[1:] { 62 for _, arg := range args[1:] {
65 check.expr(x, arg, nil, iota) 63 check.expr(x, arg, nil, iota)
66 if x.mode == invalid { 64 if x.mode == invalid {
67 goto Error 65 goto Error
68 } 66 }
69 // TODO(gri) check assignability 67 // TODO(gri) check assignability
70 } 68 }
71 x.mode = value 69 x.mode = value
72 x.typ = resultTyp 70 x.typ = resultTyp
73 71
74 case _Cap, _Len: 72 case _Cap, _Len:
75 mode := invalid 73 mode := invalid
76 var val interface{} 74 var val interface{}
77 » » switch typ := implicitDeref(utyp0).(type) { 75 » » switch typ := implicitDeref(underlying(x.typ)).(type) {
78 case *Basic: 76 case *Basic:
79 if isString(typ) && id == _Len { 77 if isString(typ) && id == _Len {
80 if x.mode == constant { 78 if x.mode == constant {
81 mode = constant 79 mode = constant
82 val = int64(len(x.val.(string))) 80 val = int64(len(x.val.(string)))
83 } else { 81 } else {
84 mode = value 82 mode = value
85 } 83 }
86 } 84 }
87 85
(...skipping 15 matching lines...) Expand all
103 101
104 if mode == invalid { 102 if mode == invalid {
105 check.invalidArg(x.pos(), "%s for %s", x, bin.name) 103 check.invalidArg(x.pos(), "%s for %s", x, bin.name)
106 goto Error 104 goto Error
107 } 105 }
108 x.mode = mode 106 x.mode = mode
109 x.typ = Typ[Int] 107 x.typ = Typ[Int]
110 x.val = val 108 x.val = val
111 109
112 case _Close: 110 case _Close:
113 » » ch, ok := utyp0.(*Chan) 111 » » ch, ok := underlying(x.typ).(*Chan)
114 if !ok { 112 if !ok {
115 check.invalidArg(x.pos(), "%s is not a channel", x) 113 check.invalidArg(x.pos(), "%s is not a channel", x)
116 goto Error 114 goto Error
117 } 115 }
118 if ch.Dir&ast.SEND == 0 { 116 if ch.Dir&ast.SEND == 0 {
119 check.invalidArg(x.pos(), "%s must not be a receive-only channel", x) 117 check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
120 goto Error 118 goto Error
121 } 119 }
122 x.mode = novalue 120 x.mode = novalue
123 121
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 } 167 }
170 168
171 case _Copy: 169 case _Copy:
172 var y operand 170 var y operand
173 check.expr(&y, args[1], nil, iota) 171 check.expr(&y, args[1], nil, iota)
174 if y.mode == invalid { 172 if y.mode == invalid {
175 goto Error 173 goto Error
176 } 174 }
177 175
178 var dst, src Type 176 var dst, src Type
179 » » if t, ok := utyp0.(*Slice); ok { 177 » » if t, ok := underlying(x.typ).(*Slice); ok {
180 dst = t.Elt 178 dst = t.Elt
181 } 179 }
182 switch t := underlying(y.typ).(type) { 180 switch t := underlying(y.typ).(type) {
183 case *Basic: 181 case *Basic:
184 if isString(y.typ) { 182 if isString(y.typ) {
185 src = Typ[Byte] 183 src = Typ[Byte]
186 } 184 }
187 case *Slice: 185 case *Slice:
188 src = t.Elt 186 src = t.Elt
189 } 187 }
190 188
191 if dst == nil || src == nil { 189 if dst == nil || src == nil {
192 check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y) 190 check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
193 goto Error 191 goto Error
194 } 192 }
195 193
196 if !isIdentical(dst, src) { 194 if !isIdentical(dst, src) {
197 check.invalidArg(x.pos(), "arguments to copy %s and %s h ave different element types %s and %s", x, &y, dst, src) 195 check.invalidArg(x.pos(), "arguments to copy %s and %s h ave different element types %s and %s", x, &y, dst, src)
198 goto Error 196 goto Error
199 } 197 }
200 198
201 x.mode = value 199 x.mode = value
202 x.typ = Typ[Int] 200 x.typ = Typ[Int]
203 201
204 case _Delete: 202 case _Delete:
205 » » m, ok := utyp0.(*Map) 203 » » m, ok := underlying(x.typ).(*Map)
206 if !ok { 204 if !ok {
207 check.invalidArg(x.pos(), "%s is not a map", x) 205 check.invalidArg(x.pos(), "%s is not a map", x)
208 goto Error 206 goto Error
209 } 207 }
210 check.expr(x, args[1], nil, iota) 208 check.expr(x, args[1], nil, iota)
211 if x.mode == invalid { 209 if x.mode == invalid {
212 goto Error 210 goto Error
213 } 211 }
214 if !x.isAssignable(m.Key) { 212 if !x.isAssignable(m.Key) {
215 check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.Key) 213 check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.Key)
216 goto Error 214 goto Error
217 } 215 }
218 x.mode = novalue 216 x.mode = novalue
219 217
220 case _Imag, _Real: 218 case _Imag, _Real:
221 » » if !isComplex(utyp0) { 219 » » if !isComplex(x.typ) {
222 check.invalidArg(x.pos(), "%s must be a complex number", x) 220 check.invalidArg(x.pos(), "%s must be a complex number", x)
223 goto Error 221 goto Error
224 } 222 }
225 if x.mode == constant { 223 if x.mode == constant {
226 // nothing to do for x.val == 0 224 // nothing to do for x.val == 0
227 if !isZeroConst(x.val) { 225 if !isZeroConst(x.val) {
228 c := x.val.(Complex) 226 c := x.val.(Complex)
229 if id == _Real { 227 if id == _Real {
230 x.val = c.Re 228 x.val = c.Re
231 } else { 229 } else {
232 x.val = c.Im 230 x.val = c.Im
233 } 231 }
234 } 232 }
235 } else { 233 } else {
236 x.mode = value 234 x.mode = value
237 } 235 }
238 k := Invalid 236 k := Invalid
239 » » switch utyp0.(*Basic).Kind { 237 » » switch underlying(x.typ).(*Basic).Kind {
240 case Complex64: 238 case Complex64:
241 k = Float32 239 k = Float32
242 case Complex128: 240 case Complex128:
243 k = Float64 241 k = Float64
244 case UntypedComplex: 242 case UntypedComplex:
245 k = UntypedFloat 243 k = UntypedFloat
246 default: 244 default:
247 unreachable() 245 unreachable()
248 } 246 }
249 x.typ = Typ[k] 247 x.typ = Typ[k]
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 329
332 case _Sizeof: 330 case _Sizeof:
333 x.mode = constant 331 x.mode = constant
334 x.val = sizeof(check.ctxt, x.typ) 332 x.val = sizeof(check.ctxt, x.typ)
335 x.typ = Typ[Uintptr] 333 x.typ = Typ[Uintptr]
336 334
337 case _Assert: 335 case _Assert:
338 // assert(pred) causes a typechecker error if pred is false. 336 // assert(pred) causes a typechecker error if pred is false.
339 // The result of assert is the value of pred if there is no erro r. 337 // The result of assert is the value of pred if there is no erro r.
340 // Note: assert is only available in self-test mode. 338 // Note: assert is only available in self-test mode.
341 » » if x.mode != constant || !isBoolean(utyp0) { 339 » » if x.mode != constant || !isBoolean(x.typ) {
342 check.invalidArg(x.pos(), "%s is not a boolean constant" , x) 340 check.invalidArg(x.pos(), "%s is not a boolean constant" , x)
343 goto Error 341 goto Error
344 } 342 }
345 pred, ok := x.val.(bool) 343 pred, ok := x.val.(bool)
346 if !ok { 344 if !ok {
347 check.errorf(x.pos(), "internal error: value of %s shoul d be a boolean constant", x) 345 check.errorf(x.pos(), "internal error: value of %s shoul d be a boolean constant", x)
348 goto Error 346 goto Error
349 } 347 }
350 if !pred { 348 if !pred {
351 check.errorf(call.Pos(), "%s failed", call) 349 check.errorf(call.Pos(), "%s failed", call)
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 return sizeof(ctxt, typ.Elt) * typ.Len 448 return sizeof(ctxt, typ.Elt) * typ.Len
451 case *Struct: 449 case *Struct:
452 var size int64 450 var size int64
453 for _, f := range typ.Fields { 451 for _, f := range typ.Fields {
454 size += sizeof(ctxt, f.Type) 452 size += sizeof(ctxt, f.Type)
455 } 453 }
456 return size 454 return size
457 } 455 }
458 return ctxt.PtrSize // good enough 456 return ctxt.PtrSize // good enough
459 } 457 }
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b