// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.// Source: ../../cmd/compile/internal/types2/instantiate.go// Copyright 2021 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.// This file implements instantiation of generic types// through substitution of type parameters by type arguments.package typesimport (.)// A genericType implements access to its type parameters.type genericType interface {Type TypeParams() *TypeParamList}// Instantiate instantiates the type orig with the given type arguments targs.// orig must be an *Alias, *Named, or *Signature type. If there is no error,// the resulting Type is an instantiated type of the same kind (*Alias, *Named// or *Signature, respectively).//// Methods attached to a *Named type are also instantiated, and associated with// a new *Func that has the same position as the original method, but nil function// scope.//// If ctxt is non-nil, it may be used to de-duplicate the instance against// previous instances with the same identity. As a special case, generic// *Signature origin types are only considered identical if they are pointer// equivalent, so that instantiating distinct (but possibly identical)// signatures will yield different instances. The use of a shared context does// not guarantee that identical instances are deduplicated in all cases.//// If validate is set, Instantiate verifies that the number of type arguments// and parameters match, and that the type arguments satisfy their respective// type constraints. If verification fails, the resulting error may wrap an// *ArgumentError indicating which type argument did not satisfy its type parameter// constraint, and why.//// If validate is not set, Instantiate does not verify the type argument count// or whether the type arguments satisfy their constraints. Instantiate is// guaranteed to not return an error, but may panic. Specifically, for// *Signature types, Instantiate will panic immediately if the type argument// count is incorrect; for *Named types, a panic may occur later inside the// *Named API.func ( *Context, Type, []Type, bool) (Type, error) {assert(len() > 0)if == nil { = NewContext() } := .(genericType) // signature of Instantiate must not change for backward-compatibilityif { := .TypeParams().list()assert(len() > 0)iflen() != len() {returnnil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(), , len()) }if , := (*Checker)(nil).verify(nopos, , , ); != nil {returnnil, &ArgumentError{, } } } := (*Checker)(nil).instance(nopos, , , nil, )return , nil}// instance instantiates the given original (generic) function or type with the// provided type arguments and returns the resulting instance. If an identical// instance exists already in the given contexts, it returns that instance,// otherwise it creates a new one.//// If expanding is non-nil, it is the Named instance type currently being// expanded. If ctxt is non-nil, it is the context associated with the current// type-checking pass or call to Instantiate. At least one of expanding or ctxt// must be non-nil.//// For Named types the resulting instance may be unexpanded.func ( *Checker) ( token.Pos, genericType, []Type, *Named, *Context) ( Type) {// The order of the contexts below matters: we always prefer instances in the // expanding instance context in order to preserve reference cycles. // // Invariant: if expanding != nil, the returned instance will be the instance // recorded in expanding.inst.ctxt.var []*Contextif != nil { = append(, .inst.ctxt) }if != nil { = append(, ) }assert(len() > 0)// Compute all hashes; hashes may differ across contexts due to different // unique IDs for Named types within the hasher. := make([]string, len())for , := range { [] = .instanceHash(, ) }// Record the result in all contexts. // Prefer to re-use existing types from expanding context, if it exists, to reduce // the memory pinned by the Named type. := func( Type) Type {for := len() - 1; >= 0; -- { = [].update([], , , ) }return }// typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance.for , := range {if := .lookup([], , ); != nil {return () } }switch orig := .(type) {case *Named: = .newNamedInstance(, , , ) // substituted lazilycase *Alias:// TODO(gri) is this correct?assert( == nil) // Alias instances cannot be reached from Named types := .TypeParams()// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)if !.validateTArgLen(, .String(), .Len(), len()) {returnTyp[Invalid] }if .Len() == 0 {return// nothing to do (minor optimization) }return .newAliasInstance(, , , )case *Signature:assert( == nil) // function instances cannot be reached from Named types := .TypeParams()// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)if !.validateTArgLen(, .String(), .Len(), len()) {returnTyp[Invalid] }if .Len() == 0 {return// nothing to do (minor optimization) } := .subst(, , makeSubstMap(.list(), ), nil, ).(*Signature)// If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects).if == { := * = & }// After instantiating a generic signature, it is not generic // anymore; we need to set tparams to nil. .tparams = nil = default:// only types and functions can be genericpanic(fmt.Sprintf("%v: cannot instantiate %v", , )) }// Update all contexts; it's possible that we've lost a race.return ()}// validateTArgLen checks that the number of type arguments (got) matches the// number of type parameters (want); if they don't match an error is reported.// If validation fails and check is nil, validateTArgLen panics.func ( *Checker) ( token.Pos, string, , int) bool {varstringswitch {case < : = "not enough"case > : = "too many"default:returntrue } := .sprintf("%s type arguments for type %s: have %d, want %d", , , , )if != nil { .error(atPos(), WrongTypeArgCount, )returnfalse }panic(fmt.Sprintf("%v: %s", , ))}func ( *Checker) ( token.Pos, []*TypeParam, []Type, *Context) (int, error) { := makeSubstMap(, )for , := range {// Ensure that we have a (possibly implicit) interface as type bound (go.dev/issue/51048). .iface()// The type parameter bound is parameterized with the same type parameters // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiated // the parameterized type. := .subst(, .bound, , nil, )varstringif !.implements(, [], , true, &) {return , errors.New() } }return -1, nil}// implements checks if V implements T. The receiver may be nil if implements// is called through an exported API call such as AssignableTo. If constraint// is set, T is a type constraint.//// If the provided cause is non-nil, it may be set to an error string// explaining why V does not implement (or satisfy, for constraints) T.func ( *Checker) ( token.Pos, , Type, bool, *string) bool { := under() := under()if !isValid() || !isValid() {returntrue// avoid follow-on errors }if , := .(*Pointer); != nil && !isValid(under(.base)) {returntrue// avoid follow-on errors (see go.dev/issue/49541 for an example) } := "implement"if { = "satisfy" } , := .(*Interface)if == nil {if != nil {varstringifisInterfacePtr() { = .sprintf("type %s is pointer to interface, not interface", ) } else { = .sprintf("%s is not an interface", ) } * = .sprintf("%s does not %s %s (%s)", , , , ) }returnfalse }// Every type satisfies the empty interface.if .Empty() {returntrue }// T is not the empty interface (i.e., the type set of T is restricted)// An interface V with an empty type set satisfies any interface. // (The empty set is a subset of any set.) , := .(*Interface)if != nil && .typeSet().IsEmpty() {returntrue }// type set of V is not empty// No type with non-empty type set satisfies the empty type set.if .typeSet().IsEmpty() {if != nil { * = .sprintf("cannot %s %s (empty type set)", , ) }returnfalse }// V must implement T's methods, if any.if , := .missingMethod(, , true, Identical, ); != nil/* !Implements(V, T) */ {if != nil { * = .sprintf("%s does not %s %s %s", , , , *) }returnfalse }// Only check comparability if we don't have a more specific error. := func() bool {if !.IsComparable() {returntrue }// If T is comparable, V must be comparable. // If V is strictly comparable, we're done.ifcomparable(, false/* strict comparability */, nil, nil) {returntrue }// For constraint satisfaction, use dynamic (spec) comparability // so that ordinary, non-type parameter interfaces implement comparable.if && comparable(, true/* spec comparability */, nil, nil) {// V is comparable if we are at Go 1.20 or higher.if == nil || .allowVersion(atPos(), go1_20) { // atPos needed so that go/types generate passesreturntrue }if != nil { * = .sprintf("%s to %s comparable requires go1.20 or later", , ) }returnfalse }if != nil { * = .sprintf("%s does not %s comparable", , ) }returnfalse }// V must also be in the set of types of T, if any. // Constraints with empty type sets were already excluded above.if !.typeSet().hasTerms() {return () // nothing to do }// If V is itself an interface, each of its possible types must be in the set // of T types (i.e., the V type set must be a subset of the T type set). // Interfaces V with empty type sets were already excluded above.if != nil {if !.typeSet().subsetOf(.typeSet()) {// TODO(gri) report which type is missingif != nil { * = .sprintf("%s does not %s %s", , , ) }returnfalse }return () }// Otherwise, V's type must be included in the iface type set.varTypeif .typeSet().is(func( *term) bool {if !.includes() {// If V ∉ t.typ but V ∈ ~t.typ then remember this type // so we can suggest it as an alternative in the error // message.if == nil && !.tilde && Identical(.typ, under(.typ)) { := * .tilde = trueif .includes() { = .typ } }returntrue }returnfalse }) {if != nil {varstringswitch {case != nil: = .sprintf("possibly missing ~ for %s in %s", , )casementions(, ): = .sprintf("%s mentions %s, but %s is not in the type set of %s", , , , )default: = .sprintf("%s missing in %s", , .typeSet().terms) } * = .sprintf("%s does not %s %s (%s)", , , , ) }returnfalse }return ()}// mentions reports whether type T "mentions" typ in an (embedded) element or term// of T (whether typ is in the type set of T or not). For better error messages.func mentions(, Type) bool {switch T := .(type) {case *Interface:for , := range .embeddeds {if (, ) {returntrue } }case *Union:for , := range .terms {if (.typ, ) {returntrue } }default:ifIdentical(, ) {returntrue } }returnfalse}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.