// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
// Source: ../../cmd/compile/internal/types2/named.go

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	
	
	
	
)

// Type-checking Named types is subtle, because they may be recursively
// defined, and because their full details may be spread across multiple
// declarations (via methods). For this reason they are type-checked lazily,
// to avoid information being accessed before it is complete.
//
// Conceptually, it is helpful to think of named types as having two distinct
// sets of information:
//  - "LHS" information, defining their identity: Obj() and TypeArgs()
//  - "RHS" information, defining their details: TypeParams(), Underlying(),
//    and methods.
//
// In this taxonomy, LHS information is available immediately, but RHS
// information is lazy. Specifically, a named type N may be constructed in any
// of the following ways:
//  1. type-checked from the source
//  2. loaded eagerly from export data
//  3. loaded lazily from export data (when using unified IR)
//  4. instantiated from a generic type
//
// In cases 1, 3, and 4, it is possible that the underlying type or methods of
// N may not be immediately available.
//  - During type-checking, we allocate N before type-checking its underlying
//    type or methods, so that we can create recursive references.
//  - When loading from export data, we may load its methods and underlying
//    type lazily using a provided load function.
//  - After instantiating, we lazily expand the underlying type and methods
//    (note that instances may be created while still in the process of
//    type-checking the original type declaration).
//
// In cases 3 and 4 this lazy construction may also occur concurrently, due to
// concurrent use of the type checker API (after type checking or importing has
// finished). It is critical that we keep track of state, so that Named types
// are constructed exactly once and so that we do not access their details too
// soon.
//
// We achieve this by tracking state with an atomic state variable, and
// guarding potentially concurrent calculations with a mutex. See [stateMask]
// for details.
//
// GLOSSARY: Here are a few terms used in this file to describe Named types:
//  - We say that a Named type is "instantiated" if it has been constructed by
//    instantiating a generic named type with type arguments.
//  - We say that a Named type is "declared" if it corresponds to a type
//    declaration in the source. Instantiated named types correspond to a type
//    instantiation in the source, not a declaration. But their Origin type is
//    a declared type.
//  - We say that a Named type is "unpacked" if its RHS information has been
//    populated, normalizing its representation for use in type-checking
//    operations and abstracting away how it was created:
//      - For a Named type constructed from unified IR, this involves invoking
//        a lazy loader function to extract details from UIR as needed.
//      - For an instantiated Named type, this involves extracting information
//        from its origin and substituting type arguments into a "synthetic"
//        RHS; this process is called "expanding" the RHS (see below).
//  - We say that a Named type is "expanded" if it is an instantiated type and
//    type parameters in its RHS and methods have been substituted with the type
//    arguments from the instantiation. A type may be partially expanded if some
//    but not all of these details have been substituted. Similarly, we refer to
//    these individual details (RHS or method) as being "expanded".
//
// Some invariants to keep in mind: each declared Named type has a single
// corresponding object, and that object's type is the (possibly generic) Named
// type. Declared Named types are identical if and only if their pointers are
// identical. On the other hand, multiple instantiated Named types may be
// identical even though their pointers are not identical. One has to use
// Identical to compare them. For instantiated named types, their obj is a
// synthetic placeholder that records their position of the corresponding
// instantiation in the source (if they were constructed during type checking).
//
// To prevent infinite expansion of named instances that are created outside of
// type-checking, instances share a Context with other instances created during
// their expansion. Via the pidgeonhole principle, this guarantees that in the
// presence of a cycle of named types, expansion will eventually find an
// existing instance in the Context and short-circuit the expansion.
//
// Once an instance is fully expanded, we can nil out this shared Context to unpin
// memory, though the Context may still be held by other incomplete instances
// in its "lineage".

