package gotypesimport ()// WalkNamed visits every named type reachable from t, invoking visit for each type// name. It does not descend into a type parameter's constraint; a caller that needs// the constraint walks it separately. When visit returns false for a name, the walk does// not descend into that name's type arguments (it prunes below the node); it// still visits the rest of the tree, so this controls descent, not whole-walk// termination. A caller that wants to stop entirely self-guards inside visit.func ( types.Type, func(*types.TypeName) bool) {walkNamed(, &Set[types.Type]{}, )}// walkNamed is WalkNamed's recursion, threading the cycle-guard seen set that the// exported entry point seeds fresh.func ( types.Type, *Set[types.Type], func(*types.TypeName) bool) {// Rendering names an alias, not its expansion, so the alias's own name is // what reachability must judge, and it is judged before the seen check: // the seen set keys on types.Identical, under which an alias equals its // target, so whichever spelling were walked first would swallow the other // (an exported alias hiding its unexported target, or vice versa). Aliases // bypass the dedup entirely; they cannot cycle (the type checker rejects // alias cycles), so the walk still covers only the finite spelling tree. // Only the rendered type arguments are walked, never Unalias(u).if , := .(*types.Alias); {if !(.Obj()) {return }if := .TypeArgs(); != nil {for := range .Types() { (, , ) } }return }if !.Add() {return }switch u := .(type) {case *types.Named:if !(.Obj()) {return }if := .TypeArgs(); != nil {for := range .Types() { (, , ) } }case *types.Pointer: (.Elem(), , )case *types.Slice: (.Elem(), , )case *types.Array: (.Elem(), , )case *types.Chan: (.Elem(), , )case *types.Map: (.Key(), , ) (.Elem(), , )case *types.Signature:walkTuple(.Params(), , )walkTuple(.Results(), , )case *types.Struct:for := range .Fields() { (.Type(), , ) }case *types.Interface:for := range .EmbeddedTypes() { (, , ) }for := range .ExplicitMethods() { (.Type(), , ) }case *types.Union:for := range .Terms() { (.Type(), , ) }case *types.Basic:// A predeclared or basic type names no type; nothing to visit or descend.case *types.TypeParam:// constraints are handled separately for lifted paramsdefault:panic(fmt.Sprintf("plumb: WalkNamed: unhandled type kind %T", )) }}func ( *types.Tuple, *Set[types.Type], func(*types.TypeName) bool) {for := range .Variables() {walkNamed(.Type(), , ) }}// ContainsInvalid reports whether t mentions the invalid type anywhere, meaning// it failed to type-check and plumb must not render it.func ( types.Type) bool {returntypeContains(, &Set[types.Type]{}, func( types.Type) bool { , := .(*types.Basic)return && .Kind() == types.Invalid })}// ContainsTypeParam reports whether t mentions any type parameter anywhere:// the test for a pinning that cannot survive a resolution restart, since lifted// parameters are per-run objects.func ( types.Type) bool {returntypeContains(, &Set[types.Type]{}, func( types.Type) bool { , := .(*types.TypeParam)return })}// typeContains walks t (guarding against cycles) and reports whether pred holds// for any node. The switch is exhaustive over every types.Type kind: leaf kinds// terminate explicitly and any unhandled kind panics, never silently reports// false. A silent false here is precisely how an unrendered invalid type would// slip past ContainsInvalid and reach the emitter.func ( types.Type, *Set[types.Type], func(types.Type) bool) bool { = types.Unalias()if !.Add() {returnfalse }if () {returntrue }switch u := .(type) {case *types.Basic, *types.TypeParam:// Leaf types: nothing to descend into. A type parameter renders as its // name; its constraint is validated separately (see checks.go).returnfalsecase *types.Pointer:return (.Elem(), , )case *types.Slice:return (.Elem(), , )case *types.Array:return (.Elem(), , )case *types.Chan:return (.Elem(), , )case *types.Map:return (.Key(), , ) || (.Elem(), , )case *types.Named:if := .TypeArgs(); != nil {for := range .Types() {if (, , ) {returntrue } } }returnfalsecase *types.Signature:returntupleContains(.Params(), , ) || tupleContains(.Results(), , )case *types.Struct:for := range .Fields() {if (.Type(), , ) {returntrue } }returnfalsecase *types.Interface:for := range .EmbeddedTypes() {if (, , ) {returntrue } }for := range .ExplicitMethods() {if (.Type(), , ) {returntrue } }returnfalsecase *types.Union:for := range .Terms() {if (.Type(), , ) {returntrue } }returnfalsedefault:panic(fmt.Sprintf("plumb: typeContains: unhandled type kind %T", )) }}func ( *types.Tuple, *Set[types.Type], func(types.Type) bool) bool {for := range .Variables() {iftypeContains(.Type(), , ) {returntrue } }returnfalse}// universeNames is the set of predeclared identifiers, backing IsUniverseName.varuniverseNames = func() map[string]bool { := map[string]bool{}for , := rangetypes.Universe.Names() { [] = true }return}()// IsUniverseName reports whether name is a predeclared identifier.func ( string) bool { returnuniverseNames[] }
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)