Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/types/unify.go

Documentation: go/types

     1  // Copyright 2020 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 unification.
     6  
     7  package types
     8  
     9  import (
    10  	"bytes"
    11  	"go/token"
    12  	"sort"
    13  )
    14  
    15  // The unifier maintains two separate sets of type parameters x and y
    16  // which are used to resolve type parameters in the x and y arguments
    17  // provided to the unify call. For unidirectional unification, only
    18  // one of these sets (say x) is provided, and then type parameters are
    19  // only resolved for the x argument passed to unify, not the y argument
    20  // (even if that also contains possibly the same type parameters). This
    21  // is crucial to infer the type parameters of self-recursive calls:
    22  //
    23  //	func f[P any](a P) { f(a) }
    24  //
    25  // For the call f(a) we want to infer that the type argument for P is P.
    26  // During unification, the parameter type P must be resolved to the type
    27  // parameter P ("x" side), but the argument type P must be left alone so
    28  // that unification resolves the type parameter P to P.
    29  //
    30  // For bidirection unification, both sets are provided. This enables
    31  // unification to go from argument to parameter type and vice versa.
    32  // For constraint type inference, we use bidirectional unification
    33  // where both the x and y type parameters are identical. This is done
    34  // by setting up one of them (using init) and then assigning its value
    35  // to the other.
    36  
    37  // A unifier maintains the current type parameters for x and y
    38  // and the respective types inferred for each type parameter.
    39  // A unifier is created by calling newUnifier.
    40  type unifier struct {
    41  	check *Checker
    42  	exact bool
    43  	x, y  tparamsList // x and y must initialized via tparamsList.init
    44  	types []Type      // inferred types, shared by x and y
    45  }
    46  
    47  // newUnifier returns a new unifier.
    48  // If exact is set, unification requires unified types to match
    49  // exactly. If exact is not set, a named type's underlying type
    50  // is considered if unification would fail otherwise, and the
    51  // direction of channels is ignored.
    52  func newUnifier(check *Checker, exact bool) *unifier {
    53  	u := &unifier{check: check, exact: exact}
    54  	u.x.unifier = u
    55  	u.y.unifier = u
    56  	return u
    57  }
    58  
    59  // unify attempts to unify x and y and reports whether it succeeded.
    60  func (u *unifier) unify(x, y Type) bool {
    61  	return u.nify(x, y, nil)
    62  }
    63  
    64  // A tparamsList describes a list of type parameters and the types inferred for them.
    65  type tparamsList struct {
    66  	unifier *unifier
    67  	tparams []*TypeName
    68  	// For each tparams element, there is a corresponding type slot index in indices.
    69  	// index  < 0: unifier.types[-index-1] == nil
    70  	// index == 0: no type slot allocated yet
    71  	// index  > 0: unifier.types[index-1] == typ
    72  	// Joined tparams elements share the same type slot and thus have the same index.
    73  	// By using a negative index for nil types we don't need to check unifier.types
    74  	// to see if we have a type or not.
    75  	indices []int // len(d.indices) == len(d.tparams)
    76  }
    77  
    78  // String returns a string representation for a tparamsList. For debugging.
    79  func (d *tparamsList) String() string {
    80  	var buf bytes.Buffer
    81  	buf.WriteByte('[')
    82  	for i, tname := range d.tparams {
    83  		if i > 0 {
    84  			buf.WriteString(", ")
    85  		}
    86  		writeType(&buf, tname.typ, nil, nil)
    87  		buf.WriteString(": ")
    88  		writeType(&buf, d.at(i), nil, nil)
    89  	}
    90  	buf.WriteByte(']')
    91  	return buf.String()
    92  }
    93  
    94  // init initializes d with the given type parameters.
    95  // The type parameters must be in the order in which they appear in their declaration
    96  // (this ensures that the tparams indices match the respective type parameter index).
    97  func (d *tparamsList) init(tparams []*TypeName) {
    98  	if len(tparams) == 0 {
    99  		return
   100  	}
   101  	if debug {
   102  		for i, tpar := range tparams {
   103  			assert(i == tpar.typ.(*_TypeParam).index)
   104  		}
   105  	}
   106  	d.tparams = tparams
   107  	d.indices = make([]int, len(tparams))
   108  }
   109  
   110  // join unifies the i'th type parameter of x with the j'th type parameter of y.
   111  // If both type parameters already have a type associated with them and they are
   112  // not joined, join fails and return false.
   113  func (u *unifier) join(i, j int) bool {
   114  	ti := u.x.indices[i]
   115  	tj := u.y.indices[j]
   116  	switch {
   117  	case ti == 0 && tj == 0:
   118  		// Neither type parameter has a type slot associated with them.
   119  		// Allocate a new joined nil type slot (negative index).
   120  		u.types = append(u.types, nil)
   121  		u.x.indices[i] = -len(u.types)
   122  		u.y.indices[j] = -len(u.types)
   123  	case ti == 0:
   124  		// The type parameter for x has no type slot yet. Use slot of y.
   125  		u.x.indices[i] = tj
   126  	case tj == 0:
   127  		// The type parameter for y has no type slot yet. Use slot of x.
   128  		u.y.indices[j] = ti
   129  
   130  	// Both type parameters have a slot: ti != 0 && tj != 0.
   131  	case ti == tj:
   132  		// Both type parameters already share the same slot. Nothing to do.
   133  		break
   134  	case ti > 0 && tj > 0:
   135  		// Both type parameters have (possibly different) inferred types. Cannot join.
   136  		return false
   137  	case ti > 0:
   138  		// Only the type parameter for x has an inferred type. Use x slot for y.
   139  		u.y.setIndex(j, ti)
   140  	default:
   141  		// Either the type parameter for y has an inferred type, or neither type
   142  		// parameter has an inferred type. In either case, use y slot for x.
   143  		u.x.setIndex(i, tj)
   144  	}
   145  	return true
   146  }
   147  
   148  // If typ is a type parameter of d, index returns the type parameter index.
   149  // Otherwise, the result is < 0.
   150  func (d *tparamsList) index(typ Type) int {
   151  	if t, ok := typ.(*_TypeParam); ok {
   152  		if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t {
   153  			return i
   154  		}
   155  	}
   156  	return -1
   157  }
   158  
   159  // setIndex sets the type slot index for the i'th type parameter
   160  // (and all its joined parameters) to tj. The type parameter
   161  // must have a (possibly nil) type slot associated with it.
   162  func (d *tparamsList) setIndex(i, tj int) {
   163  	ti := d.indices[i]
   164  	assert(ti != 0 && tj != 0)
   165  	for k, tk := range d.indices {
   166  		if tk == ti {
   167  			d.indices[k] = tj
   168  		}
   169  	}
   170  }
   171  
   172  // at returns the type set for the i'th type parameter; or nil.
   173  func (d *tparamsList) at(i int) Type {
   174  	if ti := d.indices[i]; ti > 0 {
   175  		return d.unifier.types[ti-1]
   176  	}
   177  	return nil
   178  }
   179  
   180  // set sets the type typ for the i'th type parameter;
   181  // typ must not be nil and it must not have been set before.
   182  func (d *tparamsList) set(i int, typ Type) {
   183  	assert(typ != nil)
   184  	u := d.unifier
   185  	switch ti := d.indices[i]; {
   186  	case ti < 0:
   187  		u.types[-ti-1] = typ
   188  		d.setIndex(i, -ti)
   189  	case ti == 0:
   190  		u.types = append(u.types, typ)
   191  		d.indices[i] = len(u.types)
   192  	default:
   193  		panic("type already set")
   194  	}
   195  }
   196  
   197  // types returns the list of inferred types (via unification) for the type parameters
   198  // described by d, and an index. If all types were inferred, the returned index is < 0.
   199  // Otherwise, it is the index of the first type parameter which couldn't be inferred;
   200  // i.e., for which list[index] is nil.
   201  func (d *tparamsList) types() (list []Type, index int) {
   202  	list = make([]Type, len(d.tparams))
   203  	index = -1
   204  	for i := range d.tparams {
   205  		t := d.at(i)
   206  		list[i] = t
   207  		if index < 0 && t == nil {
   208  			index = i
   209  		}
   210  	}
   211  	return
   212  }
   213  
   214  func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
   215  	return x == y || u.nify(x, y, p)
   216  }
   217  
   218  // nify implements the core unification algorithm which is an
   219  // adapted version of Checker.identical0. For changes to that
   220  // code the corresponding changes should be made here.
   221  // Must not be called directly from outside the unifier.
   222  func (u *unifier) nify(x, y Type, p *ifacePair) bool {
   223  	// types must be expanded for comparison
   224  	x = expand(x)
   225  	y = expand(y)
   226  
   227  	if !u.exact {
   228  		// If exact unification is known to fail because we attempt to
   229  		// match a type name against an unnamed type literal, consider
   230  		// the underlying type of the named type.
   231  		// (Subtle: We use isNamed to include any type with a name (incl.
   232  		// basic types and type parameters. We use asNamed() because we only
   233  		// want *Named types.)
   234  		switch {
   235  		case !isNamed(x) && y != nil && asNamed(y) != nil:
   236  			return u.nify(x, under(y), p)
   237  		case x != nil && asNamed(x) != nil && !isNamed(y):
   238  			return u.nify(under(x), y, p)
   239  		}
   240  	}
   241  
   242  	// Cases where at least one of x or y is a type parameter.
   243  	switch i, j := u.x.index(x), u.y.index(y); {
   244  	case i >= 0 && j >= 0:
   245  		// both x and y are type parameters
   246  		if u.join(i, j) {
   247  			return true
   248  		}
   249  		// both x and y have an inferred type - they must match
   250  		return u.nifyEq(u.x.at(i), u.y.at(j), p)
   251  
   252  	case i >= 0:
   253  		// x is a type parameter, y is not
   254  		if tx := u.x.at(i); tx != nil {
   255  			return u.nifyEq(tx, y, p)
   256  		}
   257  		// otherwise, infer type from y
   258  		u.x.set(i, y)
   259  		return true
   260  
   261  	case j >= 0:
   262  		// y is a type parameter, x is not
   263  		if ty := u.y.at(j); ty != nil {
   264  			return u.nifyEq(x, ty, p)
   265  		}
   266  		// otherwise, infer type from x
   267  		u.y.set(j, x)
   268  		return true
   269  	}
   270  
   271  	// For type unification, do not shortcut (x == y) for identical
   272  	// types. Instead keep comparing them element-wise to unify the
   273  	// matching (and equal type parameter types). A simple test case
   274  	// where this matters is: func f[P any](a P) { f(a) } .
   275  
   276  	switch x := x.(type) {
   277  	case *Basic:
   278  		// Basic types are singletons except for the rune and byte
   279  		// aliases, thus we cannot solely rely on the x == y check
   280  		// above. See also comment in TypeName.IsAlias.
   281  		if y, ok := y.(*Basic); ok {
   282  			return x.kind == y.kind
   283  		}
   284  
   285  	case *Array:
   286  		// Two array types are identical if they have identical element types
   287  		// and the same array length.
   288  		if y, ok := y.(*Array); ok {
   289  			// If one or both array lengths are unknown (< 0) due to some error,
   290  			// assume they are the same to avoid spurious follow-on errors.
   291  			return (x.len < 0 || y.len < 0 || x.len == y.len) && u.nify(x.elem, y.elem, p)
   292  		}
   293  
   294  	case *Slice:
   295  		// Two slice types are identical if they have identical element types.
   296  		if y, ok := y.(*Slice); ok {
   297  			return u.nify(x.elem, y.elem, p)
   298  		}
   299  
   300  	case *Struct:
   301  		// Two struct types are identical if they have the same sequence of fields,
   302  		// and if corresponding fields have the same names, and identical types,
   303  		// and identical tags. Two embedded fields are considered to have the same
   304  		// name. Lower-case field names from different packages are always different.
   305  		if y, ok := y.(*Struct); ok {
   306  			if x.NumFields() == y.NumFields() {
   307  				for i, f := range x.fields {
   308  					g := y.fields[i]
   309  					if f.embedded != g.embedded ||
   310  						x.Tag(i) != y.Tag(i) ||
   311  						!f.sameId(g.pkg, g.name) ||
   312  						!u.nify(f.typ, g.typ, p) {
   313  						return false
   314  					}
   315  				}
   316  				return true
   317  			}
   318  		}
   319  
   320  	case *Pointer:
   321  		// Two pointer types are identical if they have identical base types.
   322  		if y, ok := y.(*Pointer); ok {
   323  			return u.nify(x.base, y.base, p)
   324  		}
   325  
   326  	case *Tuple:
   327  		// Two tuples types are identical if they have the same number of elements
   328  		// and corresponding elements have identical types.
   329  		if y, ok := y.(*Tuple); ok {
   330  			if x.Len() == y.Len() {
   331  				if x != nil {
   332  					for i, v := range x.vars {
   333  						w := y.vars[i]
   334  						if !u.nify(v.typ, w.typ, p) {
   335  							return false
   336  						}
   337  					}
   338  				}
   339  				return true
   340  			}
   341  		}
   342  
   343  	case *Signature:
   344  		// Two function types are identical if they have the same number of parameters
   345  		// and result values, corresponding parameter and result types are identical,
   346  		// and either both functions are variadic or neither is. Parameter and result
   347  		// names are not required to match.
   348  		// TODO(gri) handle type parameters or document why we can ignore them.
   349  		if y, ok := y.(*Signature); ok {
   350  			return x.variadic == y.variadic &&
   351  				u.nify(x.params, y.params, p) &&
   352  				u.nify(x.results, y.results, p)
   353  		}
   354  
   355  	case *_Sum:
   356  		// This should not happen with the current internal use of sum types.
   357  		panic("type inference across sum types not implemented")
   358  
   359  	case *Interface:
   360  		// Two interface types are identical if they have the same set of methods with
   361  		// the same names and identical function types. Lower-case method names from
   362  		// different packages are always different. The order of the methods is irrelevant.
   363  		if y, ok := y.(*Interface); ok {
   364  			// If identical0 is called (indirectly) via an external API entry point
   365  			// (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in
   366  			// that case, interfaces are expected to be complete and lazy completion
   367  			// here is not needed.
   368  			if u.check != nil {
   369  				u.check.completeInterface(token.NoPos, x)
   370  				u.check.completeInterface(token.NoPos, y)
   371  			}
   372  			a := x.allMethods
   373  			b := y.allMethods
   374  			if len(a) == len(b) {
   375  				// Interface types are the only types where cycles can occur
   376  				// that are not "terminated" via named types; and such cycles
   377  				// can only be created via method parameter types that are
   378  				// anonymous interfaces (directly or indirectly) embedding
   379  				// the current interface. Example:
   380  				//
   381  				//    type T interface {
   382  				//        m() interface{T}
   383  				//    }
   384  				//
   385  				// If two such (differently named) interfaces are compared,
   386  				// endless recursion occurs if the cycle is not detected.
   387  				//
   388  				// If x and y were compared before, they must be equal
   389  				// (if they were not, the recursion would have stopped);
   390  				// search the ifacePair stack for the same pair.
   391  				//
   392  				// This is a quadratic algorithm, but in practice these stacks
   393  				// are extremely short (bounded by the nesting depth of interface
   394  				// type declarations that recur via parameter types, an extremely
   395  				// rare occurrence). An alternative implementation might use a
   396  				// "visited" map, but that is probably less efficient overall.
   397  				q := &ifacePair{x, y, p}
   398  				for p != nil {
   399  					if p.identical(q) {
   400  						return true // same pair was compared before
   401  					}
   402  					p = p.prev
   403  				}
   404  				if debug {
   405  					assert(sort.IsSorted(byUniqueMethodName(a)))
   406  					assert(sort.IsSorted(byUniqueMethodName(b)))
   407  				}
   408  				for i, f := range a {
   409  					g := b[i]
   410  					if f.Id() != g.Id() || !u.nify(f.typ, g.typ, q) {
   411  						return false
   412  					}
   413  				}
   414  				return true
   415  			}
   416  		}
   417  
   418  	case *Map:
   419  		// Two map types are identical if they have identical key and value types.
   420  		if y, ok := y.(*Map); ok {
   421  			return u.nify(x.key, y.key, p) && u.nify(x.elem, y.elem, p)
   422  		}
   423  
   424  	case *Chan:
   425  		// Two channel types are identical if they have identical value types.
   426  		if y, ok := y.(*Chan); ok {
   427  			return (!u.exact || x.dir == y.dir) && u.nify(x.elem, y.elem, p)
   428  		}
   429  
   430  	case *Named:
   431  		// Two named types are identical if their type names originate
   432  		// in the same type declaration.
   433  		// if y, ok := y.(*Named); ok {
   434  		// 	return x.obj == y.obj
   435  		// }
   436  		if y, ok := y.(*Named); ok {
   437  			// TODO(gri) This is not always correct: two types may have the same names
   438  			//           in the same package if one of them is nested in a function.
   439  			//           Extremely unlikely but we need an always correct solution.
   440  			if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
   441  				assert(len(x.targs) == len(y.targs))
   442  				for i, x := range x.targs {
   443  					if !u.nify(x, y.targs[i], p) {
   444  						return false
   445  					}
   446  				}
   447  				return true
   448  			}
   449  		}
   450  
   451  	case *_TypeParam:
   452  		// Two type parameters (which are not part of the type parameters of the
   453  		// enclosing type as those are handled in the beginning of this function)
   454  		// are identical if they originate in the same declaration.
   455  		return x == y
   456  
   457  	// case *instance:
   458  	//	unreachable since types are expanded
   459  
   460  	case nil:
   461  		// avoid a crash in case of nil type
   462  
   463  	default:
   464  		u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams)
   465  		unreachable()
   466  	}
   467  
   468  	return false
   469  }
   470  

View as plain text