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.
5 // This file implements type unification.
16 // Upper limit for recursion depth. Used to catch infinite recursions
17 // due to implementation issues (e.g., see issues #48619, #48656).
18 unificationDepthLimit = 50
20 // Whether to panic when unificationDepthLimit is reached.
21 // If disabled, a recursion depth overflow results in a (quiet)
22 // unification failure.
23 panicAtUnificationDepthLimit = true
25 // If enableCoreTypeUnification is set, unification will consider
26 // the core types, if any, of non-local (unbound) type parameters.
27 enableCoreTypeUnification = true
29 // If traceInference is set, unification will print a trace of its operation.
30 // Interpretation of trace:
31 // x ≡ y attempt to unify types x and y
32 // p ➞ y type parameter p is set to type y (p is inferred to be y)
33 // p ⇄ q type parameters p and q match (p is inferred to be q and vice versa)
34 // x ≢ y types x and y cannot be unified
35 // [p, q, ...] ➞ [x, y, ...] mapping from type parameters to types
36 traceInference = false
38 // If exactUnification is set, unification requires (named) types
39 // to match exactly. If it is not set, the underlying types are
40 // considered when unification is known to fail otherwise.
41 exactUnification = false
44 // A unifier maintains a list of type parameters and
45 // corresponding types inferred for each type parameter.
46 // A unifier is created by calling newUnifier.
48 // tparams is the initial list of type parameters provided.
49 // Only used to print/return types in reproducible order.
51 // handles maps each type parameter to its inferred type through
52 // an indirection *Type called (inferred type) "handle".
53 // Initially, each type parameter has its own, separate handle,
54 // with a nil (i.e., not yet inferred) type.
55 // After a type parameter P is unified with a type parameter Q,
56 // P and Q share the same handle (and thus type). This ensures
57 // that inferring the type for a given type parameter P will
58 // automatically infer the same type for all other parameters
59 // unified (joined) with P.
60 handles map[*TypeParam]*Type
61 depth int // recursion depth during unification
64 // newUnifier returns a new unifier initialized with the given type parameter list.
65 func newUnifier(tparams []*TypeParam) *unifier {
66 handles := make(map[*TypeParam]*Type, len(tparams))
67 // Allocate all handles up-front: in a correct program, all type parameters
68 // must be resolved and thus eventually will get a handle.
69 // Also, sharing of handles caused by unified type parameters is rare and
70 // so it's ok to not optimize for that case (and delay handle allocation).
71 for _, x := range tparams {
72 handles[x] = new(Type)
74 return &unifier{tparams, handles, 0}
77 // unify attempts to unify x and y and reports whether it succeeded.
78 // As a side-effect, types may be inferred for type parameters.
79 func (u *unifier) unify(x, y Type) bool {
80 return u.nify(x, y, nil)
83 func (u *unifier) tracef(format string, args ...interface{}) {
84 fmt.Println(strings.Repeat(". ", u.depth) + sprintf(nil, true, format, args...))
87 // String returns a string representation of the current mapping
88 // from type parameters to types.
89 func (u *unifier) String() string {
91 w := newTypeWriter(&buf, nil)
93 for i, x := range u.tparams {
105 // join unifies the given type parameters x and y.
106 // If both type parameters already have a type associated with them
107 // and they are not joined, join fails and returns false.
108 func (u *unifier) join(x, y *TypeParam) bool {
110 u.tracef("%s ⇄ %s", x, y)
112 switch hx, hy := u.handles[x], u.handles[y]; {
114 // Both type parameters already share the same handle. Nothing to do.
115 case *hx != nil && *hy != nil:
116 // Both type parameters have (possibly different) inferred types. Cannot join.
119 // Only type parameter x has an inferred type. Use handle of x.
121 // This case is treated like the default case.
123 // // Only type parameter y has an inferred type. Use handle of y.
124 // u.setHandle(x, hy)
126 // Neither type parameter has an inferred type. Use handle of y.
132 // asTypeParam returns x.(*TypeParam) if x is a type parameter recorded with u.
133 // Otherwise, the result is nil.
134 func (u *unifier) asTypeParam(x Type) *TypeParam {
135 if x, _ := x.(*TypeParam); x != nil {
136 if _, found := u.handles[x]; found {
143 // setHandle sets the handle for type parameter x
144 // (and all its joined type parameters) to h.
145 func (u *unifier) setHandle(x *TypeParam, h *Type) {
148 for y, hy := range u.handles {
155 // at returns the (possibly nil) type for type parameter x.
156 func (u *unifier) at(x *TypeParam) Type {
160 // set sets the type t for type parameter x;
161 // t must not be nil and it must not have been set before.
162 func (u *unifier) set(x *TypeParam, t Type) {
165 u.tracef("%s ➞ %s", x, t)
172 // unknowns returns the number of type parameters for which no type has been set yet.
173 func (u *unifier) unknowns() int {
175 for _, h := range u.handles {
183 // inferred returns the list of inferred types (via unification) for the type parameters
184 // recorded with u, and an index. If all types were inferred, the returned index is < 0.
185 // Otherwise, it is the index of the first type parameter which couldn't be inferred;
186 // i.e., for which list[index] is nil.
187 func (u *unifier) inferred() (list []Type, index int) {
188 list = make([]Type, len(u.tparams))
190 for i, x := range u.tparams {
193 if index < 0 && t == nil {
200 func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
201 return x == y || u.nify(x, y, p)
204 // nify implements the core unification algorithm which is an
205 // adapted version of Checker.identical. For changes to that
206 // code the corresponding changes should be made here.
207 // Must not be called directly from outside the unifier.
208 func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
210 u.tracef("%s ≡ %s", x, y)
213 // Stop gap for cases where unification fails.
214 if u.depth >= unificationDepthLimit {
216 u.tracef("depth %d >= %d", u.depth, unificationDepthLimit)
218 if panicAtUnificationDepthLimit {
219 panic("unification reached recursion depth limit")
226 if traceInference && !result {
227 u.tracef("%s ≢ %s", x, y)
231 if !exactUnification {
232 // If exact unification is known to fail because we attempt to
233 // match a type name against an unnamed type literal, consider
234 // the underlying type of the named type.
235 // (We use !hasName to exclude any type with a name, including
236 // basic types and type parameters; the rest are unamed types.)
237 if nx, _ := x.(*Named); nx != nil && !hasName(y) {
239 u.tracef("under %s ≡ %s", nx, y)
241 return u.nify(nx.under(), y, p)
242 } else if ny, _ := y.(*Named); ny != nil && !hasName(x) {
244 u.tracef("%s ≡ under %s", x, ny)
246 return u.nify(x, ny.under(), p)
250 // Cases where at least one of x or y is a type parameter recorded with u.
251 switch px, py := u.asTypeParam(x), u.asTypeParam(y); {
252 case px != nil && py != nil:
253 // both x and y are type parameters
257 // both x and y have an inferred type - they must match
258 return u.nifyEq(u.at(px), u.at(py), p)
261 // x is a type parameter, y is not
262 if tx := u.at(px); tx != nil {
263 return u.nifyEq(tx, y, p)
265 // otherwise, infer type from y
270 // y is a type parameter, x is not
271 if ty := u.at(py); ty != nil {
272 return u.nifyEq(x, ty, p)
274 // otherwise, infer type from x
279 // If we get here and x or y is a type parameter, they are type parameters
280 // from outside our declaration list. Try to unify their core types, if any
281 // (see go.dev/issue/50755 for a test case).
282 if enableCoreTypeUnification && !exactUnification {
283 if isTypeParam(x) && !hasName(y) {
284 // When considering the type parameter for unification
285 // we look at the adjusted core term (adjusted core type
286 // with tilde information).
287 // If the adjusted core type is a named type N; the
288 // corresponding core type is under(N). Since !exactUnification
289 // and y doesn't have a name, unification will end up
290 // comparing under(N) to y, so we can just use the core
291 // type instead. And we can ignore the tilde because we
292 // already look at the underlying types on both sides
293 // and we have known types on both sides.
295 if cx := coreType(x); cx != nil {
297 u.tracef("core %s ≡ %s", x, y)
299 return u.nify(cx, y, p)
301 } else if isTypeParam(y) && !hasName(x) {
303 if cy := coreType(y); cy != nil {
305 u.tracef("%s ≡ core %s", x, y)
307 return u.nify(x, cy, p)
312 // For type unification, do not shortcut (x == y) for identical
313 // types. Instead keep comparing them element-wise to unify the
314 // matching (and equal type parameter types). A simple test case
315 // where this matters is: func f[P any](a P) { f(a) } .
317 switch x := x.(type) {
319 // Basic types are singletons except for the rune and byte
320 // aliases, thus we cannot solely rely on the x == y check
321 // above. See also comment in TypeName.IsAlias.
322 if y, ok := y.(*Basic); ok {
323 return x.kind == y.kind
327 // Two array types are identical if they have identical element types
328 // and the same array length.
329 if y, ok := y.(*Array); ok {
330 // If one or both array lengths are unknown (< 0) due to some error,
331 // assume they are the same to avoid spurious follow-on errors.
332 return (x.len < 0 || y.len < 0 || x.len == y.len) && u.nify(x.elem, y.elem, p)
336 // Two slice types are identical if they have identical element types.
337 if y, ok := y.(*Slice); ok {
338 return u.nify(x.elem, y.elem, p)
342 // Two struct types are identical if they have the same sequence of fields,
343 // and if corresponding fields have the same names, and identical types,
344 // and identical tags. Two embedded fields are considered to have the same
345 // name. Lower-case field names from different packages are always different.
346 if y, ok := y.(*Struct); ok {
347 if x.NumFields() == y.NumFields() {
348 for i, f := range x.fields {
350 if f.embedded != g.embedded ||
351 x.Tag(i) != y.Tag(i) ||
352 !f.sameId(g.pkg, g.name) ||
353 !u.nify(f.typ, g.typ, p) {
362 // Two pointer types are identical if they have identical base types.
363 if y, ok := y.(*Pointer); ok {
364 return u.nify(x.base, y.base, p)
368 // Two tuples types are identical if they have the same number of elements
369 // and corresponding elements have identical types.
370 if y, ok := y.(*Tuple); ok {
371 if x.Len() == y.Len() {
373 for i, v := range x.vars {
375 if !u.nify(v.typ, w.typ, p) {
385 // Two function types are identical if they have the same number of parameters
386 // and result values, corresponding parameter and result types are identical,
387 // and either both functions are variadic or neither is. Parameter and result
388 // names are not required to match.
389 // TODO(gri) handle type parameters or document why we can ignore them.
390 if y, ok := y.(*Signature); ok {
391 return x.variadic == y.variadic &&
392 u.nify(x.params, y.params, p) &&
393 u.nify(x.results, y.results, p)
397 // Two interface types are identical if they have the same set of methods with
398 // the same names and identical function types. Lower-case method names from
399 // different packages are always different. The order of the methods is irrelevant.
400 if y, ok := y.(*Interface); ok {
403 if xset.comparable != yset.comparable {
406 if !xset.terms.equal(yset.terms) {
411 if len(a) == len(b) {
412 // Interface types are the only types where cycles can occur
413 // that are not "terminated" via named types; and such cycles
414 // can only be created via method parameter types that are
415 // anonymous interfaces (directly or indirectly) embedding
416 // the current interface. Example:
418 // type T interface {
422 // If two such (differently named) interfaces are compared,
423 // endless recursion occurs if the cycle is not detected.
425 // If x and y were compared before, they must be equal
426 // (if they were not, the recursion would have stopped);
427 // search the ifacePair stack for the same pair.
429 // This is a quadratic algorithm, but in practice these stacks
430 // are extremely short (bounded by the nesting depth of interface
431 // type declarations that recur via parameter types, an extremely
432 // rare occurrence). An alternative implementation might use a
433 // "visited" map, but that is probably less efficient overall.
434 q := &ifacePair{x, y, p}
437 return true // same pair was compared before
442 assertSortedMethods(a)
443 assertSortedMethods(b)
445 for i, f := range a {
447 if f.Id() != g.Id() || !u.nify(f.typ, g.typ, q) {
456 // Two map types are identical if they have identical key and value types.
457 if y, ok := y.(*Map); ok {
458 return u.nify(x.key, y.key, p) && u.nify(x.elem, y.elem, p)
462 // Two channel types are identical if they have identical value types.
463 if y, ok := y.(*Chan); ok {
464 return (!exactUnification || x.dir == y.dir) && u.nify(x.elem, y.elem, p)
468 // TODO(gri) This code differs now from the parallel code in Checker.identical. Investigate.
469 if y, ok := y.(*Named); ok {
470 xargs := x.TypeArgs().list()
471 yargs := y.TypeArgs().list()
473 if len(xargs) != len(yargs) {
477 // TODO(gri) This is not always correct: two types may have the same names
478 // in the same package if one of them is nested in a function.
479 // Extremely unlikely but we need an always correct solution.
480 if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
481 for i, x := range xargs {
482 if !u.nify(x, yargs[i], p) {
491 // Two type parameters (which are not part of the type parameters of the
492 // enclosing type as those are handled in the beginning of this function)
493 // are identical if they originate in the same declaration.
497 // avoid a crash in case of nil type
500 panic(sprintf(nil, true, "u.nify(%s, %s), u.tparams = %s", x, y, u.tparams))