...

Source file src/go/types/infer.go

Documentation: go/types

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements type parameter inference given
     6  // a list of concrete arguments and a parameter list.
     7  
     8  package types
     9  
    10  import (
    11  	"fmt"
    12  	"go/token"
    13  	"strings"
    14  )
    15  
    16  // infer attempts to infer the complete set of type arguments for generic function instantiation/call
    17  // based on the given type parameters tparams, type arguments targs, function parameters params, and
    18  // function arguments args, if any. There must be at least one type parameter, no more type arguments
    19  // than type parameters, and params and args must match in number (incl. zero).
    20  // If successful, infer returns the complete list of type arguments, one for each type parameter.
    21  // Otherwise the result is nil and appropriate errors will be reported.
    22  //
    23  // Inference proceeds as follows:
    24  //
    25  //	Starting with given type arguments
    26  //	1) apply FTI (function type inference) with typed arguments,
    27  //	2) apply CTI (constraint type inference),
    28  //	3) apply FTI with untyped function arguments,
    29  //	4) apply CTI.
    30  //
    31  // The process stops as soon as all type arguments are known or an error occurs.
    32  func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (result []Type) {
    33  	if debug {
    34  		defer func() {
    35  			assert(result == nil || len(result) == len(tparams))
    36  			for _, targ := range result {
    37  				assert(targ != nil)
    38  			}
    39  			//check.dump("### inferred targs = %s", result)
    40  		}()
    41  	}
    42  
    43  	if traceInference {
    44  		check.dump("-- inferA %s%s ➞ %s", tparams, params, targs)
    45  		defer func() {
    46  			check.dump("=> inferA %s ➞ %s", tparams, result)
    47  		}()
    48  	}
    49  
    50  	// There must be at least one type parameter, and no more type arguments than type parameters.
    51  	n := len(tparams)
    52  	assert(n > 0 && len(targs) <= n)
    53  
    54  	// Function parameters and arguments must match in number.
    55  	assert(params.Len() == len(args))
    56  
    57  	// If we already have all type arguments, we're done.
    58  	if len(targs) == n {
    59  		return targs
    60  	}
    61  	// len(targs) < n
    62  
    63  	const enableTparamRenaming = true
    64  	if enableTparamRenaming {
    65  		// For the purpose of type inference we must differentiate type parameters
    66  		// occurring in explicit type or value function arguments from the type
    67  		// parameters we are solving for via unification, because they may be the
    68  		// same in self-recursive calls. For example:
    69  		//
    70  		//  func f[P *Q, Q any](p P, q Q) {
    71  		//    f(p)
    72  		//  }
    73  		//
    74  		// In this example, the fact that the P used in the instantation f[P] has
    75  		// the same pointer identity as the P we are trying to solve for via
    76  		// unification is coincidental: there is nothing special about recursive
    77  		// calls that should cause them to conflate the identity of type arguments
    78  		// with type parameters. To put it another way: any such self-recursive
    79  		// call is equivalent to a mutually recursive call, which does not run into
    80  		// any problems of type parameter identity. For example, the following code
    81  		// is equivalent to the code above.
    82  		//
    83  		//  func f[P interface{*Q}, Q any](p P, q Q) {
    84  		//    f2(p)
    85  		//  }
    86  		//
    87  		//  func f2[P interface{*Q}, Q any](p P, q Q) {
    88  		//    f(p)
    89  		//  }
    90  		//
    91  		// We can turn the first example into the second example by renaming type
    92  		// parameters in the original signature to give them a new identity. As an
    93  		// optimization, we do this only for self-recursive calls.
    94  
    95  		// We can detect if we are in a self-recursive call by comparing the
    96  		// identity of the first type parameter in the current function with the
    97  		// first type parameter in tparams. This works because type parameters are
    98  		// unique to their type parameter list.
    99  		selfRecursive := check.sig != nil && check.sig.tparams.Len() > 0 && tparams[0] == check.sig.tparams.At(0)
   100  
   101  		if selfRecursive {
   102  			// In self-recursive inference, rename the type parameters with new type
   103  			// parameters that are the same but for their pointer identity.
   104  			tparams2 := make([]*TypeParam, len(tparams))
   105  			for i, tparam := range tparams {
   106  				tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
   107  				tparams2[i] = NewTypeParam(tname, nil)
   108  				tparams2[i].index = tparam.index // == i
   109  			}
   110  
   111  			renameMap := makeRenameMap(tparams, tparams2)
   112  			for i, tparam := range tparams {
   113  				tparams2[i].bound = check.subst(posn.Pos(), tparam.bound, renameMap, nil, check.context())
   114  			}
   115  
   116  			tparams = tparams2
   117  			params = check.subst(posn.Pos(), params, renameMap, nil, check.context()).(*Tuple)
   118  		}
   119  	}
   120  
   121  	// If we have more than 2 arguments, we may have arguments with named and unnamed types.
   122  	// If that is the case, permutate params and args such that the arguments with named
   123  	// types are first in the list. This doesn't affect type inference if all types are taken
   124  	// as is. But when we have inexact unification enabled (as is the case for function type
   125  	// inference), when a named type is unified with an unnamed type, unification proceeds
   126  	// with the underlying type of the named type because otherwise unification would fail
   127  	// right away. This leads to an asymmetry in type inference: in cases where arguments of
   128  	// named and unnamed types are passed to parameters with identical type, different types
   129  	// (named vs underlying) may be inferred depending on the order of the arguments.
   130  	// By ensuring that named types are seen first, order dependence is avoided and unification
   131  	// succeeds where it can (issue #43056).
   132  	const enableArgSorting = true
   133  	if m := len(args); m >= 2 && enableArgSorting {
   134  		// Determine indices of arguments with named and unnamed types.
   135  		var named, unnamed []int
   136  		for i, arg := range args {
   137  			if hasName(arg.typ) {
   138  				named = append(named, i)
   139  			} else {
   140  				unnamed = append(unnamed, i)
   141  			}
   142  		}
   143  
   144  		// If we have named and unnamed types, move the arguments with
   145  		// named types first. Update the parameter list accordingly.
   146  		// Make copies so as not to clobber the incoming slices.
   147  		if len(named) != 0 && len(unnamed) != 0 {
   148  			params2 := make([]*Var, m)
   149  			args2 := make([]*operand, m)
   150  			i := 0
   151  			for _, j := range named {
   152  				params2[i] = params.At(j)
   153  				args2[i] = args[j]
   154  				i++
   155  			}
   156  			for _, j := range unnamed {
   157  				params2[i] = params.At(j)
   158  				args2[i] = args[j]
   159  				i++
   160  			}
   161  			params = NewTuple(params2...)
   162  			args = args2
   163  		}
   164  	}
   165  
   166  	// --- 1 ---
   167  	// Continue with the type arguments we have. Avoid matching generic
   168  	// parameters that already have type arguments against function arguments:
   169  	// It may fail because matching uses type identity while parameter passing
   170  	// uses assignment rules. Instantiate the parameter list with the type
   171  	// arguments we have, and continue with that parameter list.
   172  
   173  	// First, make sure we have a "full" list of type arguments, some of which
   174  	// may be nil (unknown). Make a copy so as to not clobber the incoming slice.
   175  	if len(targs) < n {
   176  		targs2 := make([]Type, n)
   177  		copy(targs2, targs)
   178  		targs = targs2
   179  	}
   180  	// len(targs) == n
   181  
   182  	// Substitute type arguments for their respective type parameters in params,
   183  	// if any. Note that nil targs entries are ignored by check.subst.
   184  	// TODO(gri) Can we avoid this (we're setting known type arguments below,
   185  	//           but that doesn't impact the isParameterized check for now).
   186  	if params.Len() > 0 {
   187  		smap := makeSubstMap(tparams, targs)
   188  		params = check.subst(token.NoPos, params, smap, nil, check.context()).(*Tuple)
   189  	}
   190  
   191  	// Unify parameter and argument types for generic parameters with typed arguments
   192  	// and collect the indices of generic parameters with untyped arguments.
   193  	// Terminology: generic parameter = function parameter with a type-parameterized type
   194  	u := newUnifier(false)
   195  	u.x.init(tparams)
   196  
   197  	// Set the type arguments which we know already.
   198  	for i, targ := range targs {
   199  		if targ != nil {
   200  			u.x.set(i, targ)
   201  		}
   202  	}
   203  
   204  	errorf := func(kind string, tpar, targ Type, arg *operand) {
   205  		// provide a better error message if we can
   206  		targs, index := u.x.types()
   207  		if index == 0 {
   208  			// The first type parameter couldn't be inferred.
   209  			// If none of them could be inferred, don't try
   210  			// to provide the inferred type in the error msg.
   211  			allFailed := true
   212  			for _, targ := range targs {
   213  				if targ != nil {
   214  					allFailed = false
   215  					break
   216  				}
   217  			}
   218  			if allFailed {
   219  				check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
   220  				return
   221  			}
   222  		}
   223  		smap := makeSubstMap(tparams, targs)
   224  		// TODO(rFindley): pass a positioner here, rather than arg.Pos().
   225  		inferred := check.subst(arg.Pos(), tpar, smap, nil, check.context())
   226  		// _CannotInferTypeArgs indicates a failure of inference, though the actual
   227  		// error may be better attributed to a user-provided type argument (hence
   228  		// _InvalidTypeArg). We can't differentiate these cases, so fall back on
   229  		// the more general _CannotInferTypeArgs.
   230  		if inferred != tpar {
   231  			check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
   232  		} else {
   233  			check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
   234  		}
   235  	}
   236  
   237  	// indices of the generic parameters with untyped arguments - save for later
   238  	var indices []int
   239  	for i, arg := range args {
   240  		par := params.At(i)
   241  		// If we permit bidirectional unification, this conditional code needs to be
   242  		// executed even if par.typ is not parameterized since the argument may be a
   243  		// generic function (for which we want to infer its type arguments).
   244  		if isParameterized(tparams, par.typ) {
   245  			if arg.mode == invalid {
   246  				// An error was reported earlier. Ignore this targ
   247  				// and continue, we may still be able to infer all
   248  				// targs resulting in fewer follow-on errors.
   249  				continue
   250  			}
   251  			if targ := arg.typ; isTyped(targ) {
   252  				// If we permit bidirectional unification, and targ is
   253  				// a generic function, we need to initialize u.y with
   254  				// the respective type parameters of targ.
   255  				if !u.unify(par.typ, targ) {
   256  					errorf("type", par.typ, targ, arg)
   257  					return nil
   258  				}
   259  			} else if _, ok := par.typ.(*TypeParam); ok {
   260  				// Since default types are all basic (i.e., non-composite) types, an
   261  				// untyped argument will never match a composite parameter type; the
   262  				// only parameter type it can possibly match against is a *TypeParam.
   263  				// Thus, for untyped arguments we only need to look at parameter types
   264  				// that are single type parameters.
   265  				indices = append(indices, i)
   266  			}
   267  		}
   268  	}
   269  
   270  	// If we've got all type arguments, we're done.
   271  	var index int
   272  	targs, index = u.x.types()
   273  	if index < 0 {
   274  		return targs
   275  	}
   276  
   277  	// --- 2 ---
   278  	// See how far we get with constraint type inference.
   279  	// Note that even if we don't have any type arguments, constraint type inference
   280  	// may produce results for constraints that explicitly specify a type.
   281  	targs, index = check.inferB(posn, tparams, targs)
   282  	if targs == nil || index < 0 {
   283  		return targs
   284  	}
   285  
   286  	// --- 3 ---
   287  	// Use any untyped arguments to infer additional type arguments.
   288  	// Some generic parameters with untyped arguments may have been given
   289  	// a type by now, we can ignore them.
   290  	for _, i := range indices {
   291  		tpar := params.At(i).typ.(*TypeParam) // is type parameter by construction of indices
   292  		// Only consider untyped arguments for which the corresponding type
   293  		// parameter doesn't have an inferred type yet.
   294  		if targs[tpar.index] == nil {
   295  			arg := args[i]
   296  			targ := Default(arg.typ)
   297  			// The default type for an untyped nil is untyped nil. We must not
   298  			// infer an untyped nil type as type parameter type. Ignore untyped
   299  			// nil by making sure all default argument types are typed.
   300  			if isTyped(targ) && !u.unify(tpar, targ) {
   301  				errorf("default type", tpar, targ, arg)
   302  				return nil
   303  			}
   304  		}
   305  	}
   306  
   307  	// If we've got all type arguments, we're done.
   308  	targs, index = u.x.types()
   309  	if index < 0 {
   310  		return targs
   311  	}
   312  
   313  	// --- 4 ---
   314  	// Again, follow up with constraint type inference.
   315  	targs, index = check.inferB(posn, tparams, targs)
   316  	if targs == nil || index < 0 {
   317  		return targs
   318  	}
   319  
   320  	// At least one type argument couldn't be inferred.
   321  	assert(index >= 0 && targs[index] == nil)
   322  	tpar := tparams[index]
   323  	check.errorf(posn, _CannotInferTypeArgs, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos)
   324  	return nil
   325  }
   326  
   327  // typeParamsString produces a string containing all the type parameter names
   328  // in list suitable for human consumption.
   329  func typeParamsString(list []*TypeParam) string {
   330  	// common cases
   331  	n := len(list)
   332  	switch n {
   333  	case 0:
   334  		return ""
   335  	case 1:
   336  		return list[0].obj.name
   337  	case 2:
   338  		return list[0].obj.name + " and " + list[1].obj.name
   339  	}
   340  
   341  	// general case (n > 2)
   342  	var b strings.Builder
   343  	for i, tname := range list[:n-1] {
   344  		if i > 0 {
   345  			b.WriteString(", ")
   346  		}
   347  		b.WriteString(tname.obj.name)
   348  	}
   349  	b.WriteString(", and ")
   350  	b.WriteString(list[n-1].obj.name)
   351  	return b.String()
   352  }
   353  
   354  // isParameterized reports whether typ contains any of the type parameters of tparams.
   355  func isParameterized(tparams []*TypeParam, typ Type) bool {
   356  	w := tpWalker{
   357  		seen:    make(map[Type]bool),
   358  		tparams: tparams,
   359  	}
   360  	return w.isParameterized(typ)
   361  }
   362  
   363  type tpWalker struct {
   364  	seen    map[Type]bool
   365  	tparams []*TypeParam
   366  }
   367  
   368  func (w *tpWalker) isParameterized(typ Type) (res bool) {
   369  	// detect cycles
   370  	if x, ok := w.seen[typ]; ok {
   371  		return x
   372  	}
   373  	w.seen[typ] = false
   374  	defer func() {
   375  		w.seen[typ] = res
   376  	}()
   377  
   378  	switch t := typ.(type) {
   379  	case nil, *Basic: // TODO(gri) should nil be handled here?
   380  		break
   381  
   382  	case *Array:
   383  		return w.isParameterized(t.elem)
   384  
   385  	case *Slice:
   386  		return w.isParameterized(t.elem)
   387  
   388  	case *Struct:
   389  		for _, fld := range t.fields {
   390  			if w.isParameterized(fld.typ) {
   391  				return true
   392  			}
   393  		}
   394  
   395  	case *Pointer:
   396  		return w.isParameterized(t.base)
   397  
   398  	case *Tuple:
   399  		n := t.Len()
   400  		for i := 0; i < n; i++ {
   401  			if w.isParameterized(t.At(i).typ) {
   402  				return true
   403  			}
   404  		}
   405  
   406  	case *Signature:
   407  		// t.tparams may not be nil if we are looking at a signature
   408  		// of a generic function type (or an interface method) that is
   409  		// part of the type we're testing. We don't care about these type
   410  		// parameters.
   411  		// Similarly, the receiver of a method may declare (rather then
   412  		// use) type parameters, we don't care about those either.
   413  		// Thus, we only need to look at the input and result parameters.
   414  		return w.isParameterized(t.params) || w.isParameterized(t.results)
   415  
   416  	case *Interface:
   417  		tset := t.typeSet()
   418  		for _, m := range tset.methods {
   419  			if w.isParameterized(m.typ) {
   420  				return true
   421  			}
   422  		}
   423  		return tset.is(func(t *term) bool {
   424  			return t != nil && w.isParameterized(t.typ)
   425  		})
   426  
   427  	case *Map:
   428  		return w.isParameterized(t.key) || w.isParameterized(t.elem)
   429  
   430  	case *Chan:
   431  		return w.isParameterized(t.elem)
   432  
   433  	case *Named:
   434  		return w.isParameterizedTypeList(t.TypeArgs().list())
   435  
   436  	case *TypeParam:
   437  		// t must be one of w.tparams
   438  		return tparamIndex(w.tparams, t) >= 0
   439  
   440  	default:
   441  		unreachable()
   442  	}
   443  
   444  	return false
   445  }
   446  
   447  func (w *tpWalker) isParameterizedTypeList(list []Type) bool {
   448  	for _, t := range list {
   449  		if w.isParameterized(t) {
   450  			return true
   451  		}
   452  	}
   453  	return false
   454  }
   455  
   456  // inferB returns the list of actual type arguments inferred from the type parameters'
   457  // bounds and an initial set of type arguments. If type inference is impossible because
   458  // unification fails, an error is reported if report is set to true, the resulting types
   459  // list is nil, and index is 0.
   460  // Otherwise, types is the list of inferred type arguments, and index is the index of the
   461  // first type argument in that list that couldn't be inferred (and thus is nil). If all
   462  // type arguments were inferred successfully, index is < 0. The number of type arguments
   463  // provided may be less than the number of type parameters, but there must be at least one.
   464  func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type) (types []Type, index int) {
   465  	assert(len(tparams) >= len(targs) && len(targs) > 0)
   466  
   467  	if traceInference {
   468  		check.dump("-- inferB %s ➞ %s", tparams, targs)
   469  		defer func() {
   470  			check.dump("=> inferB %s ➞ %s", tparams, types)
   471  		}()
   472  	}
   473  
   474  	// Setup bidirectional unification between constraints
   475  	// and the corresponding type arguments (which may be nil!).
   476  	u := newUnifier(false)
   477  	u.x.init(tparams)
   478  	u.y = u.x // type parameters between LHS and RHS of unification are identical
   479  
   480  	// Set the type arguments which we know already.
   481  	for i, targ := range targs {
   482  		if targ != nil {
   483  			u.x.set(i, targ)
   484  		}
   485  	}
   486  
   487  	// Repeatedly apply constraint type inference as long as
   488  	// there are still unknown type arguments and progress is
   489  	// being made.
   490  	//
   491  	// This is an O(n^2) algorithm where n is the number of
   492  	// type parameters: if there is progress (and iteration
   493  	// continues), at least one type argument is inferred
   494  	// per iteration and we have a doubly nested loop.
   495  	// In practice this is not a problem because the number
   496  	// of type parameters tends to be very small (< 5 or so).
   497  	// (It should be possible for unification to efficiently
   498  	// signal newly inferred type arguments; then the loops
   499  	// here could handle the respective type parameters only,
   500  	// but that will come at a cost of extra complexity which
   501  	// may not be worth it.)
   502  	for n := u.x.unknowns(); n > 0; {
   503  		nn := n
   504  
   505  		for i, tpar := range tparams {
   506  			// If there is a core term (i.e., a core type with tilde information)
   507  			// unify the type parameter with the core type.
   508  			if core, single := coreTerm(tpar); core != nil {
   509  				// A type parameter can be unified with its core type in two cases.
   510  				tx := u.x.at(i)
   511  				switch {
   512  				case tx != nil:
   513  					// The corresponding type argument tx is known.
   514  					// In this case, if the core type has a tilde, the type argument's underlying
   515  					// type must match the core type, otherwise the type argument and the core type
   516  					// must match.
   517  					// If tx is an external type parameter, don't consider its underlying type
   518  					// (which is an interface). Core type unification will attempt to unify against
   519  					// core.typ.
   520  					// Note also that even with inexact unification we cannot leave away the under
   521  					// call here because it's possible that both tx and core.typ are named types,
   522  					// with under(tx) being a (named) basic type matching core.typ. Such cases do
   523  					// not match with inexact unification.
   524  					if core.tilde && !isTypeParam(tx) {
   525  						tx = under(tx)
   526  					}
   527  					if !u.unify(tx, core.typ) {
   528  						// TODO(gri) improve error message by providing the type arguments
   529  						//           which we know already
   530  						// Don't use term.String() as it always qualifies types, even if they
   531  						// are in the current package.
   532  						tilde := ""
   533  						if core.tilde {
   534  							tilde = "~"
   535  						}
   536  						check.errorf(posn, _InvalidTypeArg, "%s does not match %s%s", tpar, tilde, core.typ)
   537  						return nil, 0
   538  					}
   539  
   540  				case single && !core.tilde:
   541  					// The corresponding type argument tx is unknown and there's a single
   542  					// specific type and no tilde.
   543  					// In this case the type argument must be that single type; set it.
   544  					u.x.set(i, core.typ)
   545  
   546  				default:
   547  					// Unification is not possible and no progress was made.
   548  					continue
   549  				}
   550  
   551  				// The number of known type arguments may have changed.
   552  				nn = u.x.unknowns()
   553  				if nn == 0 {
   554  					break // all type arguments are known
   555  				}
   556  			}
   557  		}
   558  
   559  		assert(nn <= n)
   560  		if nn == n {
   561  			break // no progress
   562  		}
   563  		n = nn
   564  	}
   565  
   566  	// u.x.types() now contains the incoming type arguments plus any additional type
   567  	// arguments which were inferred from core terms. The newly inferred non-nil
   568  	// entries may still contain references to other type parameters.
   569  	// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
   570  	// was given, unification produced the type list [int, []C, *A]. We eliminate the
   571  	// remaining type parameters by substituting the type parameters in this type list
   572  	// until nothing changes anymore.
   573  	types, _ = u.x.types()
   574  	if debug {
   575  		for i, targ := range targs {
   576  			assert(targ == nil || types[i] == targ)
   577  		}
   578  	}
   579  
   580  	// The data structure of each (provided or inferred) type represents a graph, where
   581  	// each node corresponds to a type and each (directed) vertice points to a component
   582  	// type. The substitution process described above repeatedly replaces type parameter
   583  	// nodes in these graphs with the graphs of the types the type parameters stand for,
   584  	// which creates a new (possibly bigger) graph for each type.
   585  	// The substitution process will not stop if the replacement graph for a type parameter
   586  	// also contains that type parameter.
   587  	// For instance, for [A interface{ *A }], without any type argument provided for A,
   588  	// unification produces the type list [*A]. Substituting A in *A with the value for
   589  	// A will lead to infinite expansion by producing [**A], [****A], [********A], etc.,
   590  	// because the graph A -> *A has a cycle through A.
   591  	// Generally, cycles may occur across multiple type parameters and inferred types
   592  	// (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]).
   593  	// We eliminate cycles by walking the graphs for all type parameters. If a cycle
   594  	// through a type parameter is detected, cycleFinder nils out the respectice type
   595  	// which kills the cycle; this also means that the respective type could not be
   596  	// inferred.
   597  	//
   598  	// TODO(gri) If useful, we could report the respective cycle as an error. We don't
   599  	//           do this now because type inference will fail anyway, and furthermore,
   600  	//           constraints with cycles of this kind cannot currently be satisfied by
   601  	//           any user-suplied type. But should that change, reporting an error
   602  	//           would be wrong.
   603  	w := cycleFinder{tparams, types, make(map[Type]bool)}
   604  	for _, t := range tparams {
   605  		w.typ(t) // t != nil
   606  	}
   607  
   608  	// dirty tracks the indices of all types that may still contain type parameters.
   609  	// We know that nil type entries and entries corresponding to provided (non-nil)
   610  	// type arguments are clean, so exclude them from the start.
   611  	var dirty []int
   612  	for i, typ := range types {
   613  		if typ != nil && (i >= len(targs) || targs[i] == nil) {
   614  			dirty = append(dirty, i)
   615  		}
   616  	}
   617  
   618  	for len(dirty) > 0 {
   619  		// TODO(gri) Instead of creating a new substMap for each iteration,
   620  		// provide an update operation for substMaps and only change when
   621  		// needed. Optimization.
   622  		smap := makeSubstMap(tparams, types)
   623  		n := 0
   624  		for _, index := range dirty {
   625  			t0 := types[index]
   626  			if t1 := check.subst(token.NoPos, t0, smap, nil, check.context()); t1 != t0 {
   627  				types[index] = t1
   628  				dirty[n] = index
   629  				n++
   630  			}
   631  		}
   632  		dirty = dirty[:n]
   633  	}
   634  
   635  	// Once nothing changes anymore, we may still have type parameters left;
   636  	// e.g., a constraint with core type *P may match a type parameter Q but
   637  	// we don't have any type arguments to fill in for *P or Q (issue #45548).
   638  	// Don't let such inferences escape, instead nil them out.
   639  	for i, typ := range types {
   640  		if typ != nil && isParameterized(tparams, typ) {
   641  			types[i] = nil
   642  		}
   643  	}
   644  
   645  	// update index
   646  	index = -1
   647  	for i, typ := range types {
   648  		if typ == nil {
   649  			index = i
   650  			break
   651  		}
   652  	}
   653  
   654  	return
   655  }
   656  
   657  // If the type parameter has a single specific type S, coreTerm returns (S, true).
   658  // Otherwise, if tpar has a core type T, it returns a term corresponding to that
   659  // core type and false. In that case, if any term of tpar has a tilde, the core
   660  // term has a tilde. In all other cases coreTerm returns (nil, false).
   661  func coreTerm(tpar *TypeParam) (*term, bool) {
   662  	n := 0
   663  	var single *term // valid if n == 1
   664  	var tilde bool
   665  	tpar.is(func(t *term) bool {
   666  		if t == nil {
   667  			assert(n == 0)
   668  			return false // no terms
   669  		}
   670  		n++
   671  		single = t
   672  		if t.tilde {
   673  			tilde = true
   674  		}
   675  		return true
   676  	})
   677  	if n == 1 {
   678  		if debug {
   679  			assert(debug && under(single.typ) == coreType(tpar))
   680  		}
   681  		return single, true
   682  	}
   683  	if typ := coreType(tpar); typ != nil {
   684  		// A core type is always an underlying type.
   685  		// If any term of tpar has a tilde, we don't
   686  		// have a precise core type and we must return
   687  		// a tilde as well.
   688  		return &term{tilde, typ}, false
   689  	}
   690  	return nil, false
   691  }
   692  
   693  type cycleFinder struct {
   694  	tparams []*TypeParam
   695  	types   []Type
   696  	seen    map[Type]bool
   697  }
   698  
   699  func (w *cycleFinder) typ(typ Type) {
   700  	if w.seen[typ] {
   701  		// We have seen typ before. If it is one of the type parameters
   702  		// in tparams, iterative substitution will lead to infinite expansion.
   703  		// Nil out the corresponding type which effectively kills the cycle.
   704  		if tpar, _ := typ.(*TypeParam); tpar != nil {
   705  			if i := tparamIndex(w.tparams, tpar); i >= 0 {
   706  				// cycle through tpar
   707  				w.types[i] = nil
   708  			}
   709  		}
   710  		// If we don't have one of our type parameters, the cycle is due
   711  		// to an ordinary recursive type and we can just stop walking it.
   712  		return
   713  	}
   714  	w.seen[typ] = true
   715  	defer delete(w.seen, typ)
   716  
   717  	switch t := typ.(type) {
   718  	case *Basic:
   719  		// nothing to do
   720  
   721  	case *Array:
   722  		w.typ(t.elem)
   723  
   724  	case *Slice:
   725  		w.typ(t.elem)
   726  
   727  	case *Struct:
   728  		w.varList(t.fields)
   729  
   730  	case *Pointer:
   731  		w.typ(t.base)
   732  
   733  	// case *Tuple:
   734  	//      This case should not occur because tuples only appear
   735  	//      in signatures where they are handled explicitly.
   736  
   737  	case *Signature:
   738  		if t.params != nil {
   739  			w.varList(t.params.vars)
   740  		}
   741  		if t.results != nil {
   742  			w.varList(t.results.vars)
   743  		}
   744  
   745  	case *Union:
   746  		for _, t := range t.terms {
   747  			w.typ(t.typ)
   748  		}
   749  
   750  	case *Interface:
   751  		for _, m := range t.methods {
   752  			w.typ(m.typ)
   753  		}
   754  		for _, t := range t.embeddeds {
   755  			w.typ(t)
   756  		}
   757  
   758  	case *Map:
   759  		w.typ(t.key)
   760  		w.typ(t.elem)
   761  
   762  	case *Chan:
   763  		w.typ(t.elem)
   764  
   765  	case *Named:
   766  		for _, tpar := range t.TypeArgs().list() {
   767  			w.typ(tpar)
   768  		}
   769  
   770  	case *TypeParam:
   771  		if i := tparamIndex(w.tparams, t); i >= 0 && w.types[i] != nil {
   772  			w.typ(w.types[i])
   773  		}
   774  
   775  	default:
   776  		panic(fmt.Sprintf("unexpected %T", typ))
   777  	}
   778  }
   779  
   780  func (w *cycleFinder) varList(list []*Var) {
   781  	for _, v := range list {
   782  		w.typ(v.typ)
   783  	}
   784  }
   785  

View as plain text