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