// A Named represents a named (defined) type.
//
// A declaration such as:
//
//	type S struct { ... }
//
// creates a defined type whose underlying type is a struct,
// and binds this type to the object S, a [TypeName].
// Use [Named.Underlying] to access the underlying type.
// Use [Named.Obj] to obtain the object S.
//
// Before type aliases (Go 1.9), the spec called defined types "named types".
type Named struct {
	check *Checker  // non-nil during type-checking; nil otherwise
	obj   *TypeName // corresponding declared object for declared types; see above for instantiated types

	// flags indicating temporary violations of the invariants for fromRHS and underlying
	allowNilRHS        bool // same as below, as well as briefly during checking of a type declaration
	allowNilUnderlying bool // may be true from creation via [NewNamed] until [Named.SetUnderlying]

	inst *instance // information for instantiated types; nil otherwise

	mu         sync.Mutex     // guards all fields below
	state_     uint32         // the current state of this type; must only be accessed atomically or when mu is held
	fromRHS    Type           // the declaration RHS this type is derived from
	tparams    *TypeParamList // type parameters, or nil
	underlying Type           // underlying type, or nil
	finite     bool           // whether the type has finite size

	// methods declared for this type (not the method set of this type)
	// Signatures are type-checked lazily.
	// For non-instantiated types, this is a fully populated list of methods. For
	// instantiated types, methods are individually expanded when they are first
	// accessed.
	methods []*Func

	// loader may be provided to lazily load type parameters, underlying type, methods, and delayed functions
	loader func(*Named) ([]*TypeParam, Type, []*Func, []func())
}

// instance holds information that is only necessary for instantiated named
// types.
type instance struct {
	orig            *Named    // original, uninstantiated type
	targs           *TypeList // type arguments
	expandedMethods int       // number of expanded methods; expandedMethods <= len(orig.methods)
	ctxt            *Context  // local Context; set to nil after full expansion
}

// stateMask represents each state in the lifecycle of a named type.
//
// Each named type begins in the initial state. A named type may transition to a new state
// according to the below diagram:
//
//	initial
//	lazyLoaded
//	unpacked
//	└── hasMethods
//	└── hasUnder
//	└── hasFinite
//
// That is, descent down the tree is mostly linear (initial through unpacked), except upon
// reaching the leaves (hasMethods, hasUnder, and hasFinite). A type may occupy any
// combination of the leaf states at once (they are independent states).
//
// To represent this independence, the set of active states is represented with a bit set. State
// transitions are monotonic. Once a state bit is set, it remains set.
//
// The above constraints significantly narrow the possible bit sets for a named type. With bits
// set left-to-right, they are:
//
//	00000 | initial
//	10000 | lazyLoaded
//	11000 | unpacked, which implies lazyLoaded
//	11100 | hasMethods, which implies unpacked (which in turn implies lazyLoaded)
//	11010 | hasUnder, which implies unpacked ...
//	11001 | hasFinite, which implies unpacked ...
//	11110 | both hasMethods and hasUnder which implies unpacked ...
//	...   | (other combinations of leaf states)
//
// To read the state of a named type, use [Named.stateHas]; to write, use [Named.setState].
type stateMask uint32

const (
	// initially, type parameters, RHS, underlying, and methods might be unavailable
	lazyLoaded stateMask = 1 << iota // methods are available, but constraints might be unexpanded (for generic types)
	unpacked                         // methods might be unexpanded (for instances)
	hasMethods                       // methods are all expanded (for instances)
	hasUnder                         // underlying type is available
	hasFinite                        // size finiteness is available
)

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
// The underlying type must not be a *Named.
func ( *TypeName,  Type,  []*Func) *Named {
	if asNamed() != nil {
		panic("underlying type must not be *Named")
	}
	 := (*Checker)(nil).newNamed(, , )
	if  == nil {
		.allowNilRHS = true
		.allowNilUnderlying = true
	} else {
		.SetUnderlying()
	}
	return 

}

