Source File
interface.go
Belonging Package
go/types
// 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 types
import (
)
// ----------------------------------------------------------------------------
// API
// An Interface represents an interface type.
type Interface struct {
check *Checker // for error reporting; nil once type set is computed
obj *TypeName // type name object defining this interface; or nil (for better error messages)
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 { return computeInterfaceTypeSet(.check, token.NoPos, ) }
// emptyInterface represents the empty (completed) interface
var 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 {
[] =
}
return NewInterfaceType(, )
}
// 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 {
if len() == 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 stability
sortMethods()
.methods =
.embeddeds =
.complete = true
return
}
// check may be nil
func ( *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 { return len(.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 { return len(.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 EmbeddedType which is not restricted to defined (*Named) types.
func ( *Interface) ( int) *Named { , := .embeddeds[].(*Named); return }
// 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 set
return
}
func ( *Interface) () Type { return }
func ( *Interface) () string { return TypeString(, nil) }
// ----------------------------------------------------------------------------
// Implementation
func ( *Interface) () {
.check = nil
.embedPos = nil
}
func ( *Checker) ( *Interface, *ast.InterfaceType, *Named) {
:= func( token.Pos, Type) {
.embeddeds = append(.embeddeds, )
if .embedPos == nil {
.embedPos = new([]token.Pos)
}
*.embedPos = append(*.embedPos, )
}
for , := range .Methods.List {
if len(.Names) == 0 {
(.Type.Pos(), parseUnion(, .Type))
continue
}
// f.Name != nil
// We have a method with name f.Names[0].
:= .Names[0]
if .Name == "_" {
.errorf(, _BlankIfaceMethod, "invalid method name _")
continue // ignore
}
:= .typ(.Type)
, := .(*Signature)
if == nil {
if != Typ[Invalid] {
.invalidAST(.Type, "%s is not a method signature", )
}
continue // ignore
}
// Always type-check method type parameters but complain if they are not enabled.
// (This extra check is needed here because interface method signatures don't have
// a receiver specification.)
if .tparams != nil {
var positioner = .Type
if , := .Type.(*ast.FuncType); != nil && .TypeParams != nil {
= .TypeParams
}
.errorf(, _InvalidMethodTypeParams, "methods cannot have type parameters")
}
// use named receiver type if available (for better error messages)
var Type =
if != 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 = true
if len(.methods) == 0 && len(.embeddeds) == 0 {
// empty interface
.tset = &topTypeSet
return
}
// sort for API stability
sortMethods(.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 Golds v0.4.9. (GOOS=linux GOARCH=amd64)