1// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
2// Source: ../../cmd/compile/internal/types2/named.go
3
4// Copyright 2011 The Go Authors. All rights reserved.
5// Use of this source code is governed by a BSD-style
6// license that can be found in the LICENSE file.
7
8package types
9
10import (
11	"go/token"
12	"strings"
13	"sync"
14	"sync/atomic"
15)
16
17// Type-checking Named types is subtle, because they may be recursively
18// defined, and because their full details may be spread across multiple
19// declarations (via methods). For this reason they are type-checked lazily,
20// to avoid information being accessed before it is complete.
21//
22// Conceptually, it is helpful to think of named types as having two distinct
23// sets of information:
24//  - "LHS" information, defining their identity: Obj() and TypeArgs()
25//  - "RHS" information, defining their details: TypeParams(), Underlying(),
26//    and methods.
27//
28// In this taxonomy, LHS information is available immediately, but RHS
29// information is lazy. Specifically, a named type N may be constructed in any
30// of the following ways:
31//  1. type-checked from the source
32//  2. loaded eagerly from export data
33//  3. loaded lazily from export data (when using unified IR)
34//  4. instantiated from a generic type
35//
36// In cases 1, 3, and 4, it is possible that the underlying type or methods of
37// N may not be immediately available.
38//  - During type-checking, we allocate N before type-checking its underlying
39//    type or methods, so that we may resolve recursive references.
40//  - When loading from export data, we may load its methods and underlying
41//    type lazily using a provided load function.
42//  - After instantiating, we lazily expand the underlying type and methods
43//    (note that instances may be created while still in the process of
44//    type-checking the original type declaration).
45//
46// In cases 3 and 4 this lazy construction may also occur concurrently, due to
47// concurrent use of the type checker API (after type checking or importing has
48// finished). It is critical that we keep track of state, so that Named types
49// are constructed exactly once and so that we do not access their details too
50// soon.
51//
52// We achieve this by tracking state with an atomic state variable, and
53// guarding potentially concurrent calculations with a mutex. At any point in
54// time this state variable determines which data on N may be accessed. As
55// state monotonically progresses, any data available at state M may be
56// accessed without acquiring the mutex at state N, provided N >= M.
57//
58// GLOSSARY: Here are a few terms used in this file to describe Named types:
59//  - We say that a Named type is "instantiated" if it has been constructed by
60//    instantiating a generic named type with type arguments.
61//  - We say that a Named type is "declared" if it corresponds to a type
62//    declaration in the source. Instantiated named types correspond to a type
63//    instantiation in the source, not a declaration. But their Origin type is
64//    a declared type.
65//  - We say that a Named type is "resolved" if its RHS information has been
66//    loaded or fully type-checked. For Named types constructed from export
67//    data, this may involve invoking a loader function to extract information
68//    from export data. For instantiated named types this involves reading
69//    information from their origin.
70//  - We say that a Named type is "expanded" if it is an instantiated type and
71//    type parameters in its underlying type and methods have been substituted
72//    with the type arguments from the instantiation. A type may be partially
73//    expanded if some but not all of these details have been substituted.
74//    Similarly, we refer to these individual details (underlying type or
75//    method) as being "expanded".
76//  - When all information is known for a named type, we say it is "complete".
77//
78// Some invariants to keep in mind: each declared Named type has a single
79// corresponding object, and that object's type is the (possibly generic) Named
80// type. Declared Named types are identical if and only if their pointers are
81// identical. On the other hand, multiple instantiated Named types may be
82// identical even though their pointers are not identical. One has to use
83// Identical to compare them. For instantiated named types, their obj is a
84// synthetic placeholder that records their position of the corresponding
85// instantiation in the source (if they were constructed during type checking).
86//
87// To prevent infinite expansion of named instances that are created outside of
88// type-checking, instances share a Context with other instances created during
89// their expansion. Via the pidgeonhole principle, this guarantees that in the
90// presence of a cycle of named types, expansion will eventually find an
91// existing instance in the Context and short-circuit the expansion.
92//
93// Once an instance is complete, we can nil out this shared Context to unpin
94// memory, though this Context may still be held by other incomplete instances
95// in its "lineage".
96
97// A Named represents a named (defined) type.
98type Named struct {
99	check *Checker  // non-nil during type-checking; nil otherwise
100	obj   *TypeName // corresponding declared object for declared types; see above for instantiated types
101
102	// fromRHS holds the type (on RHS of declaration) this *Named type is derived
103	// from (for cycle reporting). Only used by validType, and therefore does not
104	// require synchronization.
105	fromRHS Type
106
107	// information for instantiated types; nil otherwise
108	inst *instance
109
110	mu         sync.Mutex     // guards all fields below
111	state_     uint32         // the current state of this type; must only be accessed atomically
112	underlying Type           // possibly a *Named during setup; never a *Named once set up completely
113	tparams    *TypeParamList // type parameters, or nil
114
115	// methods declared for this type (not the method set of this type)
116	// Signatures are type-checked lazily.
117	// For non-instantiated types, this is a fully populated list of methods. For
118	// instantiated types, methods are individually expanded when they are first
119	// accessed.
120	methods []*Func
121
122	// loader may be provided to lazily load type parameters, underlying type, and methods.
123	loader func(*Named) (tparams []*TypeParam, underlying Type, methods []*Func)
124}
125
126// instance holds information that is only necessary for instantiated named
127// types.
128type instance struct {
129	orig            *Named    // original, uninstantiated type
130	targs           *TypeList // type arguments
131	expandedMethods int       // number of expanded methods; expandedMethods <= len(orig.methods)
132	ctxt            *Context  // local Context; set to nil after full expansion
133}
134
135// namedState represents the possible states that a named type may assume.
136type namedState uint32
137
138const (
139	unresolved namedState = iota // tparams, underlying type and methods might be unavailable
140	resolved                     // resolve has run; methods might be incomplete (for instances)
141	complete                     // all data is known
142)
143
144// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
145// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
146// The underlying type must not be a *Named.
147func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
148	if asNamed(underlying) != nil {
149		panic("underlying type must not be *Named")
150	}
151	return (*Checker)(nil).newNamed(obj, underlying, methods)
152}
153
154// resolve resolves the type parameters, methods, and underlying type of n.
155// This information may be loaded from a provided loader function, or computed
156// from an origin type (in the case of instances).
157//
158// After resolution, the type parameters, methods, and underlying type of n are
159// accessible; but if n is an instantiated type, its methods may still be
160// unexpanded.
161func (n *Named) resolve() *Named {
162	if n.state() >= resolved { // avoid locking below
163		return n
164	}
165
166	// TODO(rfindley): if n.check is non-nil we can avoid locking here, since
167	// type-checking is not concurrent. Evaluate if this is worth doing.
168	n.mu.Lock()
169	defer n.mu.Unlock()
170
171	if n.state() >= resolved {
172		return n
173	}
174
175	if n.inst != nil {
176		assert(n.underlying == nil) // n is an unresolved instance
177		assert(n.loader == nil)     // instances are created by instantiation, in which case n.loader is nil
178
179		orig := n.inst.orig
180		orig.resolve()
181		underlying := n.expandUnderlying()
182
183		n.tparams = orig.tparams
184		n.underlying = underlying
185		n.fromRHS = orig.fromRHS // for cycle detection
186
187		if len(orig.methods) == 0 {
188			n.setState(complete) // nothing further to do
189			n.inst.ctxt = nil
190		} else {
191			n.setState(resolved)
192		}
193		return n
194	}
195
196	// TODO(mdempsky): Since we're passing n to the loader anyway
197	// (necessary because types2 expects the receiver type for methods
198	// on defined interface types to be the Named rather than the
199	// underlying Interface), maybe it should just handle calling
200	// SetTypeParams, SetUnderlying, and AddMethod instead?  Those
201	// methods would need to support reentrant calls though. It would
202	// also make the API more future-proof towards further extensions.
203	if n.loader != nil {
204		assert(n.underlying == nil)
205		assert(n.TypeArgs().Len() == 0) // instances are created by instantiation, in which case n.loader is nil
206
207		tparams, underlying, methods := n.loader(n)
208
209		n.tparams = bindTParams(tparams)
210		n.underlying = underlying
211		n.fromRHS = underlying // for cycle detection
212		n.methods = methods
213		n.loader = nil
214	}
215
216	n.setState(complete)
217	return n
218}
219
220// state atomically accesses the current state of the receiver.
221func (n *Named) state() namedState {
222	return namedState(atomic.LoadUint32(&n.state_))
223}
224
225// setState atomically stores the given state for n.
226// Must only be called while holding n.mu.
227func (n *Named) setState(state namedState) {
228	atomic.StoreUint32(&n.state_, uint32(state))
229}
230
231// newNamed is like NewNamed but with a *Checker receiver.
232func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
233	typ := &Named{check: check, obj: obj, fromRHS: underlying, underlying: underlying, methods: methods}
234	if obj.typ == nil {
235		obj.typ = typ
236	}
237	// Ensure that typ is always sanity-checked.
238	if check != nil {
239		check.needsCleanup(typ)
240	}
241	return typ
242}
243
244// newNamedInstance creates a new named instance for the given origin and type
245// arguments, recording pos as the position of its synthetic object (for error
246// reporting).
247//
248// If set, expanding is the named type instance currently being expanded, that
249// led to the creation of this instance.
250func (check *Checker) newNamedInstance(pos token.Pos, orig *Named, targs []Type, expanding *Named) *Named {
251	assert(len(targs) > 0)
252
253	obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
254	inst := &instance{orig: orig, targs: newTypeList(targs)}
255
256	// Only pass the expanding context to the new instance if their packages
257	// match. Since type reference cycles are only possible within a single
258	// package, this is sufficient for the purposes of short-circuiting cycles.
259	// Avoiding passing the context in other cases prevents unnecessary coupling
260	// of types across packages.
261	if expanding != nil && expanding.Obj().pkg == obj.pkg {
262		inst.ctxt = expanding.inst.ctxt
263	}
264	typ := &Named{check: check, obj: obj, inst: inst}
265	obj.typ = typ
266	// Ensure that typ is always sanity-checked.
267	if check != nil {
268		check.needsCleanup(typ)
269	}
270	return typ
271}
272
273func (t *Named) cleanup() {
274	assert(t.inst == nil || t.inst.orig.inst == nil)
275	// Ensure that every defined type created in the course of type-checking has
276	// either non-*Named underlying type, or is unexpanded.
277	//
278	// This guarantees that we don't leak any types whose underlying type is
279	// *Named, because any unexpanded instances will lazily compute their
280	// underlying type by substituting in the underlying type of their origin.
281	// The origin must have either been imported or type-checked and expanded
282	// here, and in either case its underlying type will be fully expanded.
283	switch t.underlying.(type) {
284	case nil:
285		if t.TypeArgs().Len() == 0 {
286			panic("nil underlying")
287		}
288	case *Named, *Alias:
289		t.under() // t.under may add entries to check.cleaners
290	}
291	t.check = nil
292}
293
294// Obj returns the type name for the declaration defining the named type t. For
295// instantiated types, this is same as the type name of the origin type.
296func (t *Named) Obj() *TypeName {
297	if t.inst == nil {
298		return t.obj
299	}
300	return t.inst.orig.obj
301}
302
303// Origin returns the generic type from which the named type t is
304// instantiated. If t is not an instantiated type, the result is t.
305func (t *Named) Origin() *Named {
306	if t.inst == nil {
307		return t
308	}
309	return t.inst.orig
310}
311
312// TypeParams returns the type parameters of the named type t, or nil.
313// The result is non-nil for an (originally) generic type even if it is instantiated.
314func (t *Named) TypeParams() *TypeParamList { return t.resolve().tparams }
315
316// SetTypeParams sets the type parameters of the named type t.
317// t must not have type arguments.
318func (t *Named) SetTypeParams(tparams []*TypeParam) {
319	assert(t.inst == nil)
320	t.resolve().tparams = bindTParams(tparams)
321}
322
323// TypeArgs returns the type arguments used to instantiate the named type t.
324func (t *Named) TypeArgs() *TypeList {
325	if t.inst == nil {
326		return nil
327	}
328	return t.inst.targs
329}
330
331// NumMethods returns the number of explicit methods defined for t.
332func (t *Named) NumMethods() int {
333	return len(t.Origin().resolve().methods)
334}
335
336// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
337//
338// For an ordinary or instantiated type t, the receiver base type of this
339// method is the named type t. For an uninstantiated generic type t, each
340// method receiver is instantiated with its receiver type parameters.
341//
342// Methods are numbered deterministically: given the same list of source files
343// presented to the type checker, or the same sequence of NewMethod and AddMethod
344// calls, the mapping from method index to corresponding method remains the same.
345// But the specific ordering is not specified and must not be relied on as it may
346// change in the future.
347func (t *Named) Method(i int) *Func {
348	t.resolve()
349
350	if t.state() >= complete {
351		return t.methods[i]
352	}
353
354	assert(t.inst != nil) // only instances should have incomplete methods
355	orig := t.inst.orig
356
357	t.mu.Lock()
358	defer t.mu.Unlock()
359
360	if len(t.methods) != len(orig.methods) {
361		assert(len(t.methods) == 0)
362		t.methods = make([]*Func, len(orig.methods))
363	}
364
365	if t.methods[i] == nil {
366		assert(t.inst.ctxt != nil) // we should still have a context remaining from the resolution phase
367		t.methods[i] = t.expandMethod(i)
368		t.inst.expandedMethods++
369
370		// Check if we've created all methods at this point. If we have, mark the
371		// type as fully expanded.
372		if t.inst.expandedMethods == len(orig.methods) {
373			t.setState(complete)
374			t.inst.ctxt = nil // no need for a context anymore
375		}
376	}
377
378	return t.methods[i]
379}
380
381// expandMethod substitutes type arguments in the i'th method for an
382// instantiated receiver.
383func (t *Named) expandMethod(i int) *Func {
384	// t.orig.methods is not lazy. origm is the method instantiated with its
385	// receiver type parameters (the "origin" method).
386	origm := t.inst.orig.Method(i)
387	assert(origm != nil)
388
389	check := t.check
390	// Ensure that the original method is type-checked.
391	if check != nil {
392		check.objDecl(origm, nil)
393	}
394
395	origSig := origm.typ.(*Signature)
396	rbase, _ := deref(origSig.Recv().Type())
397
398	// If rbase is t, then origm is already the instantiated method we're looking
399	// for. In this case, we return origm to preserve the invariant that
400	// traversing Method->Receiver Type->Method should get back to the same
401	// method.
402	//
403	// This occurs if t is instantiated with the receiver type parameters, as in
404	// the use of m in func (r T[_]) m() { r.m() }.
405	if rbase == t {
406		return origm
407	}
408
409	sig := origSig
410	// We can only substitute if we have a correspondence between type arguments
411	// and type parameters. This check is necessary in the presence of invalid
412	// code.
413	if origSig.RecvTypeParams().Len() == t.inst.targs.Len() {
414		smap := makeSubstMap(origSig.RecvTypeParams().list(), t.inst.targs.list())
415		var ctxt *Context
416		if check != nil {
417			ctxt = check.context()
418		}
419		sig = check.subst(origm.pos, origSig, smap, t, ctxt).(*Signature)
420	}
421
422	if sig == origSig {
423		// No substitution occurred, but we still need to create a new signature to
424		// hold the instantiated receiver.
425		copy := *origSig
426		sig = &copy
427	}
428
429	var rtyp Type
430	if origm.hasPtrRecv() {
431		rtyp = NewPointer(t)
432	} else {
433		rtyp = t
434	}
435
436	sig.recv = substVar(origSig.recv, rtyp)
437	return substFunc(origm, sig)
438}
439
440// SetUnderlying sets the underlying type and marks t as complete.
441// t must not have type arguments.
442func (t *Named) SetUnderlying(underlying Type) {
443	assert(t.inst == nil)
444	if underlying == nil {
445		panic("underlying type must not be nil")
446	}
447	if asNamed(underlying) != nil {
448		panic("underlying type must not be *Named")
449	}
450	t.resolve().underlying = underlying
451	if t.fromRHS == nil {
452		t.fromRHS = underlying // for cycle detection
453	}
454}
455
456// AddMethod adds method m unless it is already in the method list.
457// The method must be in the same package as t, and t must not have
458// type arguments.
459func (t *Named) AddMethod(m *Func) {
460	assert(samePkg(t.obj.pkg, m.pkg))
461	assert(t.inst == nil)
462	t.resolve()
463	if t.methodIndex(m.name, false) < 0 {
464		t.methods = append(t.methods, m)
465	}
466}
467
468// methodIndex returns the index of the method with the given name.
469// If foldCase is set, capitalization in the name is ignored.
470// The result is negative if no such method exists.
471func (t *Named) methodIndex(name string, foldCase bool) int {
472	if name == "_" {
473		return -1
474	}
475	if foldCase {
476		for i, m := range t.methods {
477			if strings.EqualFold(m.name, name) {
478				return i
479			}
480		}
481	} else {
482		for i, m := range t.methods {
483			if m.name == name {
484				return i
485			}
486		}
487	}
488	return -1
489}
490
491// Underlying returns the [underlying type] of the named type t, resolving all
492// forwarding declarations. Underlying types are never Named, TypeParam, or
493// Alias types.
494//
495// [underlying type]: https://go.dev/ref/spec#Underlying_types.
496func (t *Named) Underlying() Type {
497	// TODO(gri) Investigate if Unalias can be moved to where underlying is set.
498	return Unalias(t.resolve().underlying)
499}
500
501func (t *Named) String() string { return TypeString(t, nil) }
502
503// ----------------------------------------------------------------------------
504// Implementation
505//
506// TODO(rfindley): reorganize the loading and expansion methods under this
507// heading.
508
509// under returns the expanded underlying type of n0; possibly by following
510// forward chains of named types. If an underlying type is found, resolve
511// the chain by setting the underlying type for each defined type in the
512// chain before returning it. If no underlying type is found or a cycle
513// is detected, the result is Typ[Invalid]. If a cycle is detected and
514// n0.check != nil, the cycle is reported.
515//
516// This is necessary because the underlying type of named may be itself a
517// named type that is incomplete:
518//
519//	type (
520//		A B
521//		B *C
522//		C A
523//	)
524//
525// The type of C is the (named) type of A which is incomplete,
526// and which has as its underlying type the named type B.
527func (n0 *Named) under() Type {
528	u := n0.Underlying()
529
530	// If the underlying type of a defined type is not a defined
531	// (incl. instance) type, then that is the desired underlying
532	// type.
533	var n1 *Named
534	switch u1 := u.(type) {
535	case nil:
536		// After expansion via Underlying(), we should never encounter a nil
537		// underlying.
538		panic("nil underlying")
539	default:
540		// common case
541		return u
542	case *Named:
543		// handled below
544		n1 = u1
545	}
546
547	if n0.check == nil {
548		panic("Named.check == nil but type is incomplete")
549	}
550
551	// Invariant: after this point n0 as well as any named types in its
552	// underlying chain should be set up when this function exits.
553	check := n0.check
554	n := n0
555
556	seen := make(map[*Named]int) // types that need their underlying type resolved
557	var path []Object            // objects encountered, for cycle reporting
558
559loop:
560	for {
561		seen[n] = len(seen)
562		path = append(path, n.obj)
563		n = n1
564		if i, ok := seen[n]; ok {
565			// cycle
566			check.cycleError(path[i:], firstInSrc(path[i:]))
567			u = Typ[Invalid]
568			break
569		}
570		u = n.Underlying()
571		switch u1 := u.(type) {
572		case nil:
573			u = Typ[Invalid]
574			break loop
575		default:
576			break loop
577		case *Named:
578			// Continue collecting *Named types in the chain.
579			n1 = u1
580		}
581	}
582
583	for n := range seen {
584		// We should never have to update the underlying type of an imported type;
585		// those underlying types should have been resolved during the import.
586		// Also, doing so would lead to a race condition (was go.dev/issue/31749).
587		// Do this check always, not just in debug mode (it's cheap).
588		if n.obj.pkg != check.pkg {
589			panic("imported type with unresolved underlying type")
590		}
591		n.underlying = u
592	}
593
594	return u
595}
596
597func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
598	n.resolve()
599	if samePkg(n.obj.pkg, pkg) || isExported(name) || foldCase {
600		// If n is an instance, we may not have yet instantiated all of its methods.
601		// Look up the method index in orig, and only instantiate method at the
602		// matching index (if any).
603		if i := n.Origin().methodIndex(name, foldCase); i >= 0 {
604			// For instances, m.Method(i) will be different from the orig method.
605			return i, n.Method(i)
606		}
607	}
608	return -1, nil
609}
610
611// context returns the type-checker context.
612func (check *Checker) context() *Context {
613	if check.ctxt == nil {
614		check.ctxt = NewContext()
615	}
616	return check.ctxt
617}
618
619// expandUnderlying substitutes type arguments in the underlying type n.orig,
620// returning the result. Returns Typ[Invalid] if there was an error.
621func (n *Named) expandUnderlying() Type {
622	check := n.check
623	if check != nil && check.conf._Trace {
624		check.trace(n.obj.pos, "-- Named.expandUnderlying %s", n)
625		check.indent++
626		defer func() {
627			check.indent--
628			check.trace(n.obj.pos, "=> %s (tparams = %s, under = %s)", n, n.tparams.list(), n.underlying)
629		}()
630	}
631
632	assert(n.inst.orig.underlying != nil)
633	if n.inst.ctxt == nil {
634		n.inst.ctxt = NewContext()
635	}
636
637	orig := n.inst.orig
638	targs := n.inst.targs
639
640	if asNamed(orig.underlying) != nil {
641		// We should only get a Named underlying type here during type checking
642		// (for example, in recursive type declarations).
643		assert(check != nil)
644	}
645
646	if orig.tparams.Len() != targs.Len() {
647		// Mismatching arg and tparam length may be checked elsewhere.
648		return Typ[Invalid]
649	}
650
651	// Ensure that an instance is recorded before substituting, so that we
652	// resolve n for any recursive references.
653	h := n.inst.ctxt.instanceHash(orig, targs.list())
654	n2 := n.inst.ctxt.update(h, orig, n.TypeArgs().list(), n)
655	assert(n == n2)
656
657	smap := makeSubstMap(orig.tparams.list(), targs.list())
658	var ctxt *Context
659	if check != nil {
660		ctxt = check.context()
661	}
662	underlying := n.check.subst(n.obj.pos, orig.underlying, smap, n, ctxt)
663	// If the underlying type of n is an interface, we need to set the receiver of
664	// its methods accurately -- we set the receiver of interface methods on
665	// the RHS of a type declaration to the defined type.
666	if iface, _ := underlying.(*Interface); iface != nil {
667		if methods, copied := replaceRecvType(iface.methods, orig, n); copied {
668			// If the underlying type doesn't actually use type parameters, it's
669			// possible that it wasn't substituted. In this case we need to create
670			// a new *Interface before modifying receivers.
671			if iface == orig.underlying {
672				old := iface
673				iface = check.newInterface()
674				iface.embeddeds = old.embeddeds
675				assert(old.complete) // otherwise we are copying incomplete data
676				iface.complete = old.complete
677				iface.implicit = old.implicit // should be false but be conservative
678				underlying = iface
679			}
680			iface.methods = methods
681			iface.tset = nil // recompute type set with new methods
682
683			// If check != nil, check.newInterface will have saved the interface for later completion.
684			if check == nil { // golang/go#61561: all newly created interfaces must be fully evaluated
685				iface.typeSet()
686			}
687		}
688	}
689
690	return underlying
691}
692
693// safeUnderlying returns the underlying type of typ without expanding
694// instances, to avoid infinite recursion.
695//
696// TODO(rfindley): eliminate this function or give it a better name.
697func safeUnderlying(typ Type) Type {
698	if t := asNamed(typ); t != nil {
699		return t.underlying
700	}
701	return typ.Underlying()
702}
703