// unpack populates the type parameters, methods, and RHS of n.
//
// For the purposes of unpacking, there are three categories of named types:
//  1. Lazy loaded types
//  2. Instantiated types
//  3. All others
//
// Note that the above form a partition.
//
// Lazy loaded types:
// Type parameters, methods, and RHS of n become accessible and are fully
// expanded.
//
// Instantiated types:
// Type parameters, methods, and RHS of n become accessible, though methods
// are lazily populated as needed.
//
// All others:
// Effectively, nothing happens.
func ( *Named) () *Named {
	if .stateHas(lazyLoaded | unpacked) { // avoid locking below
		return 
	}

	// TODO(rfindley): if n.check is non-nil we can avoid locking here, since
	// type-checking is not concurrent. Evaluate if this is worth doing.
	.mu.Lock()
	defer .mu.Unlock()

	// only atomic for consistency; we are holding the mutex
	if .stateHas(lazyLoaded | unpacked) {
		return 
	}

	// underlying comes after unpacking, do not set it
	defer (func() { assert(!.stateHas(hasUnder)) })()

	if .inst != nil {
		assert(.fromRHS == nil) // instantiated types are not declared types
		assert(.loader == nil)  // cannot import an instantiation

		 := .inst.orig
		.()

		.fromRHS = .expandRHS()
		.tparams = .tparams

		if len(.methods) == 0 {
			.setState(lazyLoaded | unpacked | hasMethods) // nothing further to do
			.inst.ctxt = nil
		} else {
			.setState(lazyLoaded | unpacked)
		}
		return 
	}

	// TODO(mdempsky): Since we're passing n to the loader anyway
	// (necessary because types2 expects the receiver type for methods
	// on defined interface types to be the Named rather than the
	// underlying Interface), maybe it should just handle calling
	// SetTypeParams, SetUnderlying, and AddMethod instead?  Those
	// methods would need to support reentrant calls though. It would
	// also make the API more future-proof towards further extensions.
	if .loader != nil {
		assert(.fromRHS == nil) // not loaded yet
		assert(.inst == nil)    // cannot import an instantiation

		, , ,  := .loader()
		.loader = nil

		.tparams = bindTParams()
		.fromRHS =  // for cycle detection
		.methods = 

		.setState(lazyLoaded) // avoid deadlock calling delayed functions
		for ,  := range  {
			()
		}
	}

	.setState(lazyLoaded | unpacked | hasMethods)
	return 
}

// stateHas atomically determines whether the current state includes any active bit in sm.
func ( *Named) ( stateMask) bool {
	return stateMask(atomic.LoadUint32(&.state_))& != 0
}

// setState atomically sets the current state to include each active bit in sm.
// Must only be called while holding n.mu.
func ( *Named) ( stateMask) {
	atomic.OrUint32(&.state_, uint32())
	// verify state transitions
	if debug {
		 := stateMask(atomic.LoadUint32(&.state_))
		 := &unpacked != 0
		// unpacked => lazyLoaded
		if  {
			assert(&lazyLoaded != 0)
		}
		// hasMethods => unpacked
		if &hasMethods != 0 {
			assert()
		}
		// hasUnder => unpacked
		if &hasUnder != 0 {
			assert()
		}
		// hasFinite => unpacked
		if &hasFinite != 0 {
			assert()
		}
	}
}

// newNamed is like NewNamed but with a *Checker receiver.
func ( *Checker) ( *TypeName,  Type,  []*Func) *Named {
	 := &Named{check: , obj: , fromRHS: , methods: }
	if .typ == nil {
		.typ = 
	}
	// Ensure that typ is always sanity-checked.
	if  != nil {
		.needsCleanup()
	}
	return 
}

// newNamedInstance creates a new named instance for the given origin and type
// arguments, recording pos as the position of its synthetic object (for error
// reporting).
//
// If set, expanding is the named type instance currently being expanded, that
// led to the creation of this instance.
func ( *Checker) ( token.Pos,  *Named,  []Type,  *Named) *Named {
	assert(len() > 0)

	 := NewTypeName(, .obj.pkg, .obj.name, nil)
	 := &instance{orig: , targs: newTypeList()}

	// Only pass the expanding context to the new instance if their packages
	// match. Since type reference cycles are only possible within a single
	// package, this is sufficient for the purposes of short-circuiting cycles.
	// Avoiding passing the context in other cases prevents unnecessary coupling
	// of types across packages.
	if  != nil && .Obj().pkg == .pkg {
		.ctxt = .inst.ctxt
	}
	 := &Named{check: , obj: , inst: }
	.typ = 
	// Ensure that typ is always sanity-checked.
	if  != nil {
		.needsCleanup()
	}
	return 
}

