type Constraint … type Finder … // Find inspects a single package, populating Result with its pairs of // constrained types. // // The result is non-canonical and thus may contain duplicates (but this // tends to preserves names of interface types better). // // The package must be free of type errors, and // info.{Defs,Uses,Selections,Types} must have been populated by the // type-checker. func (f *Finder) Find(info *types.Info, files []*ast.File) { … } var tInvalid … var tUntypedBool … var tUntypedNil … // exprN visits an expression in a multi-value context. func (f *Finder) exprN(e ast.Expr) types.Type { … } func (f *Finder) call(sig *types.Signature, args []ast.Expr) { … } // builtin visits the arguments of a builtin type with signature sig. func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr) { … } func (f *Finder) extract(tuple types.Type, i int) types.Type { … } func (f *Finder) valueSpec(spec *ast.ValueSpec) { … } // assign records pairs of distinct types that are related by // assignability, where the left-hand side is an interface and both // sides have methods. // // It should be called for all assignability checks, type assertions, // explicit conversions and comparisons between two types, unless the // types are uninteresting (e.g. lhs is a concrete type, or the empty // interface; rhs has no methods). func (f *Finder) assign(lhs, rhs types.Type) { … } // typeAssert must be called for each type assertion x.(T) where x has // interface type I. func (f *Finder) typeAssert(I, T types.Type) { … } // compare must be called for each comparison x==y. func (f *Finder) compare(x, y types.Type) { … } // expr visits a true expression (not a type or defining ident) // and returns its type. func (f *Finder) expr(e ast.Expr) types.Type { … } func (f *Finder) stmt(s ast.Stmt) { … } func unparen(e ast.Expr) ast.Expr { … } func isInterface(T types.Type) bool { … } func coreType(T types.Type) types.Type { … } func instance(info *types.Info, expr ast.Expr) bool { … }