...

Source file src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/parameterized.go

Documentation: cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert

     1  // Copyright 2022 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  package ifaceassert
     6  
     7  import (
     8  	"go/types"
     9  
    10  	"golang.org/x/tools/internal/typeparams"
    11  )
    12  
    13  // isParameterized reports whether typ contains any of the type parameters of tparams.
    14  //
    15  // NOTE: Adapted from go/types/infer.go. If that is exported in a future release remove this copy.
    16  func isParameterized(typ types.Type) bool {
    17  	w := tpWalker{
    18  		seen: make(map[types.Type]bool),
    19  	}
    20  	return w.isParameterized(typ)
    21  }
    22  
    23  type tpWalker struct {
    24  	seen map[types.Type]bool
    25  }
    26  
    27  func (w *tpWalker) isParameterized(typ types.Type) (res bool) {
    28  	// detect cycles
    29  	if x, ok := w.seen[typ]; ok {
    30  		return x
    31  	}
    32  	w.seen[typ] = false
    33  	defer func() {
    34  		w.seen[typ] = res
    35  	}()
    36  
    37  	switch t := typ.(type) {
    38  	case nil, *types.Basic: // TODO(gri) should nil be handled here?
    39  		break
    40  
    41  	case *types.Array:
    42  		return w.isParameterized(t.Elem())
    43  
    44  	case *types.Slice:
    45  		return w.isParameterized(t.Elem())
    46  
    47  	case *types.Struct:
    48  		for i, n := 0, t.NumFields(); i < n; i++ {
    49  			if w.isParameterized(t.Field(i).Type()) {
    50  				return true
    51  			}
    52  		}
    53  
    54  	case *types.Pointer:
    55  		return w.isParameterized(t.Elem())
    56  
    57  	case *types.Tuple:
    58  		n := t.Len()
    59  		for i := 0; i < n; i++ {
    60  			if w.isParameterized(t.At(i).Type()) {
    61  				return true
    62  			}
    63  		}
    64  
    65  	case *types.Signature:
    66  		// t.tparams may not be nil if we are looking at a signature
    67  		// of a generic function type (or an interface method) that is
    68  		// part of the type we're testing. We don't care about these type
    69  		// parameters.
    70  		// Similarly, the receiver of a method may declare (rather than
    71  		// use) type parameters, we don't care about those either.
    72  		// Thus, we only need to look at the input and result parameters.
    73  		return w.isParameterized(t.Params()) || w.isParameterized(t.Results())
    74  
    75  	case *types.Interface:
    76  		for i, n := 0, t.NumMethods(); i < n; i++ {
    77  			if w.isParameterized(t.Method(i).Type()) {
    78  				return true
    79  			}
    80  		}
    81  		terms, err := typeparams.InterfaceTermSet(t)
    82  		if err != nil {
    83  			panic(err)
    84  		}
    85  		for _, term := range terms {
    86  			if w.isParameterized(term.Type()) {
    87  				return true
    88  			}
    89  		}
    90  
    91  	case *types.Map:
    92  		return w.isParameterized(t.Key()) || w.isParameterized(t.Elem())
    93  
    94  	case *types.Chan:
    95  		return w.isParameterized(t.Elem())
    96  
    97  	case *types.Named:
    98  		list := t.TypeArgs()
    99  		for i, n := 0, list.Len(); i < n; i++ {
   100  			if w.isParameterized(list.At(i)) {
   101  				return true
   102  			}
   103  		}
   104  
   105  	case *types.TypeParam:
   106  		return true
   107  
   108  	default:
   109  		panic(t) // unreachable
   110  	}
   111  
   112  	return false
   113  }
   114  

View as plain text