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	"bytes"
9	"fmt"
10	"sort"
11	"strconv"
12	"strings"
13
14	"cmd/compile/internal/base"
15	"cmd/compile/internal/ir"
16	"cmd/compile/internal/types"
17	"cmd/internal/objabi"
18	"cmd/internal/src"
19)
20
21func AssignConv(n ir.Node, t *types.Type, context string) ir.Node {
22	return assignconvfn(n, t, func() string { return context })
23}
24
25// DotImportRefs maps idents introduced by importDot back to the
26// ir.PkgName they were dot-imported through.
27var DotImportRefs map[*ir.Ident]*ir.PkgName
28
29// LookupNum looks up the symbol starting with prefix and ending with
30// the decimal n. If prefix is too long, LookupNum panics.
31func LookupNum(prefix string, n int) *types.Sym {
32	var buf [20]byte // plenty long enough for all current users
33	copy(buf[:], prefix)
34	b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
35	return types.LocalPkg.LookupBytes(b)
36}
37
38// Given funarg struct list, return list of fn args.
39func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field {
40	var args []*ir.Field
41	gen := 0
42	for _, t := range tl.Fields().Slice() {
43		s := t.Sym
44		if mustname && (s == nil || s.Name == "_") {
45			// invent a name so that we can refer to it in the trampoline
46			s = LookupNum(".anon", gen)
47			gen++
48		} else if s != nil && s.Pkg != types.LocalPkg {
49			// TODO(mdempsky): Preserve original position, name, and package.
50			s = Lookup(s.Name)
51		}
52		a := ir.NewField(base.Pos, s, nil, t.Type)
53		a.Pos = t.Pos
54		a.IsDDD = t.IsDDD()
55		args = append(args, a)
56	}
57
58	return args
59}
60
61// newname returns a new ONAME Node associated with symbol s.
62func NewName(s *types.Sym) *ir.Name {
63	n := ir.NewNameAt(base.Pos, s)
64	n.Curfn = ir.CurFunc
65	return n
66}
67
68// NodAddr returns a node representing &n at base.Pos.
69func NodAddr(n ir.Node) *ir.AddrExpr {
70	return NodAddrAt(base.Pos, n)
71}
72
73// nodAddrPos returns a node representing &n at position pos.
74func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
75	n = markAddrOf(n)
76	return ir.NewAddrExpr(pos, n)
77}
78
79func markAddrOf(n ir.Node) ir.Node {
80	if IncrementalAddrtaken {
81		// We can only do incremental addrtaken computation when it is ok
82		// to typecheck the argument of the OADDR. That's only safe after the
83		// main typecheck has completed.
84		// The argument to OADDR needs to be typechecked because &x[i] takes
85		// the address of x if x is an array, but not if x is a slice.
86		// Note: OuterValue doesn't work correctly until n is typechecked.
87		n = typecheck(n, ctxExpr)
88		if x := ir.OuterValue(n); x.Op() == ir.ONAME {
89			x.Name().SetAddrtaken(true)
90		}
91	} else {
92		// Remember that we built an OADDR without computing the Addrtaken bit for
93		// its argument. We'll do that later in bulk using computeAddrtaken.
94		DirtyAddrtaken = true
95	}
96	return n
97}
98
99// If IncrementalAddrtaken is false, we do not compute Addrtaken for an OADDR Node
100// when it is built. The Addrtaken bits are set in bulk by computeAddrtaken.
101// If IncrementalAddrtaken is true, then when an OADDR Node is built the Addrtaken
102// field of its argument is updated immediately.
103var IncrementalAddrtaken = false
104
105// If DirtyAddrtaken is true, then there are OADDR whose corresponding arguments
106// have not yet been marked as Addrtaken.
107var DirtyAddrtaken = false
108
109func ComputeAddrtaken(top []ir.Node) {
110	for _, n := range top {
111		var doVisit func(n ir.Node)
112		doVisit = func(n ir.Node) {
113			if n.Op() == ir.OADDR {
114				if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME {
115					x.Name().SetAddrtaken(true)
116					if x.Name().IsClosureVar() {
117						// Mark the original variable as Addrtaken so that capturevars
118						// knows not to pass it by value.
119						x.Name().Defn.Name().SetAddrtaken(true)
120					}
121				}
122			}
123			if n.Op() == ir.OCLOSURE {
124				ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doVisit)
125			}
126		}
127		ir.Visit(n, doVisit)
128	}
129}
130
131func NodNil() ir.Node {
132	n := ir.NewNilExpr(base.Pos)
133	n.SetType(types.Types[types.TNIL])
134	return n
135}
136
137// AddImplicitDots finds missing fields in obj.field that
138// will give the shortest unique addressing and
139// modifies the tree with missing field names.
140func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
141	n.X = typecheck(n.X, ctxType|ctxExpr)
142	if n.X.Diag() {
143		n.SetDiag(true)
144	}
145	t := n.X.Type()
146	if t == nil {
147		return n
148	}
149
150	if n.X.Op() == ir.OTYPE {
151		return n
152	}
153
154	s := n.Sel
155	if s == nil {
156		return n
157	}
158
159	switch path, ambig := dotpath(s, t, nil, false); {
160	case path != nil:
161		// rebuild elided dots
162		for c := len(path) - 1; c >= 0; c-- {
163			dot := ir.NewSelectorExpr(n.Pos(), ir.ODOT, n.X, path[c].field.Sym)
164			dot.SetImplicit(true)
165			dot.SetType(path[c].field.Type)
166			n.X = dot
167		}
168	case ambig:
169		base.Errorf("ambiguous selector %v", n)
170		n.X = nil
171	}
172
173	return n
174}
175
176func CalcMethods(t *types.Type) {
177	if t == nil || t.AllMethods().Len() != 0 {
178		return
179	}
180
181	// mark top-level method symbols
182	// so that expand1 doesn't consider them.
183	for _, f := range t.Methods().Slice() {
184		f.Sym.SetUniq(true)
185	}
186
187	// generate all reachable methods
188	slist = slist[:0]
189	expand1(t, true)
190
191	// check each method to be uniquely reachable
192	var ms []*types.Field
193	for i, sl := range slist {
194		slist[i].field = nil
195		sl.field.Sym.SetUniq(false)
196
197		var f *types.Field
198		path, _ := dotpath(sl.field.Sym, t, &f, false)
199		if path == nil {
200			continue
201		}
202
203		// dotpath may have dug out arbitrary fields, we only want methods.
204		if !f.IsMethod() {
205			continue
206		}
207
208		// add it to the base type method list
209		f = f.Copy()
210		f.Embedded = 1 // needs a trampoline
211		for _, d := range path {
212			if d.field.Type.IsPtr() {
213				f.Embedded = 2
214				break
215			}
216		}
217		ms = append(ms, f)
218	}
219
220	for _, f := range t.Methods().Slice() {
221		f.Sym.SetUniq(false)
222	}
223
224	ms = append(ms, t.Methods().Slice()...)
225	sort.Sort(types.MethodsByName(ms))
226	t.SetAllMethods(ms)
227}
228
229// adddot1 returns the number of fields or methods named s at depth d in Type t.
230// If exactly one exists, it will be returned in *save (if save is not nil),
231// and dotlist will contain the path of embedded fields traversed to find it,
232// in reverse order. If none exist, more will indicate whether t contains any
233// embedded fields at depth d, so callers can decide whether to retry at
234// a greater depth.
235func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
236	if t.Recur() {
237		return
238	}
239	t.SetRecur(true)
240	defer t.SetRecur(false)
241
242	var u *types.Type
243	d--
244	if d < 0 {
245		// We've reached our target depth. If t has any fields/methods
246		// named s, then we're done. Otherwise, we still need to check
247		// below for embedded fields.
248		c = lookdot0(s, t, save, ignorecase)
249		if c != 0 {
250			return c, false
251		}
252	}
253
254	u = t
255	if u.IsPtr() {
256		u = u.Elem()
257	}
258	if !u.IsStruct() && !u.IsInterface() {
259		return c, false
260	}
261
262	var fields *types.Fields
263	if u.IsStruct() {
264		fields = u.Fields()
265	} else {
266		fields = u.AllMethods()
267	}
268	for _, f := range fields.Slice() {
269		if f.Embedded == 0 || f.Sym == nil {
270			continue
271		}
272		if d < 0 {
273			// Found an embedded field at target depth.
274			return c, true
275		}
276		a, more1 := adddot1(s, f.Type, d, save, ignorecase)
277		if a != 0 && c == 0 {
278			dotlist[d].field = f
279		}
280		c += a
281		if more1 {
282			more = true
283		}
284	}
285
286	return c, more
287}
288
289// dotlist is used by adddot1 to record the path of embedded fields
290// used to access a target field or method.
291// Must be non-nil so that dotpath returns a non-nil slice even if d is zero.
292var dotlist = make([]dlist, 10)
293
294// Convert node n for assignment to type t.
295func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
296	if n == nil || n.Type() == nil || n.Type().Broke() {
297		return n
298	}
299
300	if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
301		base.Errorf("use of untyped nil")
302	}
303
304	n = convlit1(n, t, false, context)
305	if n.Type() == nil {
306		return n
307	}
308	if t.Kind() == types.TBLANK {
309		return n
310	}
311
312	// Convert ideal bool from comparison to plain bool
313	// if the next step is non-bool (like interface{}).
314	if n.Type() == types.UntypedBool && !t.IsBoolean() {
315		if n.Op() == ir.ONAME || n.Op() == ir.OLITERAL {
316			r := ir.NewConvExpr(base.Pos, ir.OCONVNOP, nil, n)
317			r.SetType(types.Types[types.TBOOL])
318			r.SetTypecheck(1)
319			r.SetImplicit(true)
320			n = r
321		}
322	}
323
324	if types.Identical(n.Type(), t) {
325		return n
326	}
327
328	op, why := Assignop(n.Type(), t)
329	if op == ir.OXXX {
330		base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why)
331		op = ir.OCONV
332	}
333
334	r := ir.NewConvExpr(base.Pos, op, t, n)
335	r.SetTypecheck(1)
336	r.SetImplicit(true)
337	return r
338}
339
340// Is type src assignment compatible to type dst?
341// If so, return op code to use in conversion.
342// If not, return OXXX. In this case, the string return parameter may
343// hold a reason why. In all other cases, it'll be the empty string.
344func Assignop(src, dst *types.Type) (ir.Op, string) {
345	if src == dst {
346		return ir.OCONVNOP, ""
347	}
348	if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
349		return ir.OXXX, ""
350	}
351
352	// 1. src type is identical to dst.
353	if types.Identical(src, dst) {
354		return ir.OCONVNOP, ""
355	}
356	return Assignop1(src, dst)
357}
358
359func Assignop1(src, dst *types.Type) (ir.Op, string) {
360	// 2. src and dst have identical underlying types and
361	//   a. either src or dst is not a named type, or
362	//   b. both are empty interface types, or
363	//   c. at least one is a gcshape type.
364	// For assignable but different non-empty interface types,
365	// we want to recompute the itab. Recomputing the itab ensures
366	// that itabs are unique (thus an interface with a compile-time
367	// type I has an itab with interface type I).
368	if types.Identical(src.Underlying(), dst.Underlying()) {
369		if src.IsEmptyInterface() {
370			// Conversion between two empty interfaces
371			// requires no code.
372			return ir.OCONVNOP, ""
373		}
374		if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
375			// Conversion between two types, at least one unnamed,
376			// needs no conversion. The exception is nonempty interfaces
377			// which need to have their itab updated.
378			return ir.OCONVNOP, ""
379		}
380		if src.IsShape() || dst.IsShape() {
381			// Conversion between a shape type and one of the types
382			// it represents also needs no conversion.
383			return ir.OCONVNOP, ""
384		}
385	}
386
387	// 3. dst is an interface type and src implements dst.
388	if dst.IsInterface() && src.Kind() != types.TNIL {
389		var missing, have *types.Field
390		var ptr int
391		if src.IsShape() {
392			// Shape types implement things they have already
393			// been typechecked to implement, even if they
394			// don't have the methods for them.
395			return ir.OCONVIFACE, ""
396		}
397		if implements(src, dst, &missing, &have, &ptr) {
398			return ir.OCONVIFACE, ""
399		}
400
401		// we'll have complained about this method anyway, suppress spurious messages.
402		if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
403			return ir.OCONVIFACE, ""
404		}
405
406		var why string
407		if isptrto(src, types.TINTER) {
408			why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
409		} else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
410			why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
411		} else if have != nil && have.Sym == missing.Sym {
412			why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
413				"\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
414		} else if ptr != 0 {
415			why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
416		} else if have != nil {
417			why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
418				"\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
419		} else {
420			why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
421		}
422
423		return ir.OXXX, why
424	}
425
426	if isptrto(dst, types.TINTER) {
427		why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
428		return ir.OXXX, why
429	}
430
431	if src.IsInterface() && dst.Kind() != types.TBLANK {
432		var missing, have *types.Field
433		var ptr int
434		var why string
435		if implements(dst, src, &missing, &have, &ptr) {
436			why = ": need type assertion"
437		}
438		return ir.OXXX, why
439	}
440
441	// 4. src is a bidirectional channel value, dst is a channel type,
442	// src and dst have identical element types, and
443	// either src or dst is not a named type.
444	if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
445		if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
446			return ir.OCONVNOP, ""
447		}
448	}
449
450	// 5. src is the predeclared identifier nil and dst is a nillable type.
451	if src.Kind() == types.TNIL {
452		switch dst.Kind() {
453		case types.TPTR,
454			types.TFUNC,
455			types.TMAP,
456			types.TCHAN,
457			types.TINTER,
458			types.TSLICE:
459			return ir.OCONVNOP, ""
460		}
461	}
462
463	// 6. rule about untyped constants - already converted by DefaultLit.
464
465	// 7. Any typed value can be assigned to the blank identifier.
466	if dst.Kind() == types.TBLANK {
467		return ir.OCONVNOP, ""
468	}
469
470	return ir.OXXX, ""
471}
472
473// Can we convert a value of type src to a value of type dst?
474// If so, return op code to use in conversion (maybe OCONVNOP).
475// If not, return OXXX. In this case, the string return parameter may
476// hold a reason why. In all other cases, it'll be the empty string.
477// srcConstant indicates whether the value of type src is a constant.
478func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
479	if src == dst {
480		return ir.OCONVNOP, ""
481	}
482	if src == nil || dst == nil {
483		return ir.OXXX, ""
484	}
485
486	// Conversions from regular to go:notinheap are not allowed
487	// (unless it's unsafe.Pointer). These are runtime-specific
488	// rules.
489	// (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
490	if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
491		why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
492		return ir.OXXX, why
493	}
494	// (b) Disallow string to []T where T is go:notinheap.
495	if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
496		why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
497		return ir.OXXX, why
498	}
499
500	// 1. src can be assigned to dst.
501	op, why := Assignop(src, dst)
502	if op != ir.OXXX {
503		return op, why
504	}
505
506	// The rules for interfaces are no different in conversions
507	// than assignments. If interfaces are involved, stop now
508	// with the good message from assignop.
509	// Otherwise clear the error.
510	if src.IsInterface() || dst.IsInterface() {
511		return ir.OXXX, why
512	}
513
514	// 2. Ignoring struct tags, src and dst have identical underlying types.
515	if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
516		return ir.OCONVNOP, ""
517	}
518
519	// 3. src and dst are unnamed pointer types and, ignoring struct tags,
520	// their base types have identical underlying types.
521	if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
522		if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
523			return ir.OCONVNOP, ""
524		}
525	}
526
527	// 4. src and dst are both integer or floating point types.
528	if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
529		if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
530			return ir.OCONVNOP, ""
531		}
532		return ir.OCONV, ""
533	}
534
535	// 5. src and dst are both complex types.
536	if src.IsComplex() && dst.IsComplex() {
537		if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
538			return ir.OCONVNOP, ""
539		}
540		return ir.OCONV, ""
541	}
542
543	// Special case for constant conversions: any numeric
544	// conversion is potentially okay. We'll validate further
545	// within evconst. See #38117.
546	if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
547		return ir.OCONV, ""
548	}
549
550	// 6. src is an integer or has type []byte or []rune
551	// and dst is a string type.
552	if src.IsInteger() && dst.IsString() {
553		return ir.ORUNESTR, ""
554	}
555
556	if src.IsSlice() && dst.IsString() {
557		if src.Elem().Kind() == types.ByteType.Kind() {
558			return ir.OBYTES2STR, ""
559		}
560		if src.Elem().Kind() == types.RuneType.Kind() {
561			return ir.ORUNES2STR, ""
562		}
563	}
564
565	// 7. src is a string and dst is []byte or []rune.
566	// String to slice.
567	if src.IsString() && dst.IsSlice() {
568		if dst.Elem().Kind() == types.ByteType.Kind() {
569			return ir.OSTR2BYTES, ""
570		}
571		if dst.Elem().Kind() == types.RuneType.Kind() {
572			return ir.OSTR2RUNES, ""
573		}
574	}
575
576	// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
577	if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
578		return ir.OCONVNOP, ""
579	}
580
581	// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
582	if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
583		return ir.OCONVNOP, ""
584	}
585
586	// 10. src is map and dst is a pointer to corresponding hmap.
587	// This rule is needed for the implementation detail that
588	// go gc maps are implemented as a pointer to a hmap struct.
589	if src.Kind() == types.TMAP && dst.IsPtr() &&
590		src.MapType().Hmap == dst.Elem() {
591		return ir.OCONVNOP, ""
592	}
593
594	// 11. src is a slice and dst is a pointer-to-array.
595	// They must have same element type.
596	if src.IsSlice() && dst.IsPtr() && dst.Elem().IsArray() &&
597		types.Identical(src.Elem(), dst.Elem().Elem()) {
598		if !types.AllowsGoVersion(curpkg(), 1, 17) {
599			return ir.OXXX, ":\n\tconversion of slices to array pointers only supported as of -lang=go1.17"
600		}
601		return ir.OSLICE2ARRPTR, ""
602	}
603
604	return ir.OXXX, ""
605}
606
607// Code to resolve elided DOTs in embedded types.
608
609// A dlist stores a pointer to a TFIELD Type embedded within
610// a TSTRUCT or TINTER Type.
611type dlist struct {
612	field *types.Field
613}
614
615// dotpath computes the unique shortest explicit selector path to fully qualify
616// a selection expression x.f, where x is of type t and f is the symbol s.
617// If no such path exists, dotpath returns nil.
618// If there are multiple shortest paths to the same depth, ambig is true.
619func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []dlist, ambig bool) {
620	// The embedding of types within structs imposes a tree structure onto
621	// types: structs parent the types they embed, and types parent their
622	// fields or methods. Our goal here is to find the shortest path to
623	// a field or method named s in the subtree rooted at t. To accomplish
624	// that, we iteratively perform depth-first searches of increasing depth
625	// until we either find the named field/method or exhaust the tree.
626	for d := 0; ; d++ {
627		if d > len(dotlist) {
628			dotlist = append(dotlist, dlist{})
629		}
630		if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
631			return dotlist[:d], false
632		} else if c > 1 {
633			return nil, true
634		} else if !more {
635			return nil, false
636		}
637	}
638}
639
640func expand0(t *types.Type) {
641	u := t
642	if u.IsPtr() {
643		u = u.Elem()
644	}
645
646	if u.IsInterface() {
647		for _, f := range u.AllMethods().Slice() {
648			if f.Sym.Uniq() {
649				continue
650			}
651			f.Sym.SetUniq(true)
652			slist = append(slist, symlink{field: f})
653		}
654
655		return
656	}
657
658	u = types.ReceiverBaseType(t)
659	if u != nil {
660		for _, f := range u.Methods().Slice() {
661			if f.Sym.Uniq() {
662				continue
663			}
664			f.Sym.SetUniq(true)
665			slist = append(slist, symlink{field: f})
666		}
667	}
668}
669
670func expand1(t *types.Type, top bool) {
671	if t.Recur() {
672		return
673	}
674	t.SetRecur(true)
675
676	if !top {
677		expand0(t)
678	}
679
680	u := t
681	if u.IsPtr() {
682		u = u.Elem()
683	}
684
685	if u.IsStruct() || u.IsInterface() {
686		var fields *types.Fields
687		if u.IsStruct() {
688			fields = u.Fields()
689		} else {
690			fields = u.AllMethods()
691		}
692		for _, f := range fields.Slice() {
693			if f.Embedded == 0 {
694				continue
695			}
696			if f.Sym == nil {
697				continue
698			}
699			expand1(f.Type, false)
700		}
701	}
702
703	t.SetRecur(false)
704}
705
706func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, followptr bool) {
707	if t == nil {
708		return nil, false
709	}
710
711	path, ambig := dotpath(s, t, &m, ignorecase)
712	if path == nil {
713		if ambig {
714			base.Errorf("%v.%v is ambiguous", t, s)
715		}
716		return nil, false
717	}
718
719	for _, d := range path {
720		if d.field.Type.IsPtr() {
721			followptr = true
722			break
723		}
724	}
725
726	if !m.IsMethod() {
727		base.Errorf("%v.%v is a field, not a method", t, s)
728		return nil, followptr
729	}
730
731	return m, followptr
732}
733
734// implements reports whether t implements the interface iface. t can be
735// an interface, a type parameter, or a concrete type. If implements returns
736// false, it stores a method of iface that is not implemented in *m. If the
737// method name matches but the type is wrong, it additionally stores the type
738// of the method (on t) in *samename.
739func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
740	t0 := t
741	if t == nil {
742		return false
743	}
744
745	if t.IsInterface() || t.IsTypeParam() {
746		if t.IsTypeParam() {
747			// If t is a simple type parameter T, its type and underlying is the same.
748			// If t is a type definition:'type P[T any] T', its type is P[T] and its
749			// underlying is T. Therefore we use 't.Underlying() != t' to distinguish them.
750			if t.Underlying() != t {
751				CalcMethods(t)
752			} else {
753				// A typeparam satisfies an interface if its type bound
754				// has all the methods of that interface.
755				t = t.Bound()
756			}
757		}
758		i := 0
759		tms := t.AllMethods().Slice()
760		for _, im := range iface.AllMethods().Slice() {
761			for i < len(tms) && tms[i].Sym != im.Sym {
762				i++
763			}
764			if i == len(tms) {
765				*m = im
766				*samename = nil
767				*ptr = 0
768				return false
769			}
770			tm := tms[i]
771			if !types.Identical(tm.Type, im.Type) {
772				*m = im
773				*samename = tm
774				*ptr = 0
775				return false
776			}
777		}
778
779		return true
780	}
781
782	t = types.ReceiverBaseType(t)
783	var tms []*types.Field
784	if t != nil {
785		CalcMethods(t)
786		tms = t.AllMethods().Slice()
787	}
788	i := 0
789	for _, im := range iface.AllMethods().Slice() {
790		if im.Broke() {
791			continue
792		}
793		for i < len(tms) && tms[i].Sym != im.Sym {
794			i++
795		}
796		if i == len(tms) {
797			*m = im
798			*samename, _ = ifacelookdot(im.Sym, t, true)
799			*ptr = 0
800			return false
801		}
802		tm := tms[i]
803		if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
804			*m = im
805			*samename = tm
806			*ptr = 0
807			return false
808		}
809		followptr := tm.Embedded == 2
810
811		// if pointer receiver in method,
812		// the method does not exist for value types.
813		rcvr := tm.Type.Recv().Type
814		if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !types.IsInterfaceMethod(tm.Type) {
815			if false && base.Flag.LowerR != 0 {
816				base.Errorf("interface pointer mismatch")
817			}
818
819			*m = im
820			*samename = nil
821			*ptr = 1
822			return false
823		}
824	}
825
826	return true
827}
828
829func isptrto(t *types.Type, et types.Kind) bool {
830	if t == nil {
831		return false
832	}
833	if !t.IsPtr() {
834		return false
835	}
836	t = t.Elem()
837	if t == nil {
838		return false
839	}
840	if t.Kind() != et {
841		return false
842	}
843	return true
844}
845
846// lookdot0 returns the number of fields or methods named s associated
847// with Type t. If exactly one exists, it will be returned in *save
848// (if save is not nil).
849func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
850	u := t
851	if u.IsPtr() {
852		u = u.Elem()
853	}
854
855	c := 0
856	if u.IsStruct() || u.IsInterface() {
857		var fields *types.Fields
858		if u.IsStruct() {
859			fields = u.Fields()
860		} else {
861			fields = u.AllMethods()
862		}
863		for _, f := range fields.Slice() {
864			if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
865				if save != nil {
866					*save = f
867				}
868				c++
869			}
870		}
871	}
872
873	u = t
874	if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
875		// If t is a defined pointer type, then x.m is shorthand for (*x).m.
876		u = t.Elem()
877	}
878	u = types.ReceiverBaseType(u)
879	if u != nil {
880		for _, f := range u.Methods().Slice() {
881			if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
882				if save != nil {
883					*save = f
884				}
885				c++
886			}
887		}
888	}
889
890	return c
891}
892
893var slist []symlink
894
895// Code to help generate trampoline functions for methods on embedded
896// types. These are approx the same as the corresponding AddImplicitDots
897// routines except that they expect to be called with unique tasks and
898// they return the actual methods.
899
900type symlink struct {
901	field *types.Field
902}
903
904// TypesOf converts a list of nodes to a list
905// of types of those nodes.
906func TypesOf(x []ir.Node) []*types.Type {
907	r := make([]*types.Type, len(x))
908	for i, n := range x {
909		r[i] = n.Type()
910	}
911	return r
912}
913
914// addTargs writes out the targs to buffer b as a comma-separated list enclosed by
915// brackets.
916func addTargs(b *bytes.Buffer, targs []*types.Type) {
917	b.WriteByte('[')
918	for i, targ := range targs {
919		if i > 0 {
920			b.WriteByte(',')
921		}
922		// Make sure that type arguments (including type params), are
923		// uniquely specified. LinkString() eliminates all spaces
924		// and includes the package path (local package path is "" before
925		// linker substitution).
926		tstring := targ.LinkString()
927		b.WriteString(tstring)
928	}
929	b.WriteString("]")
930}
931
932// InstTypeName creates a name for an instantiated type, based on the name of the
933// generic type and the type args.
934func InstTypeName(name string, targs []*types.Type) string {
935	b := bytes.NewBufferString(name)
936	addTargs(b, targs)
937	return b.String()
938}
939
940// makeInstName1 returns the name of the generic function instantiated with the
941// given types, which can have type params or shapes, or be concrete types. name is
942// the name of the generic function or method.
943func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string {
944	b := bytes.NewBufferString("")
945	i := strings.Index(name, "[")
946	assert(hasBrackets == (i >= 0))
947	if i >= 0 {
948		b.WriteString(name[0:i])
949	} else {
950		b.WriteString(name)
951	}
952	addTargs(b, targs)
953	if i >= 0 {
954		i2 := strings.LastIndex(name[i:], "]")
955		assert(i2 >= 0)
956		b.WriteString(name[i+i2+1:])
957	}
958	return b.String()
959}
960
961// MakeFuncInstSym makes the unique sym for a stenciled generic function or method,
962// based on the name of the function gf and the targs. It replaces any
963// existing bracket type list in the name. MakeInstName asserts that gf has
964// brackets in its name if and only if hasBrackets is true.
965//
966// Names of declared generic functions have no brackets originally, so hasBrackets
967// should be false. Names of generic methods already have brackets, since the new
968// type parameter is specified in the generic type of the receiver (e.g. func
969// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set.
970//
971// The standard naming is something like: 'genFn[int,bool]' for functions and
972// '(*genType[int,bool]).methodName' for methods
973//
974// isMethodNode specifies if the name of a method node is being generated (as opposed
975// to a name of an instantiation of generic function or name of the shape-based
976// function that helps implement a method of an instantiated type). For method nodes
977// on shape types, we prepend "nofunc.", because method nodes for shape types will
978// have no body, and we want to avoid a name conflict with the shape-based function
979// that helps implement the same method for fully-instantiated types.
980func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, isMethodNode, hasBrackets bool) *types.Sym {
981	nm := makeInstName1(gf.Name, targs, hasBrackets)
982	if targs[0].HasShape() && isMethodNode {
983		nm = "nofunc." + nm
984	}
985	return gf.Pkg.Lookup(nm)
986}
987
988func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym {
989	for _, targ := range targs {
990		if targ.HasTParam() {
991			fmt.Printf("FUNCTION %s\n", gf.Name)
992			for _, targ := range targs {
993				fmt.Printf("  PARAM %+v\n", targ)
994			}
995			panic("dictionary should always have concrete type args")
996		}
997	}
998	name := makeInstName1(gf.Name, targs, hasBrackets)
999	name = fmt.Sprintf("%s.%s", objabi.GlobalDictPrefix, name)
1000	return gf.Pkg.Lookup(name)
1001}
1002
1003func assert(p bool) {
1004	base.Assert(p)
1005}
1006
1007// List of newly fully-instantiated types who should have their methods generated.
1008var instTypeList []*types.Type
1009
1010// NeedInstType adds a new fully-instantiated type to instTypeList.
1011func NeedInstType(t *types.Type) {
1012	instTypeList = append(instTypeList, t)
1013}
1014
1015// GetInstTypeList returns the current contents of instTypeList.
1016func GetInstTypeList() []*types.Type {
1017	r := instTypeList
1018	return r
1019}
1020
1021// ClearInstTypeList clears the contents of instTypeList.
1022func ClearInstTypeList() {
1023	instTypeList = nil
1024}
1025
1026// General type substituter, for replacing typeparams with type args.
1027type Tsubster struct {
1028	Tparams []*types.Type
1029	Targs   []*types.Type
1030	// If non-nil, the substitution map from name nodes in the generic function to the
1031	// name nodes in the new stenciled function.
1032	Vars map[*ir.Name]*ir.Name
1033	// If non-nil, function to substitute an incomplete (TFORW) type.
1034	SubstForwFunc func(*types.Type) *types.Type
1035}
1036
1037// Typ computes the type obtained by substituting any type parameter or shape in t
1038// that appears in subst.Tparams with the corresponding type argument in subst.Targs.
1039// If t contains no type parameters, the result is t; otherwise the result is a new
1040// type. It deals with recursive types by using TFORW types and finding partially or
1041// fully created types via sym.Def.
1042func (ts *Tsubster) Typ(t *types.Type) *types.Type {
1043	// Defer the CheckSize calls until we have fully-defined
1044	// (possibly-recursive) top-level type.
1045	types.DeferCheckSize()
1046	r := ts.typ1(t)
1047	types.ResumeCheckSize()
1048	return r
1049}
1050
1051func (ts *Tsubster) typ1(t *types.Type) *types.Type {
1052	if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TFUNC {
1053		// Note: function types need to be copied regardless, as the
1054		// types of closures may contain declarations that need
1055		// to be copied. See #45738.
1056		return t
1057	}
1058
1059	if t.IsTypeParam() || t.IsShape() {
1060		for i, tp := range ts.Tparams {
1061			if tp == t {
1062				return ts.Targs[i]
1063			}
1064		}
1065		// If t is a simple typeparam T, then t has the name/symbol 'T'
1066		// and t.Underlying() == t.
1067		//
1068		// However, consider the type definition: 'type P[T any] T'. We
1069		// might use this definition so we can have a variant of type T
1070		// that we can add new methods to. Suppose t is a reference to
1071		// P[T]. t has the name 'P[T]', but its kind is TTYPEPARAM,
1072		// because P[T] is defined as T. If we look at t.Underlying(), it
1073		// is different, because the name of t.Underlying() is 'T' rather
1074		// than 'P[T]'. But the kind of t.Underlying() is also TTYPEPARAM.
1075		// In this case, we do the needed recursive substitution in the
1076		// case statement below.
1077		if t.Underlying() == t {
1078			// t is a simple typeparam that didn't match anything in tparam
1079			return t
1080		}
1081		// t is a more complex typeparam (e.g. P[T], as above, whose
1082		// definition is just T).
1083		assert(t.Sym() != nil)
1084	}
1085
1086	var newsym *types.Sym
1087	var neededTargs []*types.Type
1088	var targsChanged bool
1089	var forw *types.Type
1090
1091	if t.Sym() != nil && (t.HasTParam() || t.HasShape()) {
1092		// Need to test for t.HasTParam() again because of special TFUNC case above.
1093		// Translate the type params for this type according to
1094		// the tparam/targs mapping from subst.
1095		neededTargs = make([]*types.Type, len(t.RParams()))
1096		for i, rparam := range t.RParams() {
1097			neededTargs[i] = ts.typ1(rparam)
1098			if !types.IdenticalStrict(neededTargs[i], rparam) {
1099				targsChanged = true
1100			}
1101		}
1102		// For a named (defined) type, we have to change the name of the
1103		// type as well. We do this first, so we can look up if we've
1104		// already seen this type during this substitution or other
1105		// definitions/substitutions.
1106		genName := genericTypeName(t.Sym())
1107		newsym = t.Sym().Pkg.Lookup(InstTypeName(genName, neededTargs))
1108		if newsym.Def != nil {
1109			// We've already created this instantiated defined type.
1110			return newsym.Def.Type()
1111		}
1112
1113		// In order to deal with recursive generic types, create a TFORW
1114		// type initially and set the Def field of its sym, so it can be
1115		// found if this type appears recursively within the type.
1116		forw = NewIncompleteNamedType(t.Pos(), newsym)
1117		//println("Creating new type by sub", newsym.Name, forw.HasTParam())
1118		forw.SetRParams(neededTargs)
1119		// Copy the OrigSym from the re-instantiated type (which is the sym of
1120		// the base generic type).
1121		assert(t.OrigSym() != nil)
1122		forw.SetOrigSym(t.OrigSym())
1123	}
1124
1125	var newt *types.Type
1126
1127	switch t.Kind() {
1128	case types.TTYPEPARAM:
1129		if t.Sym() == newsym && !targsChanged {
1130			// The substitution did not change the type.
1131			return t
1132		}
1133		// Substitute the underlying typeparam (e.g. T in P[T], see
1134		// the example describing type P[T] above).
1135		newt = ts.typ1(t.Underlying())
1136		assert(newt != t)
1137
1138	case types.TARRAY:
1139		elem := t.Elem()
1140		newelem := ts.typ1(elem)
1141		if newelem != elem || targsChanged {
1142			newt = types.NewArray(newelem, t.NumElem())
1143		}
1144
1145	case types.TPTR:
1146		elem := t.Elem()
1147		newelem := ts.typ1(elem)
1148		if newelem != elem || targsChanged {
1149			newt = types.NewPtr(newelem)
1150		}
1151
1152	case types.TSLICE:
1153		elem := t.Elem()
1154		newelem := ts.typ1(elem)
1155		if newelem != elem || targsChanged {
1156			newt = types.NewSlice(newelem)
1157		}
1158
1159	case types.TSTRUCT:
1160		newt = ts.tstruct(t, targsChanged)
1161		if newt == t {
1162			newt = nil
1163		}
1164
1165	case types.TFUNC:
1166		newrecvs := ts.tstruct(t.Recvs(), false)
1167		newparams := ts.tstruct(t.Params(), false)
1168		newresults := ts.tstruct(t.Results(), false)
1169		// Translate the tparams of a signature.
1170		newtparams := ts.tstruct(t.TParams(), false)
1171		if newrecvs != t.Recvs() || newparams != t.Params() ||
1172			newresults != t.Results() || newtparams != t.TParams() || targsChanged {
1173			// If any types have changed, then the all the fields of
1174			// of recv, params, and results must be copied, because they have
1175			// offset fields that are dependent, and so must have an
1176			// independent copy for each new signature.
1177			var newrecv *types.Field
1178			if newrecvs.NumFields() > 0 {
1179				if newrecvs == t.Recvs() {
1180					newrecvs = ts.tstruct(t.Recvs(), true)
1181				}
1182				newrecv = newrecvs.Field(0)
1183			}
1184			if newparams == t.Params() {
1185				newparams = ts.tstruct(t.Params(), true)
1186			}
1187			if newresults == t.Results() {
1188				newresults = ts.tstruct(t.Results(), true)
1189			}
1190			var tparamfields []*types.Field
1191			if newtparams.HasTParam() {
1192				tparamfields = newtparams.FieldSlice()
1193			} else {
1194				// Completely remove the tparams from the resulting
1195				// signature, if the tparams are now concrete types.
1196				tparamfields = nil
1197			}
1198			newt = types.NewSignature(t.Pkg(), newrecv, tparamfields,
1199				newparams.FieldSlice(), newresults.FieldSlice())
1200		}
1201
1202	case types.TINTER:
1203		newt = ts.tinter(t, targsChanged)
1204		if newt == t {
1205			newt = nil
1206		}
1207
1208	case types.TMAP:
1209		newkey := ts.typ1(t.Key())
1210		newval := ts.typ1(t.Elem())
1211		if newkey != t.Key() || newval != t.Elem() || targsChanged {
1212			newt = types.NewMap(newkey, newval)
1213		}
1214
1215	case types.TCHAN:
1216		elem := t.Elem()
1217		newelem := ts.typ1(elem)
1218		if newelem != elem || targsChanged {
1219			newt = types.NewChan(newelem, t.ChanDir())
1220		}
1221	case types.TFORW:
1222		if ts.SubstForwFunc != nil {
1223			return ts.SubstForwFunc(forw)
1224		} else {
1225			assert(false)
1226		}
1227	case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
1228		types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
1229		types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR:
1230		newt = t.Underlying()
1231	case types.TUNION:
1232		nt := t.NumTerms()
1233		newterms := make([]*types.Type, nt)
1234		tildes := make([]bool, nt)
1235		changed := false
1236		for i := 0; i < nt; i++ {
1237			term, tilde := t.Term(i)
1238			tildes[i] = tilde
1239			newterms[i] = ts.typ1(term)
1240			if newterms[i] != term {
1241				changed = true
1242			}
1243		}
1244		if changed {
1245			newt = types.NewUnion(newterms, tildes)
1246		}
1247	default:
1248		panic(fmt.Sprintf("Bad type in (*TSubster).Typ: %v", t.Kind()))
1249	}
1250	if newt == nil {
1251		// Even though there were typeparams in the type, there may be no
1252		// change if this is a function type for a function call (which will
1253		// have its own tparams/targs in the function instantiation).
1254		return t
1255	}
1256
1257	if forw != nil {
1258		forw.SetUnderlying(newt)
1259		newt = forw
1260	}
1261
1262	if !newt.HasTParam() && !newt.IsFuncArgStruct() {
1263		// Calculate the size of any new types created. These will be
1264		// deferred until the top-level ts.Typ() or g.typ() (if this is
1265		// called from g.fillinMethods()).
1266		types.CheckSize(newt)
1267	}
1268
1269	if t.Kind() != types.TINTER && t.Methods().Len() > 0 {
1270		// Fill in the method info for the new type.
1271		var newfields []*types.Field
1272		newfields = make([]*types.Field, t.Methods().Len())
1273		for i, f := range t.Methods().Slice() {
1274			t2 := ts.typ1(f.Type)
1275			oldsym := f.Nname.Sym()
1276			newsym := MakeFuncInstSym(oldsym, ts.Targs, true, true)
1277			var nname *ir.Name
1278			if newsym.Def != nil {
1279				nname = newsym.Def.(*ir.Name)
1280			} else {
1281				nname = ir.NewNameAt(f.Pos, newsym)
1282				nname.SetType(t2)
1283				ir.MarkFunc(nname)
1284				newsym.Def = nname
1285			}
1286			newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1287			newfields[i].Nname = nname
1288		}
1289		newt.Methods().Set(newfields)
1290		if !newt.HasTParam() && !newt.HasShape() {
1291			// Generate all the methods for a new fully-instantiated type.
1292
1293			NeedInstType(newt)
1294		}
1295	}
1296	return newt
1297}
1298
1299// tstruct substitutes type params in types of the fields of a structure type. For
1300// each field, tstruct copies the Nname, and translates it if Nname is in
1301// ts.vars. To always force the creation of a new (top-level) struct,
1302// regardless of whether anything changed with the types or names of the struct's
1303// fields, set force to true.
1304func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
1305	if t.NumFields() == 0 {
1306		if t.HasTParam() || t.HasShape() {
1307			// For an empty struct, we need to return a new type,
1308			// since it may now be fully instantiated (HasTParam
1309			// becomes false).
1310			return types.NewStruct(t.Pkg(), nil)
1311		}
1312		return t
1313	}
1314	var newfields []*types.Field
1315	if force {
1316		newfields = make([]*types.Field, t.NumFields())
1317	}
1318	for i, f := range t.Fields().Slice() {
1319		t2 := ts.typ1(f.Type)
1320		if (t2 != f.Type || f.Nname != nil) && newfields == nil {
1321			newfields = make([]*types.Field, t.NumFields())
1322			for j := 0; j < i; j++ {
1323				newfields[j] = t.Field(j)
1324			}
1325		}
1326		if newfields != nil {
1327			newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1328			newfields[i].Embedded = f.Embedded
1329			newfields[i].Note = f.Note
1330			if f.IsDDD() {
1331				newfields[i].SetIsDDD(true)
1332			}
1333			if f.Nointerface() {
1334				newfields[i].SetNointerface(true)
1335			}
1336			if f.Nname != nil && ts.Vars != nil {
1337				v := ts.Vars[f.Nname.(*ir.Name)]
1338				if v != nil {
1339					// This is the case where we are
1340					// translating the type of the function we
1341					// are substituting, so its dcls are in
1342					// the subst.ts.vars table, and we want to
1343					// change to reference the new dcl.
1344					newfields[i].Nname = v
1345				} else {
1346					// This is the case where we are
1347					// translating the type of a function
1348					// reference inside the function we are
1349					// substituting, so we leave the Nname
1350					// value as is.
1351					newfields[i].Nname = f.Nname
1352				}
1353			}
1354		}
1355	}
1356	if newfields != nil {
1357		news := types.NewStruct(t.Pkg(), newfields)
1358		news.StructType().Funarg = t.StructType().Funarg
1359		return news
1360	}
1361	return t
1362
1363}
1364
1365// tinter substitutes type params in types of the methods of an interface type.
1366func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type {
1367	if t.Methods().Len() == 0 {
1368		if t.HasTParam() {
1369			// For an empty interface, we need to return a new type,
1370			// since it may now be fully instantiated (HasTParam
1371			// becomes false).
1372			return types.NewInterface(t.Pkg(), nil, false)
1373		}
1374		return t
1375	}
1376	var newfields []*types.Field
1377	if force {
1378		newfields = make([]*types.Field, t.Methods().Len())
1379	}
1380	for i, f := range t.Methods().Slice() {
1381		t2 := ts.typ1(f.Type)
1382		if (t2 != f.Type || f.Nname != nil) && newfields == nil {
1383			newfields = make([]*types.Field, t.Methods().Len())
1384			for j := 0; j < i; j++ {
1385				newfields[j] = t.Methods().Index(j)
1386			}
1387		}
1388		if newfields != nil {
1389			newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1390		}
1391	}
1392	if newfields != nil {
1393		return types.NewInterface(t.Pkg(), newfields, t.IsImplicit())
1394	}
1395	return t
1396}
1397
1398// genericSym returns the name of the base generic type for the type named by
1399// sym. It simply returns the name obtained by removing everything after the
1400// first bracket ("[").
1401func genericTypeName(sym *types.Sym) string {
1402	return sym.Name[0:strings.Index(sym.Name, "[")]
1403}
1404
1405// Shapify takes a concrete type and a type param index, and returns a GCshape type that can
1406// be used in place of the input type and still generate identical code.
1407// No methods are added - all methods calls directly on a shape should
1408// be done by converting to an interface using the dictionary.
1409//
1410// For now, we only consider two types to have the same shape, if they have exactly
1411// the same underlying type or they are both pointer types.
1412//
1413//  Shape types are also distinguished by the index of the type in a type param/arg
1414//  list. We need to do this so we can distinguish and substitute properly for two
1415//  type params in the same function that have the same shape for a particular
1416//  instantiation.
1417func Shapify(t *types.Type, index int) *types.Type {
1418	assert(!t.IsShape())
1419	// Map all types with the same underlying type to the same shape.
1420	u := t.Underlying()
1421
1422	// All pointers have the same shape.
1423	// TODO: Make unsafe.Pointer the same shape as normal pointers.
1424	// Note: pointers to arrays are special because of slice-to-array-pointer
1425	// conversions. See issue 49295.
1426	if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY {
1427		u = types.Types[types.TUINT8].PtrTo()
1428	}
1429
1430	if shapeMap == nil {
1431		shapeMap = map[int]map[*types.Type]*types.Type{}
1432	}
1433	submap := shapeMap[index]
1434	if submap == nil {
1435		submap = map[*types.Type]*types.Type{}
1436		shapeMap[index] = submap
1437	}
1438	if s := submap[u]; s != nil {
1439		return s
1440	}
1441
1442	// LinkString specifies the type uniquely, but has no spaces.
1443	nm := fmt.Sprintf("%s_%d", u.LinkString(), index)
1444	sym := types.ShapePkg.Lookup(nm)
1445	if sym.Def != nil {
1446		// Use any existing type with the same name
1447		submap[u] = sym.Def.Type()
1448		return submap[u]
1449	}
1450	name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym)
1451	s := types.NewNamed(name)
1452	sym.Def = name
1453	s.SetUnderlying(u)
1454	s.SetIsShape(true)
1455	s.SetHasShape(true)
1456	name.SetType(s)
1457	name.SetTypecheck(1)
1458	submap[u] = s
1459	return s
1460}
1461
1462var shapeMap map[int]map[*types.Type]*types.Type
1463