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 go.dev/issue/48619, go.dev/issue/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
39 // A unifier maintains a list of type parameters and
40 // corresponding types inferred for each type parameter.
41 // A unifier is created by calling newUnifier.
43 // tparams is the initial list of type parameters provided.
44 // Only used to print/return types in reproducible order.
46 // handles maps each type parameter to its inferred type through
47 // an indirection *Type called (inferred type) "handle".
48 // Initially, each type parameter has its own, separate handle,
49 // with a nil (i.e., not yet inferred) type.
50 // After a type parameter P is unified with a type parameter Q,
51 // P and Q share the same handle (and thus type). This ensures
52 // that inferring the type for a given type parameter P will
53 // automatically infer the same type for all other parameters
54 // unified (joined) with P.
55 handles map[*TypeParam]*Type
56 depth int // recursion depth during unification
59 // newUnifier returns a new unifier initialized with the given type parameter
60 // and corresponding type argument lists. The type argument list may be shorter
61 // than the type parameter list, and it may contain nil types. Matching type
62 // parameters and arguments must have the same index.
63 func newUnifier(tparams []*TypeParam, targs []Type) *unifier {
64 assert(len(tparams) >= len(targs))
65 handles := make(map[*TypeParam]*Type, len(tparams))
66 // Allocate all handles up-front: in a correct program, all type parameters
67 // must be resolved and thus eventually will get a handle.
68 // Also, sharing of handles caused by unified type parameters is rare and
69 // so it's ok to not optimize for that case (and delay handle allocation).
70 for i, x := range tparams {
77 return &unifier{tparams, handles, 0}
80 // unify attempts to unify x and y and reports whether it succeeded.
81 // As a side-effect, types may be inferred for type parameters.
82 func (u *unifier) unify(x, y Type) bool {
83 return u.nify(x, y, nil)
86 func (u *unifier) tracef(format string, args ...interface{}) {
87 fmt.Println(strings.Repeat(". ", u.depth) + sprintf(nil, true, format, args...))
90 // String returns a string representation of the current mapping
91 // from type parameters to types.
92 func (u *unifier) String() string {
94 w := newTypeWriter(&buf, nil)
96 for i, x := range u.tparams {
108 // join unifies the given type parameters x and y.
109 // If both type parameters already have a type associated with them
110 // and they are not joined, join fails and returns false.
111 func (u *unifier) join(x, y *TypeParam) bool {
113 u.tracef("%s ⇄ %s", x, y)
115 switch hx, hy := u.handles[x], u.handles[y]; {
117 // Both type parameters already share the same handle. Nothing to do.
118 case *hx != nil && *hy != nil:
119 // Both type parameters have (possibly different) inferred types. Cannot join.
122 // Only type parameter x has an inferred type. Use handle of x.
124 // This case is treated like the default case.
126 // // Only type parameter y has an inferred type. Use handle of y.
127 // u.setHandle(x, hy)
129 // Neither type parameter has an inferred type. Use handle of y.
135 // asTypeParam returns x.(*TypeParam) if x is a type parameter recorded with u.
136 // Otherwise, the result is nil.
137 func (u *unifier) asTypeParam(x Type) *TypeParam {
138 if x, _ := x.(*TypeParam); x != nil {
139 if _, found := u.handles[x]; found {
146 // setHandle sets the handle for type parameter x
147 // (and all its joined type parameters) to h.
148 func (u *unifier) setHandle(x *TypeParam, h *Type) {
151 for y, hy := range u.handles {
158 // at returns the (possibly nil) type for type parameter x.
159 func (u *unifier) at(x *TypeParam) Type {
163 // set sets the type t for type parameter x;
164 // t must not be nil and it must not have been set before.
165 func (u *unifier) set(x *TypeParam, t Type) {
168 u.tracef("%s ➞ %s", x, t)
175 // unknowns returns the number of type parameters for which no type has been set yet.
176 func (u *unifier) unknowns() int {
178 for _, h := range u.handles {
186 // inferred returns the list of inferred types (via unification) for the type parameters
187 // recorded with u, and an index. If all types were inferred, the returned index is < 0.
188 // Otherwise, it is the index of the first type parameter which couldn't be inferred;
189 // i.e., for which list[index] is nil.
190 func (u *unifier) inferred() (list []Type, index int) {
191 list = make([]Type, len(u.tparams))
193 for i, x := range u.tparams {
196 if index < 0 && t == nil {
203 func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
204 return x == y || u.nify(x, y, p)
207 // nify implements the core unification algorithm which is an
208 // adapted version of Checker.identical. For changes to that
209 // code the corresponding changes should be made here.
210 // Must not be called directly from outside the unifier.
211 func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
213 u.tracef("%s ≡ %s", x, y)
216 // Stop gap for cases where unification fails.
217 if u.depth >= unificationDepthLimit {
219 u.tracef("depth %d >= %d", u.depth, unificationDepthLimit)
221 if panicAtUnificationDepthLimit {
222 panic("unification reached recursion depth limit")
229 if traceInference && !result {
230 u.tracef("%s ≢ %s", x, y)
234 // If exact unification is known to fail because we attempt to
235 // match a type name against an unnamed type literal, consider
236 // the underlying type of the named type.
237 // (We use !hasName to exclude any type with a name, including
238 // basic types and type parameters; the rest are unamed types.)
239 if nx, _ := x.(*Named); nx != nil && !hasName(y) {
241 u.tracef("under %s ≡ %s", nx, y)
243 return u.nify(nx.under(), y, p)
244 } else if ny, _ := y.(*Named); ny != nil && !hasName(x) {
246 u.tracef("%s ≡ under %s", x, ny)
248 return u.nify(x, ny.under(), p)
251 // Cases where at least one of x or y is a type parameter recorded with u.
252 switch px, py := u.asTypeParam(x), u.asTypeParam(y); {
253 case px != nil && py != nil:
254 // both x and y are type parameters
258 // both x and y have an inferred type - they must match
259 return u.nifyEq(u.at(px), u.at(py), p)
262 // x is a type parameter, y is not
263 if tx := u.at(px); tx != nil {
264 return u.nifyEq(tx, y, p)
266 // otherwise, infer type from y
271 // y is a type parameter, x is not
272 if ty := u.at(py); ty != nil {
273 return u.nifyEq(x, ty, p)
275 // otherwise, infer type from x
280 // If we get here and x or y is a type parameter, they are type parameters
281 // from outside our declaration list. Try to unify their core types, if any
282 // (see go.dev/issue/50755 for a test case).
283 if enableCoreTypeUnification {
284 if isTypeParam(x) && !hasName(y) {
285 // When considering the type parameter for unification
286 // we look at the adjusted core term (adjusted core type
287 // with tilde information).
288 // If the adjusted core type is a named type N; the
289 // corresponding core type is under(N).
290 // Since y doesn't have a name, unification will end up
291 // comparing under(N) to y, so we can just use the core
292 // type instead. And we can ignore the tilde because we
293 // already look at the underlying types on both sides
294 // and we have known types on both sides.
296 if cx := coreType(x); cx != nil {
298 u.tracef("core %s ≡ %s", x, y)
300 return u.nify(cx, y, p)
302 } else if isTypeParam(y) && !hasName(x) {
304 if cy := coreType(y); cy != nil {
306 u.tracef("%s ≡ core %s", x, y)
308 return u.nify(x, cy, p)
313 // For type unification, do not shortcut (x == y) for identical
314 // types. Instead keep comparing them element-wise to unify the
315 // matching (and equal type parameter types). A simple test case
316 // where this matters is: func f[P any](a P) { f(a) } .
318 switch x := x.(type) {
320 // Basic types are singletons except for the rune and byte
321 // aliases, thus we cannot solely rely on the x == y check
322 // above. See also comment in TypeName.IsAlias.
323 if y, ok := y.(*Basic); ok {
324 return x.kind == y.kind
328 // Two array types are identical if they have identical element types
329 // and the same array length.
330 if y, ok := y.(*Array); ok {
331 // If one or both array lengths are unknown (< 0) due to some error,
332 // assume they are the same to avoid spurious follow-on errors.
333 return (x.len < 0 || y.len < 0 || x.len == y.len) && u.nify(x.elem, y.elem, p)
337 // Two slice types are identical if they have identical element types.
338 if y, ok := y.(*Slice); ok {
339 return u.nify(x.elem, y.elem, p)
343 // Two struct types are identical if they have the same sequence of fields,
344 // and if corresponding fields have the same names, and identical types,
345 // and identical tags. Two embedded fields are considered to have the same
346 // name. Lower-case field names from different packages are always different.
347 if y, ok := y.(*Struct); ok {
348 if x.NumFields() == y.NumFields() {
349 for i, f := range x.fields {
351 if f.embedded != g.embedded ||
352 x.Tag(i) != y.Tag(i) ||
353 !f.sameId(g.pkg, g.name) ||
354 !u.nify(f.typ, g.typ, p) {
363 // Two pointer types are identical if they have identical base types.
364 if y, ok := y.(*Pointer); ok {
365 return u.nify(x.base, y.base, p)
369 // Two tuples types are identical if they have the same number of elements
370 // and corresponding elements have identical types.
371 if y, ok := y.(*Tuple); ok {
372 if x.Len() == y.Len() {
374 for i, v := range x.vars {
376 if !u.nify(v.typ, w.typ, p) {
386 // Two function types are identical if they have the same number of parameters
387 // and result values, corresponding parameter and result types are identical,
388 // and either both functions are variadic or neither is. Parameter and result
389 // names are not required to match.
390 // TODO(gri) handle type parameters or document why we can ignore them.
391 if y, ok := y.(*Signature); ok {
392 return x.variadic == y.variadic &&
393 u.nify(x.params, y.params, p) &&
394 u.nify(x.results, y.results, p)
398 // Two interface types are identical if they have the same set of methods with
399 // the same names and identical function types. Lower-case method names from
400 // different packages are always different. The order of the methods is irrelevant.
401 if y, ok := y.(*Interface); ok {
404 if xset.comparable != yset.comparable {
407 if !xset.terms.equal(yset.terms) {
412 if len(a) == len(b) {
413 // Interface types are the only types where cycles can occur
414 // that are not "terminated" via named types; and such cycles
415 // can only be created via method parameter types that are
416 // anonymous interfaces (directly or indirectly) embedding
417 // the current interface. Example:
419 // type T interface {
423 // If two such (differently named) interfaces are compared,
424 // endless recursion occurs if the cycle is not detected.
426 // If x and y were compared before, they must be equal
427 // (if they were not, the recursion would have stopped);
428 // search the ifacePair stack for the same pair.
430 // This is a quadratic algorithm, but in practice these stacks
431 // are extremely short (bounded by the nesting depth of interface
432 // type declarations that recur via parameter types, an extremely
433 // rare occurrence). An alternative implementation might use a
434 // "visited" map, but that is probably less efficient overall.
435 q := &ifacePair{x, y, p}
438 return true // same pair was compared before
443 assertSortedMethods(a)
444 assertSortedMethods(b)
446 for i, f := range a {
448 if f.Id() != g.Id() || !u.nify(f.typ, g.typ, q) {
457 // Two map types are identical if they have identical key and value types.
458 if y, ok := y.(*Map); ok {
459 return u.nify(x.key, y.key, p) && u.nify(x.elem, y.elem, p)
463 // Two channel types are identical if they have identical value types.
464 if y, ok := y.(*Chan); ok {
465 return u.nify(x.elem, y.elem, p)
469 // TODO(gri) This code differs now from the parallel code in Checker.identical. Investigate.
470 if y, ok := y.(*Named); ok {
471 xargs := x.TypeArgs().list()
472 yargs := y.TypeArgs().list()
474 if len(xargs) != len(yargs) {
478 // TODO(gri) This is not always correct: two types may have the same names
479 // in the same package if one of them is nested in a function.
480 // Extremely unlikely but we need an always correct solution.
481 if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
482 for i, x := range xargs {
483 if !u.nify(x, yargs[i], p) {
492 // Two type parameters (which are not part of the type parameters of the
493 // enclosing type as those are handled in the beginning of this function)
494 // are identical if they originate in the same declaration.
498 // avoid a crash in case of nil type
501 panic(sprintf(nil, true, "u.nify(%s, %s), u.tparams = %s", x, y, u.tparams))