const enableReverseTypeInference … // infer attempts to infer the complete set of type arguments for generic function instantiation/call // based on the given type parameters tparams, type arguments targs, function parameters params, and // function arguments args, if any. There must be at least one type parameter, no more type arguments // than type parameters, and params and args must match in number (incl. zero). // If reverse is set, an error message's contents are reversed for a better error message for some // errors related to reverse type inference (where the function call is synthetic). // If successful, infer returns the complete list of given and inferred type arguments, one for each // type parameter. Otherwise the result is nil. Errors are reported through the err parameter. // Note: infer may fail (return nil) due to invalid args operands without reporting additional errors. func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool, err *error_) (inferred []Type) { … } // renameTParams renames the type parameters in the given type such that each type // parameter is given a new identity. renameTParams returns the new type parameters // and updated type. If the result type is unchanged from the argument type, none // of the type parameters in tparams occurred in the type. // If typ is a generic function, type parameters held with typ are not changed and // must be updated separately if desired. // The positions is only used for debug traces. func (check *Checker) renameTParams(pos syntax.Pos, tparams []*TypeParam, typ Type) ([]*TypeParam, Type) { … } // typeParamsString produces a string containing all the type parameter names // in list suitable for human consumption. func typeParamsString(list []*TypeParam) string { … } // isParameterized reports whether typ contains any of the type parameters of tparams. // If typ is a generic function, isParameterized ignores the type parameter declarations; // it only considers the signature proper (incoming and result parameters). func isParameterized(tparams []*TypeParam, typ Type) bool { … } type tpWalker … func (w *tpWalker) isParameterized(typ Type) (res bool) { … } func (w *tpWalker) varList(list []*Var) bool { … } // If the type parameter has a single specific type S, coreTerm returns (S, true). // Otherwise, if tpar has a core type T, it returns a term corresponding to that // core type and false. In that case, if any term of tpar has a tilde, the core // term has a tilde. In all other cases coreTerm returns (nil, false). func coreTerm(tpar *TypeParam) (*term, bool) { … } // killCycles walks through the given type parameters and looks for cycles // created by type parameters whose inferred types refer back to that type // parameter, either directly or indirectly. If such a cycle is detected, // it is killed by setting the corresponding inferred type to nil. // // TODO(gri) Determine if we can simply abort inference as soon as we have // found a single cycle. func killCycles(tparams []*TypeParam, inferred []Type) { … } type cycleFinder … func (w *cycleFinder) typ(typ Type) { … } func (w *cycleFinder) varList(list []*Var) { … }