// 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.package typesimport (.)// ----------------------------------------------------------------------------// API// An Interface represents an interface type.typeInterfacestruct { check *Checker// for error reporting; nil once type set is computed methods []*Func// ordered list of explicitly declared methods embeddeds []Type// ordered list of explicitly embedded elements embedPos *[]token.Pos// positions of embedded elements; or nil (for error messages) - use pointer to save space implicit bool// interface is wrapper for type set literal (non-interface T, ~T, or A|B) complete bool// indicates that obj, methods, and embeddeds are set and type set can be computed tset *_TypeSet// type set described by this interface, computed lazily}// typeSet returns the type set for interface t.func ( *Interface) () *_TypeSet { returncomputeInterfaceTypeSet(.check, nopos, ) }// emptyInterface represents the empty (completed) interfacevar emptyInterface = Interface{complete: true, tset: &topTypeSet}// NewInterface returns a new interface for the given methods and embedded types.// NewInterface takes ownership of the provided methods and may modify their types// by setting missing receivers.//// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types.func ( []*Func, []*Named) *Interface { := make([]Type, len())for , := range { [] = }returnNewInterfaceType(, )}// NewInterfaceType returns a new interface for the given methods and embedded// types. NewInterfaceType takes ownership of the provided methods and may// modify their types by setting missing receivers.//// To avoid race conditions, the interface's type set should be computed before// concurrent use of the interface, by explicitly calling Complete.func ( []*Func, []Type) *Interface {iflen() == 0 && len() == 0 {return &emptyInterface }// set method receivers if necessary := (*Checker)(nil).newInterface()for , := range {if := .typ.(*Signature); .recv == nil { .recv = NewVar(.pos, .pkg, "", ) } }// sort for API stabilitysortMethods() .methods = .embeddeds = .complete = truereturn}// check may be nilfunc ( *Checker) () *Interface { := &Interface{check: }if != nil { .needsCleanup() }return}// MarkImplicit marks the interface t as implicit, meaning this interface// corresponds to a constraint literal such as ~T or A|B without explicit// interface embedding. MarkImplicit should be called before any concurrent use// of implicit interfaces.func ( *Interface) () { .implicit = true}// NumExplicitMethods returns the number of explicitly declared methods of interface t.func ( *Interface) () int { returnlen(.methods) }// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().// The methods are ordered by their unique [Id].func ( *Interface) ( int) *Func { return .methods[] }// NumEmbeddeds returns the number of embedded types in interface t.func ( *Interface) () int { returnlen(.embeddeds) }// Embedded returns the i'th embedded defined (*[Named]) type of interface t for 0 <= i < t.NumEmbeddeds().// The result is nil if the i'th embedded type is not a defined type.//// Deprecated: Use [Interface.EmbeddedType] which is not restricted to defined (*[Named]) types.func ( *Interface) ( int) *Named { returnasNamed(.embeddeds[]) }// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().func ( *Interface) ( int) Type { return .embeddeds[] }// NumMethods returns the total number of methods of interface t.func ( *Interface) () int { return .typeSet().NumMethods() }// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().// The methods are ordered by their unique Id.func ( *Interface) ( int) *Func { return .typeSet().Method() }// Empty reports whether t is the empty interface.func ( *Interface) () bool { return .typeSet().IsAll() }// IsComparable reports whether each type in interface t's type set is comparable.func ( *Interface) () bool { return .typeSet().IsComparable(nil) }// IsMethodSet reports whether the interface t is fully described by its method// set.func ( *Interface) () bool { return .typeSet().IsMethodSet() }// IsImplicit reports whether the interface t is a wrapper for a type set literal.func ( *Interface) () bool { return .implicit }// Complete computes the interface's type set. It must be called by users of// [NewInterfaceType] and [NewInterface] after the interface's embedded types are// fully defined and before using the interface type in any way other than to// form other types. The interface must not contain duplicate methods or a// panic occurs. Complete returns the receiver.//// Interface types that have been completed are safe for concurrent use.func ( *Interface) () *Interface {if !.complete { .complete = true } .typeSet() // checks if t.tset is already setreturn}func ( *Interface) () Type { return }func ( *Interface) () string { returnTypeString(, nil) }// ----------------------------------------------------------------------------// Implementationfunc ( *Interface) () { .typeSet() // any interface that escapes type checking must be safe for concurrent use .check = nil .embedPos = nil}func ( *Checker) ( *Interface, *ast.InterfaceType, *TypeName) { := func( token.Pos, Type) { .embeddeds = append(.embeddeds, )if .embedPos == nil { .embedPos = new([]token.Pos) } *.embedPos = append(*.embedPos, ) }for , := range .Methods.List {iflen(.Names) == 0 { (.Type.Pos(), parseUnion(, .Type))continue }// f.Name != nil// We have a method with name f.Names[0]. := .Names[0]if .Name == "_" { .error(, BlankIfaceMethod, "methods must have a unique non-blank name")continue// ignore } := .typ(.Type) , := .(*Signature)if == nil {ifisValid() { .errorf(.Type, InvalidSyntaxTree, "%s is not a method signature", ) }continue// ignore }// The go/parser doesn't accept method type parameters but an ast.FuncType may have them.if .tparams != nil {varpositioner = .Typeif , := .Type.(*ast.FuncType); != nil && .TypeParams != nil { = .TypeParams } .error(, InvalidSyntaxTree, "methods cannot have type parameters") }// use named receiver type if available (for better error messages)varType = if != nil {if := asNamed(.typ); != nil { = } } .recv = NewVar(.Pos(), .pkg, "", ) := NewFunc(.Pos(), .pkg, .Name, ) .recordDef(, ) .methods = append(.methods, ) }// All methods and embedded elements for this interface are collected; // i.e., this interface may be used in a type set computation. .complete = trueiflen(.methods) == 0 && len(.embeddeds) == 0 {// empty interface .tset = &topTypeSetreturn }// sort for API stabilitysortMethods(.methods)// (don't sort embeddeds: they must correspond to *embedPos entries)// Compute type set as soon as possible to report any errors. // Subsequent uses of type sets will use this computed type // set and won't need to pass in a *Checker. .later(func() {computeInterfaceTypeSet(, .Pos(), ) }).describef(, "compute type set for %s", )}
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.