GoPLS Viewer

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