Source File
instantiate.go
Belonging Package
go/types
// 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 {TypeTypeParams() *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)if len() != len() {return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(), , len())}if , := (*Checker)(nil).verify(nopos, , , ); != nil {return nil, &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 there is an error (such as wrong number// of type arguments), the result is Typ[Invalid].//// 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.//// check may be nil (when not type-checking syntax); pos is used only only if check is non-nil.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:if !buildcfg.Experiment.AliasTypeParams {assert( == nil) // Alias instances cannot be reached from Named types}// verify type parameter count (see go.dev/issue/71198 for a test case):= .TypeParams()if !.validateTArgLen(, .obj.Name(), .Len(), len()) {// TODO(gri) Consider returning a valid alias instance with invalid// underlying (aliased) type to match behavior of *Named// types. Then this function will never return an invalid// result.return Typ[Invalid]}if .Len() == 0 {return // nothing to do (minor optimization)}= .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()) {return Typ[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 {var stringswitch {case < := "not enough"case > := "too many"default:return true}:= .sprintf("%s type arguments for type %s: have %d, want %d", , , , )if != nil {.error(atPos(), WrongTypeArgCount, )return false}panic(fmt.Sprintf("%v: %s", , ))}// check may be nil; pos is used only if check is non-nil.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, )var stringif !.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) (, Type, bool, *string) bool {:= under():= under()if !isValid() || !isValid() {return true // avoid follow-on errors}if , := .(*Pointer); != nil && !isValid(under(.base)) {return true // avoid follow-on errors (see go.dev/issue/49541 for an example)}:= "implement"if {= "satisfy"}, := .(*Interface)if == nil {if != nil {var stringif isInterfacePtr() {= .sprintf("type %s is pointer to interface, not interface", )} else {= .sprintf("%s is not an interface", )}* = .sprintf("%s does not %s %s (%s)", , , , )}return false}// Every type satisfies the empty interface.if .Empty() {return true}// 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() {return true}// 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)", , )}return false}// V must implement T's methods, if any.if !.hasAllMethods(, , true, Identical, ) /* !Implements(V, T) */ {if != nil {* = .sprintf("%s does not %s %s %s", , , , *)}return false}// Only check comparability if we don't have a more specific error.:= func() bool {if !.IsComparable() {return true}// If T is comparable, V must be comparable.// If V is strictly comparable, we're done.if comparableType(, false /* strict comparability */, nil, nil) {return true}// For constraint satisfaction, use dynamic (spec) comparability// so that ordinary, non-type parameter interfaces implement comparable.if && comparableType(, true /* spec comparability */, nil, nil) {// V is comparable if we are at Go 1.20 or higher.if == nil || .allowVersion(go1_20) {return true}if != nil {* = .sprintf("%s to %s comparable requires go1.20 or later", , )}return false}if != nil {* = .sprintf("%s does not %s comparable", , )}return false}// 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", , , )}return false}return ()}// Otherwise, V's type must be included in the iface type set.var Typeif .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}}return true}return false}) {if != nil {var stringswitch {case != nil:= .sprintf("possibly missing ~ for %s in %s", , )case mentions(, ):= .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)", , , , )}return false}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 (, Type) bool {switch T := .(type) {case *Interface:for , := range .embeddeds {if (, ) {return true}}case *Union:for , := range .terms {if (.typ, ) {return true}}default:if Identical(, ) {return true}}return false}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)