]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/typecheck/expr.go
cmd/compile: do not fatal when typechecking conversion expression
[gostls13.git] / src / cmd / compile / internal / typecheck / expr.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package typecheck
6
7 import (
8         "fmt"
9         "go/constant"
10         "go/token"
11         "internal/types/errors"
12         "strings"
13
14         "cmd/compile/internal/base"
15         "cmd/compile/internal/ir"
16         "cmd/compile/internal/types"
17         "cmd/internal/src"
18 )
19
20 func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
21         if l.Type() == nil || r.Type() == nil {
22                 return l, r, nil
23         }
24
25         r = DefaultLit(r, types.Types[types.TUINT])
26         t := r.Type()
27         if !t.IsInteger() {
28                 base.Errorf("invalid operation: %v (shift count type %v, must be integer)", n, r.Type())
29                 return l, r, nil
30         }
31         t = l.Type()
32         if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() {
33                 base.Errorf("invalid operation: %v (shift of type %v)", n, t)
34                 return l, r, nil
35         }
36
37         // no DefaultLit for left
38         // the outer context gives the type
39         t = l.Type()
40         if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL {
41                 t = types.UntypedInt
42         }
43         return l, r, t
44 }
45
46 // tcArith typechecks operands of a binary arithmetic expression.
47 // The result of tcArith MUST be assigned back to original operands,
48 // t is the type of the expression, and should be set by the caller. e.g:
49 //
50 //      n.X, n.Y, t = tcArith(n, op, n.X, n.Y)
51 //      n.SetType(t)
52 func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
53         l, r = defaultlit2(l, r, false)
54         if l.Type() == nil || r.Type() == nil {
55                 return l, r, nil
56         }
57         t := l.Type()
58         if t.Kind() == types.TIDEAL {
59                 t = r.Type()
60         }
61         aop := ir.OXXX
62         if n.Op().IsCmp() && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
63                 // comparison is okay as long as one side is
64                 // assignable to the other.  convert so they have
65                 // the same type.
66                 //
67                 // the only conversion that isn't a no-op is concrete == interface.
68                 // in that case, check comparability of the concrete type.
69                 // The conversion allocates, so only do it if the concrete type is huge.
70                 converted := false
71                 if r.Type().Kind() != types.TBLANK {
72                         aop, _ = Assignop(l.Type(), r.Type())
73                         if aop != ir.OXXX {
74                                 if r.Type().IsInterface() && !l.Type().IsInterface() && !types.IsComparable(l.Type()) {
75                                         base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type()))
76                                         return l, r, nil
77                                 }
78
79                                 types.CalcSize(l.Type())
80                                 if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Size() >= 1<<16 {
81                                         l = ir.NewConvExpr(base.Pos, aop, r.Type(), l)
82                                         l.SetTypecheck(1)
83                                 }
84
85                                 t = r.Type()
86                                 converted = true
87                         }
88                 }
89
90                 if !converted && l.Type().Kind() != types.TBLANK {
91                         aop, _ = Assignop(r.Type(), l.Type())
92                         if aop != ir.OXXX {
93                                 if l.Type().IsInterface() && !r.Type().IsInterface() && !types.IsComparable(r.Type()) {
94                                         base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type()))
95                                         return l, r, nil
96                                 }
97
98                                 types.CalcSize(r.Type())
99                                 if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Size() >= 1<<16 {
100                                         r = ir.NewConvExpr(base.Pos, aop, l.Type(), r)
101                                         r.SetTypecheck(1)
102                                 }
103
104                                 t = l.Type()
105                         }
106                 }
107         }
108
109         if t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
110                 l, r = defaultlit2(l, r, true)
111                 if l.Type() == nil || r.Type() == nil {
112                         return l, r, nil
113                 }
114                 if l.Type().IsInterface() == r.Type().IsInterface() || aop == 0 {
115                         base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
116                         return l, r, nil
117                 }
118         }
119
120         if t.Kind() == types.TIDEAL {
121                 t = mixUntyped(l.Type(), r.Type())
122         }
123         if dt := defaultType(t); !okfor[op][dt.Kind()] {
124                 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t))
125                 return l, r, nil
126         }
127
128         // okfor allows any array == array, map == map, func == func.
129         // restrict to slice/map/func == nil and nil == slice/map/func.
130         if l.Type().IsArray() && !types.IsComparable(l.Type()) {
131                 base.Errorf("invalid operation: %v (%v cannot be compared)", n, l.Type())
132                 return l, r, nil
133         }
134
135         if l.Type().IsSlice() && !ir.IsNil(l) && !ir.IsNil(r) {
136                 base.Errorf("invalid operation: %v (slice can only be compared to nil)", n)
137                 return l, r, nil
138         }
139
140         if l.Type().IsMap() && !ir.IsNil(l) && !ir.IsNil(r) {
141                 base.Errorf("invalid operation: %v (map can only be compared to nil)", n)
142                 return l, r, nil
143         }
144
145         if l.Type().Kind() == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) {
146                 base.Errorf("invalid operation: %v (func can only be compared to nil)", n)
147                 return l, r, nil
148         }
149
150         if l.Type().IsStruct() {
151                 if f := types.IncomparableField(l.Type()); f != nil {
152                         base.Errorf("invalid operation: %v (struct containing %v cannot be compared)", n, f.Type)
153                         return l, r, nil
154                 }
155         }
156
157         return l, r, t
158 }
159
160 // The result of tcCompLit MUST be assigned back to n, e.g.
161 //
162 //      n.Left = tcCompLit(n.Left)
163 func tcCompLit(n *ir.CompLitExpr) (res ir.Node) {
164         if base.EnableTrace && base.Flag.LowerT {
165                 defer tracePrint("tcCompLit", n)(&res)
166         }
167
168         lno := base.Pos
169         defer func() {
170                 base.Pos = lno
171         }()
172
173         ir.SetPos(n)
174
175         t := n.Type()
176         base.AssertfAt(t != nil, n.Pos(), "missing type in composite literal")
177
178         switch t.Kind() {
179         default:
180                 base.Errorf("invalid composite literal type %v", t)
181                 n.SetType(nil)
182
183         case types.TARRAY:
184                 typecheckarraylit(t.Elem(), t.NumElem(), n.List, "array literal")
185                 n.SetOp(ir.OARRAYLIT)
186
187         case types.TSLICE:
188                 length := typecheckarraylit(t.Elem(), -1, n.List, "slice literal")
189                 n.SetOp(ir.OSLICELIT)
190                 n.Len = length
191
192         case types.TMAP:
193                 for i3, l := range n.List {
194                         ir.SetPos(l)
195                         if l.Op() != ir.OKEY {
196                                 n.List[i3] = Expr(l)
197                                 base.Errorf("missing key in map literal")
198                                 continue
199                         }
200                         l := l.(*ir.KeyExpr)
201
202                         r := l.Key
203                         r = Expr(r)
204                         l.Key = AssignConv(r, t.Key(), "map key")
205
206                         r = l.Value
207                         r = Expr(r)
208                         l.Value = AssignConv(r, t.Elem(), "map value")
209                 }
210
211                 n.SetOp(ir.OMAPLIT)
212
213         case types.TSTRUCT:
214                 // Need valid field offsets for Xoffset below.
215                 types.CalcSize(t)
216
217                 errored := false
218                 if len(n.List) != 0 && nokeys(n.List) {
219                         // simple list of variables
220                         ls := n.List
221                         for i, n1 := range ls {
222                                 ir.SetPos(n1)
223                                 n1 = Expr(n1)
224                                 ls[i] = n1
225                                 if i >= t.NumFields() {
226                                         if !errored {
227                                                 base.Errorf("too many values in %v", n)
228                                                 errored = true
229                                         }
230                                         continue
231                                 }
232
233                                 f := t.Field(i)
234                                 s := f.Sym
235
236                                 // Do the test for assigning to unexported fields.
237                                 // But if this is an instantiated function, then
238                                 // the function has already been typechecked. In
239                                 // that case, don't do the test, since it can fail
240                                 // for the closure structs created in
241                                 // walkClosure(), because the instantiated
242                                 // function is compiled as if in the source
243                                 // package of the generic function.
244                                 if !(ir.CurFunc != nil && strings.Index(ir.CurFunc.Nname.Sym().Name, "[") >= 0) {
245                                         if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg {
246                                                 base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
247                                         }
248                                 }
249                                 // No pushtype allowed here. Must name fields for that.
250                                 n1 = AssignConv(n1, f.Type, "field value")
251                                 ls[i] = ir.NewStructKeyExpr(base.Pos, f, n1)
252                         }
253                         if len(ls) < t.NumFields() {
254                                 base.Errorf("too few values in %v", n)
255                         }
256                 } else {
257                         hash := make(map[string]bool)
258
259                         // keyed list
260                         ls := n.List
261                         for i, n := range ls {
262                                 ir.SetPos(n)
263
264                                 sk, ok := n.(*ir.StructKeyExpr)
265                                 if !ok {
266                                         kv, ok := n.(*ir.KeyExpr)
267                                         if !ok {
268                                                 if !errored {
269                                                         base.Errorf("mixture of field:value and value initializers")
270                                                         errored = true
271                                                 }
272                                                 ls[i] = Expr(n)
273                                                 continue
274                                         }
275
276                                         sk = tcStructLitKey(t, kv)
277                                         if sk == nil {
278                                                 continue
279                                         }
280
281                                         fielddup(sk.Sym().Name, hash)
282                                 }
283
284                                 // No pushtype allowed here. Tried and rejected.
285                                 sk.Value = Expr(sk.Value)
286                                 sk.Value = AssignConv(sk.Value, sk.Field.Type, "field value")
287                                 ls[i] = sk
288                         }
289                 }
290
291                 n.SetOp(ir.OSTRUCTLIT)
292         }
293
294         return n
295 }
296
297 // tcStructLitKey typechecks an OKEY node that appeared within a
298 // struct literal.
299 func tcStructLitKey(typ *types.Type, kv *ir.KeyExpr) *ir.StructKeyExpr {
300         key := kv.Key
301
302         sym := key.Sym()
303
304         // An OXDOT uses the Sym field to hold
305         // the field to the right of the dot,
306         // so s will be non-nil, but an OXDOT
307         // is never a valid struct literal key.
308         if sym == nil || sym.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || sym.IsBlank() {
309                 base.Errorf("invalid field name %v in struct initializer", key)
310                 return nil
311         }
312
313         if f := Lookdot1(nil, sym, typ, typ.Fields(), 0); f != nil {
314                 return ir.NewStructKeyExpr(kv.Pos(), f, kv.Value)
315         }
316
317         if ci := Lookdot1(nil, sym, typ, typ.Fields(), 2); ci != nil { // Case-insensitive lookup.
318                 if visible(ci.Sym) {
319                         base.Errorf("unknown field '%v' in struct literal of type %v (but does have %v)", sym, typ, ci.Sym)
320                 } else if nonexported(sym) && sym.Name == ci.Sym.Name { // Ensure exactness before the suggestion.
321                         base.Errorf("cannot refer to unexported field '%v' in struct literal of type %v", sym, typ)
322                 } else {
323                         base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ)
324                 }
325                 return nil
326         }
327
328         var f *types.Field
329         p, _ := dotpath(sym, typ, &f, true)
330         if p == nil || f.IsMethod() {
331                 base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ)
332                 return nil
333         }
334
335         // dotpath returns the parent embedded types in reverse order.
336         var ep []string
337         for ei := len(p) - 1; ei >= 0; ei-- {
338                 ep = append(ep, p[ei].field.Sym.Name)
339         }
340         ep = append(ep, sym.Name)
341         base.Errorf("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), typ)
342         return nil
343 }
344
345 // tcConv typechecks an OCONV node.
346 func tcConv(n *ir.ConvExpr) ir.Node {
347         types.CheckSize(n.Type()) // ensure width is calculated for backend
348         n.X = Expr(n.X)
349         n.X = convlit1(n.X, n.Type(), true, nil)
350         t := n.X.Type()
351         if t == nil || n.Type() == nil {
352                 n.SetType(nil)
353                 return n
354         }
355         op, why := Convertop(n.X.Op() == ir.OLITERAL, t, n.Type())
356         if op == ir.OXXX {
357                 // Due to //go:nointerface, we may be stricter than types2 here (#63333).
358                 base.ErrorfAt(n.Pos(), errors.InvalidConversion, "cannot convert %L to type %v%s", n.X, n.Type(), why)
359                 n.SetType(nil)
360                 return n
361         }
362
363         n.SetOp(op)
364         switch n.Op() {
365         case ir.OCONVNOP:
366                 if t.Kind() == n.Type().Kind() {
367                         switch t.Kind() {
368                         case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
369                                 // Floating point casts imply rounding and
370                                 // so the conversion must be kept.
371                                 n.SetOp(ir.OCONV)
372                         }
373                 }
374
375         // do not convert to []byte literal. See CL 125796.
376         // generated code and compiler memory footprint is better without it.
377         case ir.OSTR2BYTES:
378                 // ok
379
380         case ir.OSTR2RUNES:
381                 if n.X.Op() == ir.OLITERAL {
382                         return stringtoruneslit(n)
383                 }
384
385         case ir.OBYTES2STR:
386                 if t.Elem() != types.ByteType && t.Elem() != types.Types[types.TUINT8] {
387                         // If t is a slice of a user-defined byte type B (not uint8
388                         // or byte), then add an extra CONVNOP from []B to []byte, so
389                         // that the call to slicebytetostring() added in walk will
390                         // typecheck correctly.
391                         n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.ByteType), n.X)
392                         n.X.SetTypecheck(1)
393                 }
394
395         case ir.ORUNES2STR:
396                 if t.Elem() != types.RuneType && t.Elem() != types.Types[types.TINT32] {
397                         // If t is a slice of a user-defined rune type B (not uint32
398                         // or rune), then add an extra CONVNOP from []B to []rune, so
399                         // that the call to slicerunetostring() added in walk will
400                         // typecheck correctly.
401                         n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.RuneType), n.X)
402                         n.X.SetTypecheck(1)
403                 }
404
405         }
406         return n
407 }
408
409 // DotField returns a field selector expression that selects the
410 // index'th field of the given expression, which must be of struct or
411 // pointer-to-struct type.
412 func DotField(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
413         op, typ := ir.ODOT, x.Type()
414         if typ.IsPtr() {
415                 op, typ = ir.ODOTPTR, typ.Elem()
416         }
417         if !typ.IsStruct() {
418                 base.FatalfAt(pos, "DotField of non-struct: %L", x)
419         }
420
421         // TODO(mdempsky): This is the backend's responsibility.
422         types.CalcSize(typ)
423
424         field := typ.Field(index)
425         return dot(pos, field.Type, op, x, field)
426 }
427
428 func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Field) *ir.SelectorExpr {
429         n := ir.NewSelectorExpr(pos, op, x, selection.Sym)
430         n.Selection = selection
431         n.SetType(typ)
432         n.SetTypecheck(1)
433         return n
434 }
435
436 // XDotMethod returns an expression representing the field selection
437 // x.sym. If any implicit field selection are necessary, those are
438 // inserted too.
439 func XDotField(pos src.XPos, x ir.Node, sym *types.Sym) *ir.SelectorExpr {
440         n := Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
441         if n.Op() != ir.ODOT && n.Op() != ir.ODOTPTR {
442                 base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
443         }
444         return n
445 }
446
447 // XDotMethod returns an expression representing the method value
448 // x.sym (i.e., x is a value, not a type). If any implicit field
449 // selection are necessary, those are inserted too.
450 //
451 // If callee is true, the result is an ODOTMETH/ODOTINTER, otherwise
452 // an OMETHVALUE.
453 func XDotMethod(pos src.XPos, x ir.Node, sym *types.Sym, callee bool) *ir.SelectorExpr {
454         n := ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)
455         if callee {
456                 n = Callee(n).(*ir.SelectorExpr)
457                 if n.Op() != ir.ODOTMETH && n.Op() != ir.ODOTINTER {
458                         base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
459                 }
460         } else {
461                 n = Expr(n).(*ir.SelectorExpr)
462                 if n.Op() != ir.OMETHVALUE {
463                         base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
464                 }
465         }
466         return n
467 }
468
469 // tcDot typechecks an OXDOT or ODOT node.
470 func tcDot(n *ir.SelectorExpr, top int) ir.Node {
471         if n.Op() == ir.OXDOT {
472                 n = AddImplicitDots(n)
473                 n.SetOp(ir.ODOT)
474                 if n.X == nil {
475                         n.SetType(nil)
476                         return n
477                 }
478         }
479
480         n.X = Expr(n.X)
481         n.X = DefaultLit(n.X, nil)
482
483         t := n.X.Type()
484         if t == nil {
485                 base.UpdateErrorDot(ir.Line(n), fmt.Sprint(n.X), fmt.Sprint(n))
486                 n.SetType(nil)
487                 return n
488         }
489
490         if n.X.Op() == ir.OTYPE {
491                 base.FatalfAt(n.Pos(), "use NewMethodExpr to construct OMETHEXPR")
492         }
493
494         if t.IsPtr() && !t.Elem().IsInterface() {
495                 t = t.Elem()
496                 if t == nil {
497                         n.SetType(nil)
498                         return n
499                 }
500                 n.SetOp(ir.ODOTPTR)
501                 types.CheckSize(t)
502         }
503
504         if n.Sel.IsBlank() {
505                 base.Errorf("cannot refer to blank field or method")
506                 n.SetType(nil)
507                 return n
508         }
509
510         if Lookdot(n, t, 0) == nil {
511                 // Legitimate field or method lookup failed, try to explain the error
512                 switch {
513                 case t.IsEmptyInterface():
514                         base.Errorf("%v undefined (type %v is interface with no methods)", n, n.X.Type())
515
516                 case t.IsPtr() && t.Elem().IsInterface():
517                         // Pointer to interface is almost always a mistake.
518                         base.Errorf("%v undefined (type %v is pointer to interface, not interface)", n, n.X.Type())
519
520                 case Lookdot(n, t, 1) != nil:
521                         // Field or method matches by name, but it is not exported.
522                         base.Errorf("%v undefined (cannot refer to unexported field or method %v)", n, n.Sel)
523
524                 default:
525                         if mt := Lookdot(n, t, 2); mt != nil && visible(mt.Sym) { // Case-insensitive lookup.
526                                 base.Errorf("%v undefined (type %v has no field or method %v, but does have %v)", n, n.X.Type(), n.Sel, mt.Sym)
527                         } else {
528                                 base.Errorf("%v undefined (type %v has no field or method %v)", n, n.X.Type(), n.Sel)
529                         }
530                 }
531                 n.SetType(nil)
532                 return n
533         }
534
535         if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 {
536                 n.SetOp(ir.OMETHVALUE)
537                 n.SetType(NewMethodType(n.Type(), nil))
538         }
539         return n
540 }
541
542 // tcDotType typechecks an ODOTTYPE node.
543 func tcDotType(n *ir.TypeAssertExpr) ir.Node {
544         n.X = Expr(n.X)
545         n.X = DefaultLit(n.X, nil)
546         l := n.X
547         t := l.Type()
548         if t == nil {
549                 n.SetType(nil)
550                 return n
551         }
552         if !t.IsInterface() {
553                 base.Errorf("invalid type assertion: %v (non-interface type %v on left)", n, t)
554                 n.SetType(nil)
555                 return n
556         }
557
558         base.AssertfAt(n.Type() != nil, n.Pos(), "missing type: %v", n)
559
560         if n.Type() != nil && !n.Type().IsInterface() {
561                 why := ImplementsExplain(n.Type(), t)
562                 if why != "" {
563                         base.Fatalf("impossible type assertion:\n\t%s", why)
564                         n.SetType(nil)
565                         return n
566                 }
567         }
568         return n
569 }
570
571 // tcITab typechecks an OITAB node.
572 func tcITab(n *ir.UnaryExpr) ir.Node {
573         n.X = Expr(n.X)
574         t := n.X.Type()
575         if t == nil {
576                 n.SetType(nil)
577                 return n
578         }
579         if !t.IsInterface() {
580                 base.Fatalf("OITAB of %v", t)
581         }
582         n.SetType(types.NewPtr(types.Types[types.TUINTPTR]))
583         return n
584 }
585
586 // tcIndex typechecks an OINDEX node.
587 func tcIndex(n *ir.IndexExpr) ir.Node {
588         n.X = Expr(n.X)
589         n.X = DefaultLit(n.X, nil)
590         n.X = implicitstar(n.X)
591         l := n.X
592         n.Index = Expr(n.Index)
593         r := n.Index
594         t := l.Type()
595         if t == nil || r.Type() == nil {
596                 n.SetType(nil)
597                 return n
598         }
599         switch t.Kind() {
600         default:
601                 base.Errorf("invalid operation: %v (type %v does not support indexing)", n, t)
602                 n.SetType(nil)
603                 return n
604
605         case types.TSTRING, types.TARRAY, types.TSLICE:
606                 n.Index = indexlit(n.Index)
607                 if t.IsString() {
608                         n.SetType(types.ByteType)
609                 } else {
610                         n.SetType(t.Elem())
611                 }
612                 why := "string"
613                 if t.IsArray() {
614                         why = "array"
615                 } else if t.IsSlice() {
616                         why = "slice"
617                 }
618
619                 if n.Index.Type() != nil && !n.Index.Type().IsInteger() {
620                         base.Errorf("non-integer %s index %v", why, n.Index)
621                         return n
622                 }
623
624                 if !n.Bounded() && ir.IsConst(n.Index, constant.Int) {
625                         x := n.Index.Val()
626                         if constant.Sign(x) < 0 {
627                                 base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Index)
628                         } else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
629                                 base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Index, t.NumElem())
630                         } else if ir.IsConst(n.X, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.X))))) {
631                                 base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Index, len(ir.StringVal(n.X)))
632                         } else if ir.ConstOverflow(x, types.Types[types.TINT]) {
633                                 base.Errorf("invalid %s index %v (index too large)", why, n.Index)
634                         }
635                 }
636
637         case types.TMAP:
638                 n.Index = AssignConv(n.Index, t.Key(), "map index")
639                 n.SetType(t.Elem())
640                 n.SetOp(ir.OINDEXMAP)
641                 n.Assigned = false
642         }
643         return n
644 }
645
646 // tcLenCap typechecks an OLEN or OCAP node.
647 func tcLenCap(n *ir.UnaryExpr) ir.Node {
648         n.X = Expr(n.X)
649         n.X = DefaultLit(n.X, nil)
650         n.X = implicitstar(n.X)
651         l := n.X
652         t := l.Type()
653         if t == nil {
654                 n.SetType(nil)
655                 return n
656         }
657
658         var ok bool
659         if n.Op() == ir.OLEN {
660                 ok = okforlen[t.Kind()]
661         } else {
662                 ok = okforcap[t.Kind()]
663         }
664         if !ok {
665                 base.Errorf("invalid argument %L for %v", l, n.Op())
666                 n.SetType(nil)
667                 return n
668         }
669
670         n.SetType(types.Types[types.TINT])
671         return n
672 }
673
674 // tcUnsafeData typechecks an OUNSAFESLICEDATA or OUNSAFESTRINGDATA node.
675 func tcUnsafeData(n *ir.UnaryExpr) ir.Node {
676         n.X = Expr(n.X)
677         n.X = DefaultLit(n.X, nil)
678         l := n.X
679         t := l.Type()
680         if t == nil {
681                 n.SetType(nil)
682                 return n
683         }
684
685         var kind types.Kind
686         if n.Op() == ir.OUNSAFESLICEDATA {
687                 kind = types.TSLICE
688         } else {
689                 /* kind is string */
690                 kind = types.TSTRING
691         }
692
693         if t.Kind() != kind {
694                 base.Errorf("invalid argument %L for %v", l, n.Op())
695                 n.SetType(nil)
696                 return n
697         }
698
699         if kind == types.TSTRING {
700                 t = types.ByteType
701         } else {
702                 t = t.Elem()
703         }
704         n.SetType(types.NewPtr(t))
705         return n
706 }
707
708 // tcRecv typechecks an ORECV node.
709 func tcRecv(n *ir.UnaryExpr) ir.Node {
710         n.X = Expr(n.X)
711         n.X = DefaultLit(n.X, nil)
712         l := n.X
713         t := l.Type()
714         if t == nil {
715                 n.SetType(nil)
716                 return n
717         }
718         if !t.IsChan() {
719                 base.Errorf("invalid operation: %v (receive from non-chan type %v)", n, t)
720                 n.SetType(nil)
721                 return n
722         }
723
724         if !t.ChanDir().CanRecv() {
725                 base.Errorf("invalid operation: %v (receive from send-only type %v)", n, t)
726                 n.SetType(nil)
727                 return n
728         }
729
730         n.SetType(t.Elem())
731         return n
732 }
733
734 // tcSPtr typechecks an OSPTR node.
735 func tcSPtr(n *ir.UnaryExpr) ir.Node {
736         n.X = Expr(n.X)
737         t := n.X.Type()
738         if t == nil {
739                 n.SetType(nil)
740                 return n
741         }
742         if !t.IsSlice() && !t.IsString() {
743                 base.Fatalf("OSPTR of %v", t)
744         }
745         if t.IsString() {
746                 n.SetType(types.NewPtr(types.Types[types.TUINT8]))
747         } else {
748                 n.SetType(types.NewPtr(t.Elem()))
749         }
750         return n
751 }
752
753 // tcSlice typechecks an OSLICE or OSLICE3 node.
754 func tcSlice(n *ir.SliceExpr) ir.Node {
755         n.X = DefaultLit(Expr(n.X), nil)
756         n.Low = indexlit(Expr(n.Low))
757         n.High = indexlit(Expr(n.High))
758         n.Max = indexlit(Expr(n.Max))
759         hasmax := n.Op().IsSlice3()
760         l := n.X
761         if l.Type() == nil {
762                 n.SetType(nil)
763                 return n
764         }
765         if l.Type().IsArray() {
766                 if !ir.IsAddressable(n.X) {
767                         base.Errorf("invalid operation %v (slice of unaddressable value)", n)
768                         n.SetType(nil)
769                         return n
770                 }
771
772                 addr := NodAddr(n.X)
773                 addr.SetImplicit(true)
774                 n.X = Expr(addr)
775                 l = n.X
776         }
777         t := l.Type()
778         var tp *types.Type
779         if t.IsString() {
780                 if hasmax {
781                         base.Errorf("invalid operation %v (3-index slice of string)", n)
782                         n.SetType(nil)
783                         return n
784                 }
785                 n.SetType(t)
786                 n.SetOp(ir.OSLICESTR)
787         } else if t.IsPtr() && t.Elem().IsArray() {
788                 tp = t.Elem()
789                 n.SetType(types.NewSlice(tp.Elem()))
790                 types.CalcSize(n.Type())
791                 if hasmax {
792                         n.SetOp(ir.OSLICE3ARR)
793                 } else {
794                         n.SetOp(ir.OSLICEARR)
795                 }
796         } else if t.IsSlice() {
797                 n.SetType(t)
798         } else {
799                 base.Errorf("cannot slice %v (type %v)", l, t)
800                 n.SetType(nil)
801                 return n
802         }
803
804         if n.Low != nil && !checksliceindex(l, n.Low, tp) {
805                 n.SetType(nil)
806                 return n
807         }
808         if n.High != nil && !checksliceindex(l, n.High, tp) {
809                 n.SetType(nil)
810                 return n
811         }
812         if n.Max != nil && !checksliceindex(l, n.Max, tp) {
813                 n.SetType(nil)
814                 return n
815         }
816         if !checksliceconst(n.Low, n.High) || !checksliceconst(n.Low, n.Max) || !checksliceconst(n.High, n.Max) {
817                 n.SetType(nil)
818                 return n
819         }
820         return n
821 }
822
823 // tcSliceHeader typechecks an OSLICEHEADER node.
824 func tcSliceHeader(n *ir.SliceHeaderExpr) ir.Node {
825         // Errors here are Fatalf instead of Errorf because only the compiler
826         // can construct an OSLICEHEADER node.
827         // Components used in OSLICEHEADER that are supplied by parsed source code
828         // have already been typechecked in e.g. OMAKESLICE earlier.
829         t := n.Type()
830         if t == nil {
831                 base.Fatalf("no type specified for OSLICEHEADER")
832         }
833
834         if !t.IsSlice() {
835                 base.Fatalf("invalid type %v for OSLICEHEADER", n.Type())
836         }
837
838         if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
839                 base.Fatalf("need unsafe.Pointer for OSLICEHEADER")
840         }
841
842         n.Ptr = Expr(n.Ptr)
843         n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
844         n.Cap = DefaultLit(Expr(n.Cap), types.Types[types.TINT])
845
846         if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
847                 base.Fatalf("len for OSLICEHEADER must be non-negative")
848         }
849
850         if ir.IsConst(n.Cap, constant.Int) && ir.Int64Val(n.Cap) < 0 {
851                 base.Fatalf("cap for OSLICEHEADER must be non-negative")
852         }
853
854         if ir.IsConst(n.Len, constant.Int) && ir.IsConst(n.Cap, constant.Int) && constant.Compare(n.Len.Val(), token.GTR, n.Cap.Val()) {
855                 base.Fatalf("len larger than cap for OSLICEHEADER")
856         }
857
858         return n
859 }
860
861 // tcStringHeader typechecks an OSTRINGHEADER node.
862 func tcStringHeader(n *ir.StringHeaderExpr) ir.Node {
863         t := n.Type()
864         if t == nil {
865                 base.Fatalf("no type specified for OSTRINGHEADER")
866         }
867
868         if !t.IsString() {
869                 base.Fatalf("invalid type %v for OSTRINGHEADER", n.Type())
870         }
871
872         if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
873                 base.Fatalf("need unsafe.Pointer for OSTRINGHEADER")
874         }
875
876         n.Ptr = Expr(n.Ptr)
877         n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
878
879         if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
880                 base.Fatalf("len for OSTRINGHEADER must be non-negative")
881         }
882
883         return n
884 }
885
886 // tcStar typechecks an ODEREF node, which may be an expression or a type.
887 func tcStar(n *ir.StarExpr, top int) ir.Node {
888         n.X = typecheck(n.X, ctxExpr|ctxType)
889         l := n.X
890         t := l.Type()
891         if t == nil {
892                 n.SetType(nil)
893                 return n
894         }
895
896         // TODO(mdempsky): Remove (along with ctxType above) once I'm
897         // confident this code path isn't needed any more.
898         if l.Op() == ir.OTYPE {
899                 base.Fatalf("unexpected type in deref expression: %v", l)
900         }
901
902         if !t.IsPtr() {
903                 if top&(ctxExpr|ctxStmt) != 0 {
904                         base.Errorf("invalid indirect of %L", n.X)
905                         n.SetType(nil)
906                         return n
907                 }
908                 base.Errorf("%v is not a type", l)
909                 return n
910         }
911
912         n.SetType(t.Elem())
913         return n
914 }
915
916 // tcUnaryArith typechecks a unary arithmetic expression.
917 func tcUnaryArith(n *ir.UnaryExpr) ir.Node {
918         n.X = Expr(n.X)
919         l := n.X
920         t := l.Type()
921         if t == nil {
922                 n.SetType(nil)
923                 return n
924         }
925         if !okfor[n.Op()][defaultType(t).Kind()] {
926                 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t))
927                 n.SetType(nil)
928                 return n
929         }
930
931         n.SetType(t)
932         return n
933 }