X7ROOT File Manager
Current Path:
/opt/golang/1.19.4/src/cmd/compile/internal/types2
opt
/
golang
/
1.19.4
/
src
/
cmd
/
compile
/
internal
/
types2
/
📁
..
📄
api.go
(17.37 KB)
📄
api_test.go
(79.44 KB)
📄
array.go
(803 B)
📄
assignments.go
(13.89 KB)
📄
basic.go
(1.48 KB)
📄
builtins.go
(23.73 KB)
📄
builtins_test.go
(9.89 KB)
📄
call.go
(19.08 KB)
📄
chan.go
(910 B)
📄
check.go
(17.12 KB)
📄
check_test.go
(8.96 KB)
📄
compilersupport.go
(1.05 KB)
📄
context.go
(4.34 KB)
📄
context_test.go
(2.3 KB)
📄
conversions.go
(8.27 KB)
📄
decl.go
(27.86 KB)
📄
errorcalls_test.go
(1.15 KB)
📄
errors.go
(7.62 KB)
📄
errors_test.go
(1.01 KB)
📄
example_test.go
(7.41 KB)
📄
expr.go
(54.01 KB)
📄
gccgosizes.go
(1017 B)
📄
hilbert_test.go
(3.63 KB)
📄
importer_test.go
(913 B)
📄
index.go
(11.13 KB)
📄
infer.go
(24.86 KB)
📄
initorder.go
(9.55 KB)
📄
instantiate.go
(9.93 KB)
📄
instantiate_test.go
(5.98 KB)
📄
interface.go
(6.04 KB)
📄
issues_test.go
(17.4 KB)
📄
labels.go
(7.05 KB)
📄
lookup.go
(17.01 KB)
📄
main_test.go
(336 B)
📄
map.go
(659 B)
📄
mono.go
(9.03 KB)
📄
mono_test.go
(2.65 KB)
📄
named.go
(22.4 KB)
📄
named_test.go
(2.35 KB)
📄
object.go
(18.8 KB)
📄
object_test.go
(5.13 KB)
📄
objset.go
(928 B)
📄
operand.go
(10.62 KB)
📄
package.go
(2.67 KB)
📄
pointer.go
(635 B)
📄
predicates.go
(14.64 KB)
📄
resolver.go
(24.88 KB)
📄
resolver_test.go
(4.81 KB)
📄
return.go
(4.34 KB)
📄
scope.go
(9.38 KB)
📄
selection.go
(3.99 KB)
📄
self_test.go
(2.58 KB)
📄
signature.go
(12.1 KB)
📄
sizeof_test.go
(1.28 KB)
📄
sizes.go
(7.56 KB)
📄
sizes_test.go
(3.25 KB)
📄
slice.go
(577 B)
📄
stdlib_test.go
(8.8 KB)
📄
stmt.go
(25.66 KB)
📄
struct.go
(6.24 KB)
📄
subst.go
(10.78 KB)
📄
termlist.go
(3.68 KB)
📄
termlist_test.go
(7.18 KB)
📁
testdata
📄
tuple.go
(929 B)
📄
type.go
(2.92 KB)
📄
typelists.go
(1.84 KB)
📄
typeparam.go
(4.75 KB)
📄
typeset.go
(13.87 KB)
📄
typeset_test.go
(2.41 KB)
📄
typestring.go
(10.61 KB)
📄
typestring_test.go
(4.11 KB)
📄
typeterm.go
(3.52 KB)
📄
typeterm_test.go
(5.08 KB)
📄
typexpr.go
(14.8 KB)
📄
unify.go
(18.34 KB)
📄
union.go
(6.1 KB)
📄
universe.go
(7.58 KB)
📄
validtype.go
(7.77 KB)
📄
version.go
(2.13 KB)
Editing: 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 types2 import ( "cmd/compile/internal/syntax" "errors" "fmt" ) // Instantiate instantiates the type orig with the given type arguments targs. // orig must be a *Named or a *Signature type. If there is no error, the // resulting Type is an instantiated type of the same kind (either a *Named or // a *Signature). 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 // corresponding type constraints. If verification fails, the resulting error // may wrap an *ArgumentError indicating which type argument did not satisfy // its corresponding 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 Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) { if ctxt == nil { ctxt = NewContext() } if validate { var tparams []*TypeParam switch t := orig.(type) { case *Named: tparams = t.TypeParams().list() case *Signature: tparams = t.TypeParams().list() } if len(targs) != len(tparams) { return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(targs), orig, len(tparams)) } if i, err := (*Checker)(nil).verify(nopos, tparams, targs, ctxt); err != nil { return nil, &ArgumentError{i, err} } } inst := (*Checker)(nil).instance(nopos, orig, targs, nil, ctxt) return inst, 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 (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, expanding *Named, ctxt *Context) (res 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 ctxts []*Context if expanding != nil { ctxts = append(ctxts, expanding.inst.ctxt) } if ctxt != nil { ctxts = append(ctxts, ctxt) } assert(len(ctxts) > 0) // Compute all hashes; hashes may differ across contexts due to different // unique IDs for Named types within the hasher. hashes := make([]string, len(ctxts)) for i, ctxt := range ctxts { hashes[i] = ctxt.instanceHash(orig, targs) } // If local is non-nil, updateContexts return the type recorded in // local. updateContexts := func(res Type) Type { for i := len(ctxts) - 1; i >= 0; i-- { res = ctxts[i].update(hashes[i], orig, targs, res) } return res } // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. for i, ctxt := range ctxts { if inst := ctxt.lookup(hashes[i], orig, targs); inst != nil { return updateContexts(inst) } } switch orig := orig.(type) { case *Named: res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily case *Signature: assert(expanding == nil) // function instances cannot be reached from Named types tparams := orig.TypeParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } if tparams.Len() == 0 { return orig // nothing to do (minor optimization) } sig := check.subst(pos, orig, makeSubstMap(tparams.list(), targs), nil, ctxt).(*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 sig == orig { copy := *sig sig = © } // After instantiating a generic signature, it is not generic // anymore; we need to set tparams to nil. sig.tparams = nil res = sig default: // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig)) } // Update all contexts; it's possible that we've lost a race. return updateContexts(res) } // validateTArgLen verifies that the length of targs and tparams matches, // reporting an error if not. If validation fails and check is nil, // validateTArgLen panics. func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool { if ntargs != ntparams { // TODO(gri) provide better error message if check != nil { check.errorf(pos, "got %d arguments but %d type parameters", ntargs, ntparams) return false } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams)) } return true } func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type, ctxt *Context) (int, error) { smap := makeSubstMap(tparams, targs) for i, tpar := range tparams { // Ensure that we have a (possibly implicit) interface as type bound (issue #51048). tpar.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. bound := check.subst(pos, tpar.bound, smap, nil, ctxt) if err := check.implements(targs[i], bound); err != nil { return i, err } } return -1, nil } // implements checks if V implements T and reports an error if it doesn't. // The receiver may be nil if implements is called through an exported // API call such as AssignableTo. func (check *Checker) implements(V, T Type) error { Vu := under(V) Tu := under(T) if Vu == Typ[Invalid] || Tu == Typ[Invalid] { return nil // avoid follow-on errors } if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] { return nil // avoid follow-on errors (see issue #49541 for an example) } errorf := func(format string, args ...interface{}) error { return errors.New(check.sprintf(format, args...)) } Ti, _ := Tu.(*Interface) if Ti == nil { var cause string if isInterfacePtr(Tu) { cause = check.sprintf("type %s is pointer to interface, not interface", T) } else { cause = check.sprintf("%s is not an interface", T) } return errorf("%s does not implement %s (%s)", V, T, cause) } // Every type satisfies the empty interface. if Ti.Empty() { return nil } // 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.) Vi, _ := Vu.(*Interface) if Vi != nil && Vi.typeSet().IsEmpty() { return nil } // type set of V is not empty // No type with non-empty type set satisfies the empty type set. if Ti.typeSet().IsEmpty() { return errorf("cannot implement %s (empty type set)", T) } // V must implement T's methods, if any. if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ { return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong)) } // If T is comparable, V must be comparable. // Remember as a pending error and report only if we don't have a more specific error. var pending error if Ti.IsComparable() && !comparable(V, false, nil, nil) { pending = errorf("%s does not implement comparable", V) } // V must also be in the set of types of T, if any. // Constraints with empty type sets were already excluded above. if !Ti.typeSet().hasTerms() { return pending // 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 Vi != nil { if !Vi.typeSet().subsetOf(Ti.typeSet()) { // TODO(gri) report which type is missing return errorf("%s does not implement %s", V, T) } return pending } // Otherwise, V's type must be included in the iface type set. var alt Type if Ti.typeSet().is(func(t *term) bool { if !t.includes(V) { // 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 alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) { tt := *t tt.tilde = true if tt.includes(V) { alt = t.typ } } return true } return false }) { if alt != nil { return errorf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T) } else { return errorf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms) } } return pending }
Upload File
Create Folder