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