func ( *Named) () {
	// Instances can have a nil underlying at the end of type checking — they
	// will lazily expand it as needed. All other types must have one.
	if .inst == nil {
		.Underlying()
	}
	.check = nil
}

// Obj returns the type name for the declaration defining the named type t. For
// instantiated types, this is same as the type name of the origin type.
func ( *Named) () *TypeName {
	if .inst == nil {
		return .obj
	}
	return .inst.orig.obj
}

// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func ( *Named) () *Named {
	if .inst == nil {
		return 
	}
	return .inst.orig
}

// TypeParams returns the type parameters of the named type t, or nil.
// The result is non-nil for an (originally) generic type even if it is instantiated.
func ( *Named) () *TypeParamList { return .unpack().tparams }

// SetTypeParams sets the type parameters of the named type t.
// t must not have type arguments.
func ( *Named) ( []*TypeParam) {
	assert(.inst == nil)
	.unpack().tparams = bindTParams()
}

// TypeArgs returns the type arguments used to instantiate the named type t.
func ( *Named) () *TypeList {
	if .inst == nil {
		return nil
	}
	return .inst.targs
}

// NumMethods returns the number of explicit methods defined for t.
func ( *Named) () int {
	return len(.Origin().unpack().methods)
}

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
//
// For an ordinary or instantiated type t, the receiver base type of this
// method is the named type t. For an uninstantiated generic type t, each
// method receiver is instantiated with its receiver type parameters.
//
// Methods are numbered deterministically: given the same list of source files
// presented to the type checker, or the same sequence of NewMethod and AddMethod
// calls, the mapping from method index to corresponding method remains the same.
// But the specific ordering is not specified and must not be relied on as it may
// change in the future.
func ( *Named) ( int) *Func {
	.unpack()

	if .stateHas(hasMethods) {
		return .methods[]
	}

	assert(.inst != nil) // only instances should have unexpanded methods
	 := .inst.orig

	.mu.Lock()
	defer .mu.Unlock()

	if len(.methods) != len(.methods) {
		assert(len(.methods) == 0)
		.methods = make([]*Func, len(.methods))
	}

	if .methods[] == nil {
		assert(.inst.ctxt != nil) // we should still have a context remaining from the resolution phase
		.methods[] = .expandMethod()
		.inst.expandedMethods++

		// Check if we've created all methods at this point. If we have, mark the
		// type as having all of its methods.
		if .inst.expandedMethods == len(.methods) {
			.setState(hasMethods)
			.inst.ctxt = nil // no need for a context anymore
		}
	}

	return .methods[]
}

// expandMethod substitutes type arguments in the i'th method for an
// instantiated receiver.
func ( *Named) ( int) *Func {
	// t.orig.methods is not lazy. origm is the method instantiated with its
	// receiver type parameters (the "origin" method).
	 := .inst.orig.Method()
	assert( != nil)

	 := .check
	// Ensure that the original method is type-checked.
	if  != nil {
		.objDecl()
	}

	 := .typ.(*Signature)
	,  := deref(.Recv().Type())

	// If rbase is t, then origm is already the instantiated method we're looking
	// for. In this case, we return origm to preserve the invariant that
	// traversing Method->Receiver Type->Method should get back to the same
	// method.
	//
	// This occurs if t is instantiated with the receiver type parameters, as in
	// the use of m in func (r T[_]) m() { r.m() }.
	if  ==  {
		return 
	}

	 := 
	// We can only substitute if we have a correspondence between type arguments
	// and type parameters. This check is necessary in the presence of invalid
	// code.
	if .RecvTypeParams().Len() == .inst.targs.Len() {
		 := makeSubstMap(.RecvTypeParams().list(), .inst.targs.list())
		var  *Context
		if  != nil {
			 = .context()
		}
		 = .subst(.pos, , , , ).(*Signature)
	}

	if  ==  {
		// No substitution occurred, but we still need to create a new signature to
		// hold the instantiated receiver.
		 := *
		 = &
	}

	var  Type
	if .hasPtrRecv() {
		 = NewPointer()
	} else {
		 = 
	}

	.recv = cloneVar(.recv, )
	return cloneFunc(, )
}

