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.
13 "cmd/compile/internal/base"
14 "cmd/compile/internal/ir"
15 "cmd/compile/internal/types"
21 func AssignConv(n ir.Node, t *types.Type, context string) ir.Node {
22 return assignconvfn(n, t, func() string { return context })
25 // LookupNum returns types.LocalPkg.LookupNum(prefix, n).
26 func LookupNum(prefix string, n int) *types.Sym {
27 return types.LocalPkg.LookupNum(prefix, n)
30 // Given funarg struct list, return list of fn args.
31 func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field {
34 for _, t := range tl.Fields().Slice() {
36 if mustname && (s == nil || s.Name == "_") {
37 // invent a name so that we can refer to it in the trampoline
38 s = LookupNum(".anon", gen)
40 } else if s != nil && s.Pkg != types.LocalPkg {
41 // TODO(mdempsky): Preserve original position, name, and package.
44 a := ir.NewField(base.Pos, s, t.Type)
47 args = append(args, a)
53 // NewName returns a new ONAME Node associated with symbol s.
54 func NewName(s *types.Sym) *ir.Name {
55 n := ir.NewNameAt(base.Pos, s)
60 // NodAddr returns a node representing &n at base.Pos.
61 func NodAddr(n ir.Node) *ir.AddrExpr {
62 return NodAddrAt(base.Pos, n)
65 // NodAddrAt returns a node representing &n at position pos.
66 func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
68 return ir.NewAddrExpr(pos, n)
71 func markAddrOf(n ir.Node) ir.Node {
72 if IncrementalAddrtaken {
73 // We can only do incremental addrtaken computation when it is ok
74 // to typecheck the argument of the OADDR. That's only safe after the
75 // main typecheck has completed, and not loading the inlined body.
76 // The argument to OADDR needs to be typechecked because &x[i] takes
77 // the address of x if x is an array, but not if x is a slice.
78 // Note: OuterValue doesn't work correctly until n is typechecked.
79 n = typecheck(n, ctxExpr)
80 if x := ir.OuterValue(n); x.Op() == ir.ONAME {
81 x.Name().SetAddrtaken(true)
84 // Remember that we built an OADDR without computing the Addrtaken bit for
85 // its argument. We'll do that later in bulk using computeAddrtaken.
91 // If IncrementalAddrtaken is false, we do not compute Addrtaken for an OADDR Node
92 // when it is built. The Addrtaken bits are set in bulk by computeAddrtaken.
93 // If IncrementalAddrtaken is true, then when an OADDR Node is built the Addrtaken
94 // field of its argument is updated immediately.
95 var IncrementalAddrtaken = false
97 // If DirtyAddrtaken is true, then there are OADDR whose corresponding arguments
98 // have not yet been marked as Addrtaken.
99 var DirtyAddrtaken = false
101 func ComputeAddrtaken(top []ir.Node) {
102 for _, n := range top {
103 var doVisit func(n ir.Node)
104 doVisit = func(n ir.Node) {
105 if n.Op() == ir.OADDR {
106 if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME {
107 x.Name().SetAddrtaken(true)
108 if x.Name().IsClosureVar() {
109 // Mark the original variable as Addrtaken so that capturevars
110 // knows not to pass it by value.
111 x.Name().Defn.Name().SetAddrtaken(true)
115 if n.Op() == ir.OCLOSURE {
116 ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doVisit)
123 // LinksymAddr returns a new expression that evaluates to the address
124 // of lsym. typ specifies the type of the addressed memory.
125 func LinksymAddr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *ir.AddrExpr {
126 n := ir.NewLinksymExpr(pos, lsym, typ)
127 return Expr(NodAddrAt(pos, n)).(*ir.AddrExpr)
130 func NodNil() ir.Node {
131 n := ir.NewNilExpr(base.Pos)
132 n.SetType(types.Types[types.TNIL])
136 // AddImplicitDots finds missing fields in obj.field that
137 // will give the shortest unique addressing and
138 // modifies the tree with missing field names.
139 func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
140 n.X = typecheck(n.X, ctxType|ctxExpr)
146 if n.X.Op() == ir.OTYPE {
155 switch path, ambig := dotpath(s, t, nil, false); {
157 // rebuild elided dots
158 for c := len(path) - 1; c >= 0; c-- {
159 dot := ir.NewSelectorExpr(n.Pos(), ir.ODOT, n.X, path[c].field.Sym)
160 dot.SetImplicit(true)
161 dot.SetType(path[c].field.Type)
165 base.Errorf("ambiguous selector %v", n)
172 // CalcMethods calculates all the methods (including embedding) of a non-interface
174 func CalcMethods(t *types.Type) {
175 if t == nil || t.AllMethods().Len() != 0 {
179 // mark top-level method symbols
180 // so that expand1 doesn't consider them.
181 for _, f := range t.Methods().Slice() {
185 // generate all reachable methods
189 // check each method to be uniquely reachable
190 var ms []*types.Field
191 for i, sl := range slist {
193 sl.field.Sym.SetUniq(false)
196 path, _ := dotpath(sl.field.Sym, t, &f, false)
201 // dotpath may have dug out arbitrary fields, we only want methods.
206 // add it to the base type method list
208 f.Embedded = 1 // needs a trampoline
209 for _, d := range path {
210 if d.field.Type.IsPtr() {
218 for _, f := range t.Methods().Slice() {
222 ms = append(ms, t.Methods().Slice()...)
223 sort.Sort(types.MethodsByName(ms))
227 // adddot1 returns the number of fields or methods named s at depth d in Type t.
228 // If exactly one exists, it will be returned in *save (if save is not nil),
229 // and dotlist will contain the path of embedded fields traversed to find it,
230 // in reverse order. If none exist, more will indicate whether t contains any
231 // embedded fields at depth d, so callers can decide whether to retry at
233 func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
238 defer t.SetRecur(false)
243 // We've reached our target depth. If t has any fields/methods
244 // named s, then we're done. Otherwise, we still need to check
245 // below for embedded fields.
246 c = lookdot0(s, t, save, ignorecase)
256 if !u.IsStruct() && !u.IsInterface() {
260 var fields *types.Fields
264 fields = u.AllMethods()
266 for _, f := range fields.Slice() {
267 if f.Embedded == 0 || f.Sym == nil {
271 // Found an embedded field at target depth.
274 a, more1 := adddot1(s, f.Type, d, save, ignorecase)
275 if a != 0 && c == 0 {
287 // dotlist is used by adddot1 to record the path of embedded fields
288 // used to access a target field or method.
289 // Must be non-nil so that dotpath returns a non-nil slice even if d is zero.
290 var dotlist = make([]dlist, 10)
292 // Convert node n for assignment to type t.
293 func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
294 if n == nil || n.Type() == nil {
298 if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
299 base.Errorf("use of untyped nil")
302 n = convlit1(n, t, false, context)
304 base.Fatalf("cannot assign %v to %v", n, t)
306 if n.Type().IsUntyped() {
307 base.Fatalf("%L has untyped type", n)
309 if t.Kind() == types.TBLANK {
312 if types.Identical(n.Type(), t) {
316 op, why := Assignop(n.Type(), t)
318 base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why)
322 r := ir.NewConvExpr(base.Pos, op, t, n)
328 // Is type src assignment compatible to type dst?
329 // If so, return op code to use in conversion.
330 // If not, return OXXX. In this case, the string return parameter may
331 // hold a reason why. In all other cases, it'll be the empty string.
332 func Assignop(src, dst *types.Type) (ir.Op, string) {
334 return ir.OCONVNOP, ""
336 if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
340 // 1. src type is identical to dst.
341 if types.Identical(src, dst) {
342 return ir.OCONVNOP, ""
344 return Assignop1(src, dst)
347 func Assignop1(src, dst *types.Type) (ir.Op, string) {
348 // 2. src and dst have identical underlying types and
349 // a. either src or dst is not a named type, or
350 // b. both are empty interface types, or
351 // c. at least one is a gcshape type.
352 // For assignable but different non-empty interface types,
353 // we want to recompute the itab. Recomputing the itab ensures
354 // that itabs are unique (thus an interface with a compile-time
355 // type I has an itab with interface type I).
356 if types.Identical(src.Underlying(), dst.Underlying()) {
357 if src.IsEmptyInterface() {
358 // Conversion between two empty interfaces
360 return ir.OCONVNOP, ""
362 if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
363 // Conversion between two types, at least one unnamed,
364 // needs no conversion. The exception is nonempty interfaces
365 // which need to have their itab updated.
366 return ir.OCONVNOP, ""
368 if src.IsShape() || dst.IsShape() {
369 // Conversion between a shape type and one of the types
370 // it represents also needs no conversion.
371 return ir.OCONVNOP, ""
375 // 3. dst is an interface type and src implements dst.
376 if dst.IsInterface() && src.Kind() != types.TNIL {
377 var missing, have *types.Field
380 // Shape types implement things they have already
381 // been typechecked to implement, even if they
382 // don't have the methods for them.
383 return ir.OCONVIFACE, ""
385 if base.Debug.Unified != 0 && src.HasShape() {
386 // Unified IR uses OCONVIFACE for converting all derived types
387 // to interface type, not just type arguments themselves.
388 return ir.OCONVIFACE, ""
390 if implements(src, dst, &missing, &have, &ptr) {
391 return ir.OCONVIFACE, ""
395 if isptrto(src, types.TINTER) {
396 why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
397 } else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
398 why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
399 } else if have != nil && have.Sym == missing.Sym {
400 why = fmt.Sprintf(":\n\t%v does not implement %v %s", src, dst, wrongTypeFor(have.Sym, have.Type, missing.Sym, missing.Type))
402 why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
403 } else if have != nil {
404 why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
405 "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
407 why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
413 if isptrto(dst, types.TINTER) {
414 why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
418 if src.IsInterface() && dst.Kind() != types.TBLANK {
419 var missing, have *types.Field
422 if implements(dst, src, &missing, &have, &ptr) {
423 why = ": need type assertion"
428 // 4. src is a bidirectional channel value, dst is a channel type,
429 // src and dst have identical element types, and
430 // either src or dst is not a named type.
431 if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
432 if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
433 return ir.OCONVNOP, ""
437 // 5. src is the predeclared identifier nil and dst is a nillable type.
438 if src.Kind() == types.TNIL {
446 return ir.OCONVNOP, ""
450 // 6. rule about untyped constants - already converted by DefaultLit.
452 // 7. Any typed value can be assigned to the blank identifier.
453 if dst.Kind() == types.TBLANK {
454 return ir.OCONVNOP, ""
460 // Can we convert a value of type src to a value of type dst?
461 // If so, return op code to use in conversion (maybe OCONVNOP).
462 // If not, return OXXX. In this case, the string return parameter may
463 // hold a reason why. In all other cases, it'll be the empty string.
464 // srcConstant indicates whether the value of type src is a constant.
465 func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
467 return ir.OCONVNOP, ""
469 if src == nil || dst == nil {
473 // Conversions from regular to not-in-heap are not allowed
474 // (unless it's unsafe.Pointer). These are runtime-specific
476 // (a) Disallow (*T) to (*U) where T is not-in-heap but U isn't.
477 if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
478 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
481 // (b) Disallow string to []T where T is not-in-heap.
482 if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
483 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
487 // 1. src can be assigned to dst.
488 op, why := Assignop(src, dst)
493 // The rules for interfaces are no different in conversions
494 // than assignments. If interfaces are involved, stop now
495 // with the good message from assignop.
496 // Otherwise clear the error.
497 if src.IsInterface() || dst.IsInterface() {
501 // 2. Ignoring struct tags, src and dst have identical underlying types.
502 if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
503 return ir.OCONVNOP, ""
506 // 3. src and dst are unnamed pointer types and, ignoring struct tags,
507 // their base types have identical underlying types.
508 if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
509 if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
510 return ir.OCONVNOP, ""
514 // 4. src and dst are both integer or floating point types.
515 if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
516 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
517 return ir.OCONVNOP, ""
522 // 5. src and dst are both complex types.
523 if src.IsComplex() && dst.IsComplex() {
524 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
525 return ir.OCONVNOP, ""
530 // Special case for constant conversions: any numeric
531 // conversion is potentially okay. We'll validate further
532 // within evconst. See #38117.
533 if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
537 // 6. src is an integer or has type []byte or []rune
538 // and dst is a string type.
539 if src.IsInteger() && dst.IsString() {
540 return ir.ORUNESTR, ""
543 if src.IsSlice() && dst.IsString() {
544 if src.Elem().Kind() == types.ByteType.Kind() {
545 return ir.OBYTES2STR, ""
547 if src.Elem().Kind() == types.RuneType.Kind() {
548 return ir.ORUNES2STR, ""
552 // 7. src is a string and dst is []byte or []rune.
554 if src.IsString() && dst.IsSlice() {
555 if dst.Elem().Kind() == types.ByteType.Kind() {
556 return ir.OSTR2BYTES, ""
558 if dst.Elem().Kind() == types.RuneType.Kind() {
559 return ir.OSTR2RUNES, ""
563 // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
564 if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
565 return ir.OCONVNOP, ""
568 // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
569 if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
570 return ir.OCONVNOP, ""
573 // 10. src is map and dst is a pointer to corresponding hmap.
574 // This rule is needed for the implementation detail that
575 // go gc maps are implemented as a pointer to a hmap struct.
576 if src.Kind() == types.TMAP && dst.IsPtr() &&
577 src.MapType().Hmap == dst.Elem() {
578 return ir.OCONVNOP, ""
581 // 11. src is a slice and dst is an array or pointer-to-array.
582 // They must have same element type.
584 if dst.IsArray() && types.Identical(src.Elem(), dst.Elem()) {
585 return ir.OSLICE2ARR, ""
587 if dst.IsPtr() && dst.Elem().IsArray() &&
588 types.Identical(src.Elem(), dst.Elem().Elem()) {
589 return ir.OSLICE2ARRPTR, ""
596 // Code to resolve elided DOTs in embedded types.
598 // A dlist stores a pointer to a TFIELD Type embedded within
599 // a TSTRUCT or TINTER Type.
604 // dotpath computes the unique shortest explicit selector path to fully qualify
605 // a selection expression x.f, where x is of type t and f is the symbol s.
606 // If no such path exists, dotpath returns nil.
607 // If there are multiple shortest paths to the same depth, ambig is true.
608 func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []dlist, ambig bool) {
609 // The embedding of types within structs imposes a tree structure onto
610 // types: structs parent the types they embed, and types parent their
611 // fields or methods. Our goal here is to find the shortest path to
612 // a field or method named s in the subtree rooted at t. To accomplish
613 // that, we iteratively perform depth-first searches of increasing depth
614 // until we either find the named field/method or exhaust the tree.
616 if d > len(dotlist) {
617 dotlist = append(dotlist, dlist{})
619 if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
620 return dotlist[:d], false
629 func expand0(t *types.Type) {
636 for _, f := range u.AllMethods().Slice() {
641 slist = append(slist, symlink{field: f})
647 u = types.ReceiverBaseType(t)
649 for _, f := range u.Methods().Slice() {
654 slist = append(slist, symlink{field: f})
659 func expand1(t *types.Type, top bool) {
674 if u.IsStruct() || u.IsInterface() {
675 var fields *types.Fields
679 fields = u.AllMethods()
681 for _, f := range fields.Slice() {
688 expand1(f.Type, false)
695 func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, followptr bool) {
700 path, ambig := dotpath(s, t, &m, ignorecase)
703 base.Errorf("%v.%v is ambiguous", t, s)
708 for _, d := range path {
709 if d.field.Type.IsPtr() {
716 base.Errorf("%v.%v is a field, not a method", t, s)
717 return nil, followptr
723 // implements reports whether t implements the interface iface. t can be
724 // an interface, a type parameter, or a concrete type. If implements returns
725 // false, it stores a method of iface that is not implemented in *m. If the
726 // method name matches but the type is wrong, it additionally stores the type
727 // of the method (on t) in *samename.
728 func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
734 if t.IsInterface() || t.IsTypeParam() {
736 // If t is a simple type parameter T, its type and underlying is the same.
737 // If t is a type definition:'type P[T any] T', its type is P[T] and its
738 // underlying is T. Therefore we use 't.Underlying() != t' to distinguish them.
739 if t.Underlying() != t {
742 // A typeparam satisfies an interface if its type bound
743 // has all the methods of that interface.
748 tms := t.AllMethods().Slice()
749 for _, im := range iface.AllMethods().Slice() {
750 for i < len(tms) && tms[i].Sym != im.Sym {
760 if !types.Identical(tm.Type, im.Type) {
771 t = types.ReceiverBaseType(t)
772 var tms []*types.Field
775 tms = t.AllMethods().Slice()
778 for _, im := range iface.AllMethods().Slice() {
779 for i < len(tms) && tms[i].Sym != im.Sym {
784 *samename, _ = ifacelookdot(im.Sym, t, true)
789 if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
795 followptr := tm.Embedded == 2
797 // if pointer receiver in method,
798 // the method does not exist for value types.
799 rcvr := tm.Type.Recv().Type
800 if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !types.IsInterfaceMethod(tm.Type) {
801 if false && base.Flag.LowerR != 0 {
802 base.Errorf("interface pointer mismatch")
815 func isptrto(t *types.Type, et types.Kind) bool {
832 // lookdot0 returns the number of fields or methods named s associated
833 // with Type t. If exactly one exists, it will be returned in *save
834 // (if save is not nil).
835 func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
842 if u.IsStruct() || u.IsInterface() {
843 var fields *types.Fields
847 fields = u.AllMethods()
849 for _, f := range fields.Slice() {
850 if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
860 if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
861 // If t is a defined pointer type, then x.m is shorthand for (*x).m.
864 u = types.ReceiverBaseType(u)
866 for _, f := range u.Methods().Slice() {
867 if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
881 // Code to help generate trampoline functions for methods on embedded
882 // types. These are approx the same as the corresponding AddImplicitDots
883 // routines except that they expect to be called with unique tasks and
884 // they return the actual methods.
886 type symlink struct {
890 // TypesOf converts a list of nodes to a list
891 // of types of those nodes.
892 func TypesOf(x []ir.Ntype) []*types.Type {
893 r := make([]*types.Type, len(x))
894 for i, n := range x {
900 // addTargs writes out the targs to buffer b as a comma-separated list enclosed by
902 func addTargs(b *bytes.Buffer, targs []*types.Type) {
904 for i, targ := range targs {
908 // Make sure that type arguments (including type params), are
909 // uniquely specified. LinkString() eliminates all spaces
910 // and includes the package path (local package path is "" before
911 // linker substitution).
912 tstring := targ.LinkString()
913 b.WriteString(tstring)
918 // InstTypeName creates a name for an instantiated type, based on the name of the
919 // generic type and the type args.
920 func InstTypeName(name string, targs []*types.Type) string {
921 b := bytes.NewBufferString(name)
926 // makeInstName1 returns the name of the generic function instantiated with the
927 // given types, which can have type params or shapes, or be concrete types. name is
928 // the name of the generic function or method.
929 func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string {
930 b := bytes.NewBufferString("")
931 i := strings.Index(name, "[")
932 assert(hasBrackets == (i >= 0))
934 b.WriteString(name[0:i])
940 i2 := strings.LastIndex(name[i:], "]")
942 b.WriteString(name[i+i2+1:])
947 // MakeFuncInstSym makes the unique sym for a stenciled generic function or method,
948 // based on the name of the function gf and the targs. It replaces any
949 // existing bracket type list in the name. MakeInstName asserts that gf has
950 // brackets in its name if and only if hasBrackets is true.
952 // Names of declared generic functions have no brackets originally, so hasBrackets
953 // should be false. Names of generic methods already have brackets, since the new
954 // type parameter is specified in the generic type of the receiver (e.g. func
955 // (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set.
957 // The standard naming is something like: 'genFn[int,bool]' for functions and
958 // '(*genType[int,bool]).methodName' for methods
960 // isMethodNode specifies if the name of a method node is being generated (as opposed
961 // to a name of an instantiation of generic function or name of the shape-based
962 // function that helps implement a method of an instantiated type). For method nodes
963 // on shape types, we prepend "nofunc.", because method nodes for shape types will
964 // have no body, and we want to avoid a name conflict with the shape-based function
965 // that helps implement the same method for fully-instantiated types. Function names
966 // are also created at the end of (*Tsubster).typ1, so we append "nofunc" there as
968 func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, isMethodNode, hasBrackets bool) *types.Sym {
969 nm := makeInstName1(gf.Name, targs, hasBrackets)
970 if targs[0].HasShape() && isMethodNode {
973 return gf.Pkg.Lookup(nm)
976 func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym {
977 for _, targ := range targs {
978 if targ.HasTParam() {
979 fmt.Printf("FUNCTION %s\n", gf.Name)
980 for _, targ := range targs {
981 fmt.Printf(" PARAM %+v\n", targ)
983 panic("dictionary should always have concrete type args")
986 name := makeInstName1(gf.Name, targs, hasBrackets)
987 name = fmt.Sprintf("%s.%s", objabi.GlobalDictPrefix, name)
988 return gf.Pkg.Lookup(name)
991 func assert(p bool) {
995 // List of newly fully-instantiated types who should have their methods generated.
996 var instTypeList []*types.Type
998 // NeedInstType adds a new fully-instantiated type to instTypeList.
999 func NeedInstType(t *types.Type) {
1000 instTypeList = append(instTypeList, t)
1003 // GetInstTypeList returns the current contents of instTypeList.
1004 func GetInstTypeList() []*types.Type {
1009 // ClearInstTypeList clears the contents of instTypeList.
1010 func ClearInstTypeList() {
1014 // General type substituter, for replacing typeparams with type args.
1015 type Tsubster struct {
1016 Tparams []*types.Type
1018 // If non-nil, the substitution map from name nodes in the generic function to the
1019 // name nodes in the new stenciled function.
1020 Vars map[*ir.Name]*ir.Name
1021 // If non-nil, function to substitute an incomplete (TFORW) type.
1022 SubstForwFunc func(*types.Type) *types.Type
1023 // Prevent endless recursion on functions. See #51832.
1024 Funcs map[*types.Type]bool
1027 // Typ computes the type obtained by substituting any type parameter or shape in t
1028 // that appears in subst.Tparams with the corresponding type argument in subst.Targs.
1029 // If t contains no type parameters, the result is t; otherwise the result is a new
1030 // type. It deals with recursive types by using TFORW types and finding partially or
1031 // fully created types via sym.Def.
1032 func (ts *Tsubster) Typ(t *types.Type) *types.Type {
1033 // Defer the CheckSize calls until we have fully-defined
1034 // (possibly-recursive) top-level type.
1035 types.DeferCheckSize()
1037 types.ResumeCheckSize()
1041 func (ts *Tsubster) typ1(t *types.Type) *types.Type {
1042 hasParamOrShape := t.HasTParam() || t.HasShape()
1043 if !hasParamOrShape && t.Kind() != types.TFUNC {
1044 // Note: function types need to be copied regardless, as the
1045 // types of closures may contain declarations that need
1046 // to be copied. See #45738.
1050 if t.IsTypeParam() || t.IsShape() {
1051 for i, tp := range ts.Tparams {
1056 // If t is a simple typeparam T, then t has the name/symbol 'T'
1057 // and t.Underlying() == t.
1059 // However, consider the type definition: 'type P[T any] T'. We
1060 // might use this definition so we can have a variant of type T
1061 // that we can add new methods to. Suppose t is a reference to
1062 // P[T]. t has the name 'P[T]', but its kind is TTYPEPARAM,
1063 // because P[T] is defined as T. If we look at t.Underlying(), it
1064 // is different, because the name of t.Underlying() is 'T' rather
1065 // than 'P[T]'. But the kind of t.Underlying() is also TTYPEPARAM.
1066 // In this case, we do the needed recursive substitution in the
1067 // case statement below.
1068 if t.Underlying() == t {
1069 // t is a simple typeparam that didn't match anything in tparam
1072 // t is a more complex typeparam (e.g. P[T], as above, whose
1073 // definition is just T).
1074 assert(t.Sym() != nil)
1077 var newsym *types.Sym
1078 var neededTargs []*types.Type
1079 var targsChanged bool // == are there any substitutions from this
1080 var forw *types.Type
1082 if t.Sym() != nil && hasParamOrShape {
1083 // Need to test for t.HasTParam() again because of special TFUNC case above.
1084 // Translate the type params for this type according to
1085 // the tparam/targs mapping from subst.
1086 neededTargs = make([]*types.Type, len(t.RParams()))
1087 for i, rparam := range t.RParams() {
1088 neededTargs[i] = ts.typ1(rparam)
1089 if !types.IdenticalStrict(neededTargs[i], rparam) {
1093 // For a named (defined) type, we have to change the name of the
1094 // type as well. We do this first, so we can look up if we've
1095 // already seen this type during this substitution or other
1096 // definitions/substitutions.
1097 genName := genericTypeName(t.Sym())
1098 newsym = t.Sym().Pkg.Lookup(InstTypeName(genName, neededTargs))
1099 if newsym.Def != nil {
1100 // We've already created this instantiated defined type.
1101 return newsym.Def.Type()
1104 // In order to deal with recursive generic types, create a TFORW
1105 // type initially and set the Def field of its sym, so it can be
1106 // found if this type appears recursively within the type.
1107 forw = NewIncompleteNamedType(t.Pos(), newsym)
1108 //println("Creating new type by sub", newsym.Name, forw.HasTParam())
1109 forw.SetRParams(neededTargs)
1110 // Copy the OrigType from the re-instantiated type (which is the sym of
1111 // the base generic type).
1112 assert(t.OrigType() != nil)
1113 forw.SetOrigType(t.OrigType())
1116 var newt *types.Type
1119 case types.TTYPEPARAM:
1120 if t.Sym() == newsym && !targsChanged {
1121 // The substitution did not change the type.
1124 // Substitute the underlying typeparam (e.g. T in P[T], see
1125 // the example describing type P[T] above).
1126 newt = ts.typ1(t.Underlying())
1131 newelem := ts.typ1(elem)
1132 if newelem != elem || targsChanged {
1133 newt = types.NewArray(newelem, t.NumElem())
1138 newelem := ts.typ1(elem)
1139 if newelem != elem || targsChanged {
1140 newt = types.NewPtr(newelem)
1145 newelem := ts.typ1(elem)
1146 if newelem != elem || targsChanged {
1147 newt = types.NewSlice(newelem)
1151 newt = ts.tstruct(t, targsChanged)
1157 // watch out for endless recursion on plain function types that mention themselves, e.g. "type T func() T"
1158 if !hasParamOrShape {
1159 if ts.Funcs[t] { // Visit such function types only once.
1162 if ts.Funcs == nil {
1164 ts.Funcs = make(map[*types.Type]bool)
1168 newrecvs := ts.tstruct(t.Recvs(), false)
1169 newparams := ts.tstruct(t.Params(), false)
1170 newresults := ts.tstruct(t.Results(), false)
1171 // Translate the tparams of a signature.
1172 newtparams := ts.tstruct(t.TParams(), false)
1173 if newrecvs != t.Recvs() || newparams != t.Params() ||
1174 newresults != t.Results() || newtparams != t.TParams() || targsChanged {
1175 // If any types have changed, then the all the fields of
1176 // of recv, params, and results must be copied, because they have
1177 // offset fields that are dependent, and so must have an
1178 // independent copy for each new signature.
1179 var newrecv *types.Field
1180 if newrecvs.NumFields() > 0 {
1181 if newrecvs == t.Recvs() {
1182 newrecvs = ts.tstruct(t.Recvs(), true)
1184 newrecv = newrecvs.Field(0)
1186 if newparams == t.Params() {
1187 newparams = ts.tstruct(t.Params(), true)
1189 if newresults == t.Results() {
1190 newresults = ts.tstruct(t.Results(), true)
1192 var tparamfields []*types.Field
1193 if newtparams.HasTParam() {
1194 tparamfields = newtparams.FieldSlice()
1196 // Completely remove the tparams from the resulting
1197 // signature, if the tparams are now concrete types.
1200 newt = types.NewSignature(t.Pkg(), newrecv, tparamfields,
1201 newparams.FieldSlice(), newresults.FieldSlice())
1203 if !hasParamOrShape {
1208 newt = ts.tinter(t, targsChanged)
1214 newkey := ts.typ1(t.Key())
1215 newval := ts.typ1(t.Elem())
1216 if newkey != t.Key() || newval != t.Elem() || targsChanged {
1217 newt = types.NewMap(newkey, newval)
1222 newelem := ts.typ1(elem)
1223 if newelem != elem || targsChanged {
1224 newt = types.NewChan(newelem, t.ChanDir())
1227 if ts.SubstForwFunc != nil {
1228 return ts.SubstForwFunc(forw)
1232 case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
1233 types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
1234 types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR:
1235 newt = t.Underlying()
1238 newterms := make([]*types.Type, nt)
1239 tildes := make([]bool, nt)
1241 for i := 0; i < nt; i++ {
1242 term, tilde := t.Term(i)
1244 newterms[i] = ts.typ1(term)
1245 if newterms[i] != term {
1250 newt = types.NewUnion(newterms, tildes)
1253 panic(fmt.Sprintf("Bad type in (*TSubster).Typ: %v", t.Kind()))
1256 // Even though there were typeparams in the type, there may be no
1257 // change if this is a function type for a function call (which will
1258 // have its own tparams/targs in the function instantiation).
1263 forw.SetUnderlying(newt)
1267 if !newt.HasTParam() && !newt.IsFuncArgStruct() {
1268 // Calculate the size of any new types created. These will be
1269 // deferred until the top-level ts.Typ() or g.typ() (if this is
1270 // called from g.fillinMethods()).
1271 types.CheckSize(newt)
1274 if t.Kind() != types.TINTER && t.Methods().Len() > 0 {
1275 // Fill in the method info for the new type.
1276 var newfields []*types.Field
1277 newfields = make([]*types.Field, t.Methods().Len())
1278 for i, f := range t.Methods().Slice() {
1279 t2 := ts.typ1(f.Type)
1280 oldsym := f.Nname.Sym()
1282 // Use the name of the substituted receiver to create the
1283 // method name, since the receiver name may have many levels
1284 // of nesting (brackets) with type names to be substituted.
1285 recvType := t2.Recv().Type
1287 if recvType.IsPtr() {
1288 recvType = recvType.Elem()
1289 nm = "(*" + recvType.Sym().Name + ")." + f.Sym.Name
1291 nm = recvType.Sym().Name + "." + f.Sym.Name
1293 if recvType.RParams()[0].HasShape() {
1294 // We add "nofunc" to methods of shape type to avoid
1295 // conflict with the name of the shape-based helper
1296 // function. See header comment of MakeFuncInstSym.
1299 newsym := oldsym.Pkg.Lookup(nm)
1301 if newsym.Def != nil {
1302 nname = newsym.Def.(*ir.Name)
1304 nname = ir.NewNameAt(f.Pos, newsym)
1309 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1310 newfields[i].Nname = nname
1312 newt.Methods().Set(newfields)
1313 if !newt.HasTParam() && !newt.HasShape() {
1314 // Generate all the methods for a new fully-instantiated type.
1322 // tstruct substitutes type params in types of the fields of a structure type. For
1323 // each field, tstruct copies the Nname, and translates it if Nname is in
1324 // ts.vars. To always force the creation of a new (top-level) struct,
1325 // regardless of whether anything changed with the types or names of the struct's
1326 // fields, set force to true.
1327 func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
1328 if t.NumFields() == 0 {
1329 if t.HasTParam() || t.HasShape() {
1330 // For an empty struct, we need to return a new type, if
1331 // substituting from a generic type or shape type, since it
1332 // will change HasTParam/HasShape flags.
1333 return types.NewStruct(t.Pkg(), nil)
1337 var newfields []*types.Field
1339 newfields = make([]*types.Field, t.NumFields())
1341 for i, f := range t.Fields().Slice() {
1342 t2 := ts.typ1(f.Type)
1343 if (t2 != f.Type || f.Nname != nil) && newfields == nil {
1344 newfields = make([]*types.Field, t.NumFields())
1345 for j := 0; j < i; j++ {
1346 newfields[j] = t.Field(j)
1349 if newfields != nil {
1350 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1351 newfields[i].Embedded = f.Embedded
1352 newfields[i].Note = f.Note
1354 newfields[i].SetIsDDD(true)
1356 if f.Nointerface() {
1357 newfields[i].SetNointerface(true)
1359 if f.Nname != nil && ts.Vars != nil {
1360 n := f.Nname.(*ir.Name)
1363 // This is the case where we are
1364 // translating the type of the function we
1365 // are substituting, so its dcls are in
1366 // the subst.ts.vars table, and we want to
1367 // change to reference the new dcl.
1368 newfields[i].Nname = v
1369 } else if ir.IsBlank(n) {
1370 // Blank variable is not dcl list. Make a
1371 // new one to not share.
1372 m := ir.NewNameAt(n.Pos(), ir.BlankNode.Sym())
1375 newfields[i].Nname = m
1377 // This is the case where we are
1378 // translating the type of a function
1379 // reference inside the function we are
1380 // substituting, so we leave the Nname
1382 newfields[i].Nname = f.Nname
1387 if newfields != nil {
1388 news := types.NewStruct(t.Pkg(), newfields)
1389 news.StructType().Funarg = t.StructType().Funarg
1396 // tinter substitutes type params in types of the methods of an interface type.
1397 func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type {
1398 if t.Methods().Len() == 0 {
1399 if t.HasTParam() || t.HasShape() {
1400 // For an empty interface, we need to return a new type, if
1401 // substituting from a generic type or shape type, since
1402 // since it will change HasTParam/HasShape flags.
1403 return types.NewInterface(t.Pkg(), nil, false)
1407 var newfields []*types.Field
1409 newfields = make([]*types.Field, t.Methods().Len())
1411 for i, f := range t.Methods().Slice() {
1412 t2 := ts.typ1(f.Type)
1413 if (t2 != f.Type || f.Nname != nil) && newfields == nil {
1414 newfields = make([]*types.Field, t.Methods().Len())
1415 for j := 0; j < i; j++ {
1416 newfields[j] = t.Methods().Index(j)
1419 if newfields != nil {
1420 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
1423 if newfields != nil {
1424 return types.NewInterface(t.Pkg(), newfields, t.IsImplicit())
1429 // genericTypeName returns the name of the base generic type for the type named by
1430 // sym. It simply returns the name obtained by removing everything after the
1431 // first bracket ("[").
1432 func genericTypeName(sym *types.Sym) string {
1433 return sym.Name[0:strings.Index(sym.Name, "[")]
1436 // getShapes appends the list of the shape types that are used within type t to
1437 // listp. The type traversal is simplified for two reasons: (1) we can always stop a
1438 // type traversal when t.HasShape() is false; and (2) shape types can't appear inside
1439 // a named type, except for the type args of a generic type. So, the traversal will
1440 // always stop before we have to deal with recursive types.
1441 func getShapes(t *types.Type, listp *[]*types.Type) {
1446 *listp = append(*listp, t)
1451 // A named type can't have shapes in it, except for type args of a
1452 // generic type. We will have to deal with this differently once we
1453 // alloc local types in generic functions (#47631).
1454 for _, rparam := range t.RParams() {
1455 getShapes(rparam, listp)
1461 case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
1462 getShapes(t.Elem(), listp)
1465 for _, f := range t.FieldSlice() {
1466 getShapes(f.Type, listp)
1470 for _, f := range t.Recvs().FieldSlice() {
1471 getShapes(f.Type, listp)
1473 for _, f := range t.Params().FieldSlice() {
1474 getShapes(f.Type, listp)
1476 for _, f := range t.Results().FieldSlice() {
1477 getShapes(f.Type, listp)
1479 for _, f := range t.TParams().FieldSlice() {
1480 getShapes(f.Type, listp)
1484 for _, f := range t.Methods().Slice() {
1485 getShapes(f.Type, listp)
1489 getShapes(t.Key(), listp)
1490 getShapes(t.Elem(), listp)
1493 panic(fmt.Sprintf("Bad type in getShapes: %v", t.Kind()))
1498 // Shapify takes a concrete type and a type param index, and returns a GCshape type that can
1499 // be used in place of the input type and still generate identical code.
1500 // No methods are added - all methods calls directly on a shape should
1501 // be done by converting to an interface using the dictionary.
1503 // For now, we only consider two types to have the same shape, if they have exactly
1504 // the same underlying type or they are both pointer types.
1506 // tparam is the associated typeparam - it must be TTYPEPARAM type. If there is a
1507 // structural type for the associated type param (not common), then a pointer type t
1508 // is mapped to its underlying type, rather than being merged with other pointers.
1510 // Shape types are also distinguished by the index of the type in a type param/arg
1511 // list. We need to do this so we can distinguish and substitute properly for two
1512 // type params in the same function that have the same shape for a particular
1514 func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type {
1515 assert(!t.IsShape())
1517 // We are sometimes dealing with types from a shape instantiation
1518 // that were constructed from existing shape types, so t may
1519 // sometimes have shape types inside it. In that case, we find all
1520 // those shape types with getShapes() and replace them with their
1523 // If we don't do this, we may create extra unneeded shape types that
1524 // have these other shape types embedded in them. This may lead to
1525 // generating extra shape instantiations, and a mismatch between the
1526 // instantiations that we used in generating dictionaries and the
1527 // instantations that are actually called. (#51303).
1528 list := []*types.Type{}
1530 list2 := make([]*types.Type, len(list))
1531 for i, shape := range list {
1532 list2[i] = shape.Underlying()
1540 // Map all types with the same underlying type to the same shape.
1543 // All pointers have the same shape.
1544 // TODO: Make unsafe.Pointer the same shape as normal pointers.
1545 // Note: pointers to arrays are special because of slice-to-array-pointer
1546 // conversions. See issue 49295.
1547 if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY &&
1548 tparam.Bound().StructuralType() == nil && !u.Elem().NotInHeap() {
1549 u = types.Types[types.TUINT8].PtrTo()
1552 submap := shapeMap[index]
1554 submap = map[*types.Type]*types.Type{}
1555 shapeMap[index] = submap
1557 if s := submap[u]; s != nil {
1561 // LinkString specifies the type uniquely, but has no spaces.
1562 nm := fmt.Sprintf("%s_%d", u.LinkString(), index)
1563 sym := types.ShapePkg.Lookup(nm)
1565 // Use any existing type with the same name
1566 submap[u] = sym.Def.Type()
1569 name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym)
1570 s := types.NewNamed(name)
1577 name.SetTypecheck(1)
1582 var shapeMap = map[int]map[*types.Type]*types.Type{}