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
5package typecheck
6
7import (
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
20func 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)
52func 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)
163func 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.Contains(ir.CurFunc.Nname.Sym().Name, "[")) {
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.
299func 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.
346func 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.
412func 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
428func 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// XDotField returns an expression representing the field selection
437// x.sym. If any implicit field selection are necessary, those are
438// inserted too.
439func 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.
453func 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.
470func 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.
543func 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.
572func 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.
587func 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	case types.TMAP:
625		n.Index = AssignConv(n.Index, t.Key(), "map index")
626		n.SetType(t.Elem())
627		n.SetOp(ir.OINDEXMAP)
628		n.Assigned = false
629	}
630	return n
631}
632
633// tcLenCap typechecks an OLEN or OCAP node.
634func tcLenCap(n *ir.UnaryExpr) ir.Node {
635	n.X = Expr(n.X)
636	n.X = DefaultLit(n.X, nil)
637	n.X = implicitstar(n.X)
638	l := n.X
639	t := l.Type()
640	if t == nil {
641		n.SetType(nil)
642		return n
643	}
644
645	var ok bool
646	if n.Op() == ir.OLEN {
647		ok = okforlen[t.Kind()]
648	} else {
649		ok = okforcap[t.Kind()]
650	}
651	if !ok {
652		base.Errorf("invalid argument %L for %v", l, n.Op())
653		n.SetType(nil)
654		return n
655	}
656
657	n.SetType(types.Types[types.TINT])
658	return n
659}
660
661// tcUnsafeData typechecks an OUNSAFESLICEDATA or OUNSAFESTRINGDATA node.
662func tcUnsafeData(n *ir.UnaryExpr) ir.Node {
663	n.X = Expr(n.X)
664	n.X = DefaultLit(n.X, nil)
665	l := n.X
666	t := l.Type()
667	if t == nil {
668		n.SetType(nil)
669		return n
670	}
671
672	var kind types.Kind
673	if n.Op() == ir.OUNSAFESLICEDATA {
674		kind = types.TSLICE
675	} else {
676		/* kind is string */
677		kind = types.TSTRING
678	}
679
680	if t.Kind() != kind {
681		base.Errorf("invalid argument %L for %v", l, n.Op())
682		n.SetType(nil)
683		return n
684	}
685
686	if kind == types.TSTRING {
687		t = types.ByteType
688	} else {
689		t = t.Elem()
690	}
691	n.SetType(types.NewPtr(t))
692	return n
693}
694
695// tcRecv typechecks an ORECV node.
696func tcRecv(n *ir.UnaryExpr) ir.Node {
697	n.X = Expr(n.X)
698	n.X = DefaultLit(n.X, nil)
699	l := n.X
700	t := l.Type()
701	if t == nil {
702		n.SetType(nil)
703		return n
704	}
705	if !t.IsChan() {
706		base.Errorf("invalid operation: %v (receive from non-chan type %v)", n, t)
707		n.SetType(nil)
708		return n
709	}
710
711	if !t.ChanDir().CanRecv() {
712		base.Errorf("invalid operation: %v (receive from send-only type %v)", n, t)
713		n.SetType(nil)
714		return n
715	}
716
717	n.SetType(t.Elem())
718	return n
719}
720
721// tcSPtr typechecks an OSPTR node.
722func tcSPtr(n *ir.UnaryExpr) ir.Node {
723	n.X = Expr(n.X)
724	t := n.X.Type()
725	if t == nil {
726		n.SetType(nil)
727		return n
728	}
729	if !t.IsSlice() && !t.IsString() {
730		base.Fatalf("OSPTR of %v", t)
731	}
732	if t.IsString() {
733		n.SetType(types.NewPtr(types.Types[types.TUINT8]))
734	} else {
735		n.SetType(types.NewPtr(t.Elem()))
736	}
737	return n
738}
739
740// tcSlice typechecks an OSLICE or OSLICE3 node.
741func tcSlice(n *ir.SliceExpr) ir.Node {
742	n.X = DefaultLit(Expr(n.X), nil)
743	n.Low = indexlit(Expr(n.Low))
744	n.High = indexlit(Expr(n.High))
745	n.Max = indexlit(Expr(n.Max))
746	hasmax := n.Op().IsSlice3()
747	l := n.X
748	if l.Type() == nil {
749		n.SetType(nil)
750		return n
751	}
752	if l.Type().IsArray() {
753		if !ir.IsAddressable(n.X) {
754			base.Errorf("invalid operation %v (slice of unaddressable value)", n)
755			n.SetType(nil)
756			return n
757		}
758
759		addr := NodAddr(n.X)
760		addr.SetImplicit(true)
761		n.X = Expr(addr)
762		l = n.X
763	}
764	t := l.Type()
765	var tp *types.Type
766	if t.IsString() {
767		if hasmax {
768			base.Errorf("invalid operation %v (3-index slice of string)", n)
769			n.SetType(nil)
770			return n
771		}
772		n.SetType(t)
773		n.SetOp(ir.OSLICESTR)
774	} else if t.IsPtr() && t.Elem().IsArray() {
775		tp = t.Elem()
776		n.SetType(types.NewSlice(tp.Elem()))
777		types.CalcSize(n.Type())
778		if hasmax {
779			n.SetOp(ir.OSLICE3ARR)
780		} else {
781			n.SetOp(ir.OSLICEARR)
782		}
783	} else if t.IsSlice() {
784		n.SetType(t)
785	} else {
786		base.Errorf("cannot slice %v (type %v)", l, t)
787		n.SetType(nil)
788		return n
789	}
790
791	if n.Low != nil && !checksliceindex(l, n.Low, tp) {
792		n.SetType(nil)
793		return n
794	}
795	if n.High != nil && !checksliceindex(l, n.High, tp) {
796		n.SetType(nil)
797		return n
798	}
799	if n.Max != nil && !checksliceindex(l, n.Max, tp) {
800		n.SetType(nil)
801		return n
802	}
803	if !checksliceconst(n.Low, n.High) || !checksliceconst(n.Low, n.Max) || !checksliceconst(n.High, n.Max) {
804		n.SetType(nil)
805		return n
806	}
807	return n
808}
809
810// tcSliceHeader typechecks an OSLICEHEADER node.
811func tcSliceHeader(n *ir.SliceHeaderExpr) ir.Node {
812	// Errors here are Fatalf instead of Errorf because only the compiler
813	// can construct an OSLICEHEADER node.
814	// Components used in OSLICEHEADER that are supplied by parsed source code
815	// have already been typechecked in e.g. OMAKESLICE earlier.
816	t := n.Type()
817	if t == nil {
818		base.Fatalf("no type specified for OSLICEHEADER")
819	}
820
821	if !t.IsSlice() {
822		base.Fatalf("invalid type %v for OSLICEHEADER", n.Type())
823	}
824
825	if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
826		base.Fatalf("need unsafe.Pointer for OSLICEHEADER")
827	}
828
829	n.Ptr = Expr(n.Ptr)
830	n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
831	n.Cap = DefaultLit(Expr(n.Cap), types.Types[types.TINT])
832
833	if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
834		base.Fatalf("len for OSLICEHEADER must be non-negative")
835	}
836
837	if ir.IsConst(n.Cap, constant.Int) && ir.Int64Val(n.Cap) < 0 {
838		base.Fatalf("cap for OSLICEHEADER must be non-negative")
839	}
840
841	if ir.IsConst(n.Len, constant.Int) && ir.IsConst(n.Cap, constant.Int) && constant.Compare(n.Len.Val(), token.GTR, n.Cap.Val()) {
842		base.Fatalf("len larger than cap for OSLICEHEADER")
843	}
844
845	return n
846}
847
848// tcStringHeader typechecks an OSTRINGHEADER node.
849func tcStringHeader(n *ir.StringHeaderExpr) ir.Node {
850	t := n.Type()
851	if t == nil {
852		base.Fatalf("no type specified for OSTRINGHEADER")
853	}
854
855	if !t.IsString() {
856		base.Fatalf("invalid type %v for OSTRINGHEADER", n.Type())
857	}
858
859	if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
860		base.Fatalf("need unsafe.Pointer for OSTRINGHEADER")
861	}
862
863	n.Ptr = Expr(n.Ptr)
864	n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
865
866	if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
867		base.Fatalf("len for OSTRINGHEADER must be non-negative")
868	}
869
870	return n
871}
872
873// tcStar typechecks an ODEREF node, which may be an expression or a type.
874func tcStar(n *ir.StarExpr, top int) ir.Node {
875	n.X = typecheck(n.X, ctxExpr|ctxType)
876	l := n.X
877	t := l.Type()
878	if t == nil {
879		n.SetType(nil)
880		return n
881	}
882
883	// TODO(mdempsky): Remove (along with ctxType above) once I'm
884	// confident this code path isn't needed any more.
885	if l.Op() == ir.OTYPE {
886		base.Fatalf("unexpected type in deref expression: %v", l)
887	}
888
889	if !t.IsPtr() {
890		if top&(ctxExpr|ctxStmt) != 0 {
891			base.Errorf("invalid indirect of %L", n.X)
892			n.SetType(nil)
893			return n
894		}
895		base.Errorf("%v is not a type", l)
896		return n
897	}
898
899	n.SetType(t.Elem())
900	return n
901}
902
903// tcUnaryArith typechecks a unary arithmetic expression.
904func tcUnaryArith(n *ir.UnaryExpr) ir.Node {
905	n.X = Expr(n.X)
906	l := n.X
907	t := l.Type()
908	if t == nil {
909		n.SetType(nil)
910		return n
911	}
912	if !okfor[n.Op()][defaultType(t).Kind()] {
913		base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t))
914		n.SetType(nil)
915		return n
916	}
917
918	n.SetType(t)
919	return n
920}
921