// SetUnderlying sets the underlying type and marks t as complete.
// t must not have type arguments.
func ( *Named) ( Type) {
	assert(.inst == nil)
	if  == nil {
		panic("underlying type must not be nil")
	}
	if asNamed() != nil {
		panic("underlying type must not be *Named")
	}
	// be careful to uphold the state invariants
	.mu.Lock()
	defer .mu.Unlock()

	.fromRHS = 
	.allowNilRHS = false
	.setState(lazyLoaded | unpacked | hasMethods) // TODO(markfreeman): Why hasMethods?

	.underlying = 
	.allowNilUnderlying = false
	.setState(hasUnder)
}

// AddMethod adds method m unless it is already in the method list.
// The method must be in the same package as t, and t must not have
// type arguments.
func ( *Named) ( *Func) {
	assert(samePkg(.obj.pkg, .pkg))
	assert(.inst == nil)
	.unpack()
	if .methodIndex(.name, false) < 0 {
		.methods = append(.methods, )
	}
}

// methodIndex returns the index of the method with the given name.
// If foldCase is set, capitalization in the name is ignored.
// The result is negative if no such method exists.
func ( *Named) ( string,  bool) int {
	if  == "_" {
		return -1
	}
	if  {
		for ,  := range .methods {
			if strings.EqualFold(.name, ) {
				return 
			}
		}
	} else {
		for ,  := range .methods {
			if .name ==  {
				return 
			}
		}
	}
	return -1
}

// rhs returns [Named.fromRHS].
//
// In debug mode, it also asserts that n is in an appropriate state.
func ( *Named) () Type {
	if debug {
		assert(.stateHas(lazyLoaded | unpacked))
	}
	return .fromRHS
}

// Underlying returns the [underlying type] of the named type t, resolving all
// forwarding declarations. Underlying types are never Named, TypeParam, or
// Alias types.
//
// [underlying type]: https://go.dev/ref/spec#Underlying_types.
func ( *Named) () Type {
	.unpack()

	// The gccimporter depends on writing a nil underlying via NewNamed and
	// immediately reading it back. Rather than putting that in Named.under
	// and complicating things there, we just check for that special case here.
	if .rhs() == nil {
		assert(.allowNilRHS)
		if .allowNilUnderlying {
			return nil
		}
	}

	if !.stateHas(hasUnder) { // minor performance optimization
		.resolveUnderlying()
	}

	return .underlying
}

func ( *Named) () string { return TypeString(, nil) }

// ----------------------------------------------------------------------------
// Implementation
//
// TODO(rfindley): reorganize the loading and expansion methods under this
// heading.

// resolveUnderlying computes the underlying type of n. If n already has an
// underlying type, nothing happens.
//
// It does so by following RHS type chains for alias and named types. If any
// other type T is found, each named type in the chain has its underlying
// type set to T. Aliases are skipped because their underlying type is
// not memoized.
//
// resolveUnderlying assumes that there are no direct cycles; if there were
// any, they were broken (by setting the respective types to invalid) during
// the directCycles check phase.
func ( *Named) () {
	assert(.stateHas(unpacked))

	var  map[*Named]bool // for debugging only
	if debug {
		 = make(map[*Named]bool)
	}

	var  []*Named
	var  Type
	for  := Type();  == nil; {
		switch t := .(type) {
		case nil:
			 = Typ[Invalid]

		case *Alias:
			 = unalias()

		case *Named:
			if debug {
				assert(![])
				[] = true
			}

			// don't recalculate the underlying
			if .stateHas(hasUnder) {
				 = .underlying
				break
			}

			if debug {
				[] = true
			}
			 = append(, )

			.unpack()
			assert(.rhs() != nil || .allowNilRHS)
			 = .rhs()

		default:
			 =  // any type literal or predeclared type works
		}
	}

	for ,  := range  {
		func() {
			.mu.Lock()
			defer .mu.Unlock()
			// Careful, t.underlying has lock-free readers. Since we might be racing
			// another call to resolveUnderlying, we have to avoid overwriting
			// t.underlying. Otherwise, the race detector will be tripped.
			if !.stateHas(hasUnder) {
				.underlying = 
				.setState(hasUnder)
			}
		}()
	}
}

func ( *Named) ( *Package,  string,  bool) (int, *Func) {
	.unpack()
	if samePkg(.obj.pkg, ) || isExported() ||  {
		// If n is an instance, we may not have yet instantiated all of its methods.
		// Look up the method index in orig, and only instantiate method at the
		// matching index (if any).
		if  := .Origin().methodIndex(, );  >= 0 {
			// For instances, m.Method(i) will be different from the orig method.
			return , .Method()
		}
	}
	return -1, nil
}

// context returns the type-checker context.
func ( *Checker) () *Context {
	if .ctxt == nil {
		.ctxt = NewContext()
	}
	return .ctxt
}

// expandRHS crafts a synthetic RHS for an instantiated type using the RHS of
// its origin type (which must be a generic type).
//
// Suppose that we had:
//
//	type T[P any] struct {
//	  f P
//	}
//
//	type U T[int]
//
// When we go to U, we observe T[int]. Since T[int] is an instantiation, it has no
// declaration. Here, we craft a synthetic RHS for T[int] as if it were declared,
// somewhat similar to:
//
//	type T[int] struct {
//	  f int
//	}
//
// And note that the synthetic RHS here is the same as the underlying for U. Now,
// consider:
//
//	type T[_ any] U
//	type U int
//	type V T[U]
//
// The synthetic RHS for T[U] becomes:
//
//	type T[U] U
//
// Whereas the underlying of V is int, not U.
func ( *Named) () ( Type) {
	 := .check
	if  != nil && .conf._Trace {
		.trace(.obj.pos, "-- Named.expandRHS %s", )
		.indent++
		defer func() {
			.indent--
			.trace(.obj.pos, "=> %s (rhs = %s)", , )
		}()
	}

	assert(!.stateHas(unpacked))
	assert(.inst.orig.stateHas(lazyLoaded | unpacked))

	if .inst.ctxt == nil {
		.inst.ctxt = NewContext()
	}

	 := .inst.ctxt
	 := .inst.orig

	 := .inst.targs
	 := .tparams

	if .Len() != .Len() {
		return Typ[Invalid]
	}

	 := .instanceHash(, .list())
	 := .update(, , .list(), ) // block fixed point infinite instantiation
	assert( == )

	 := makeSubstMap(.list(), .list())
	if  != nil {
		 = .context()
	}

	 = .subst(.obj.pos, .rhs(), , , )

	// TODO(markfreeman): Can we handle this in substitution?
	// If the RHS is an interface, we must set the receiver of interface methods
	// to the named type.
	if ,  := .(*Interface);  != nil {
		if ,  := replaceRecvType(.methods, , );  {
			// If the RHS doesn't use type parameters, it may not have been
			// substituted; we need to craft a new interface first.
			if  == .rhs() {
				assert(.complete) // otherwise we are copying incomplete data

				 := .newInterface()
				.complete = true
				.implicit = false
				.embeddeds = .embeddeds

				 = 
			}
			.methods = 
			.tset = nil // recompute type set with new methods

			// go.dev/issue/61561: We have to complete the interface even without a checker.
			if  == nil {
				.typeSet()
			}

			return 
		}
	}

	return 
}

// safeUnderlying returns the underlying type of typ without expanding
// instances, to avoid infinite recursion.
//
// TODO(rfindley): eliminate this function or give it a better name.
func safeUnderlying( Type) Type {
	if  := asNamed();  != nil {
		return .underlying
	}
	return .Underlying()
}