GoPLS Viewer

Home|gopls/refactor/satisfy/find_test.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.
4
5package satisfy_test
6
7import (
8    "fmt"
9    "go/ast"
10    "go/importer"
11    "go/parser"
12    "go/token"
13    "go/types"
14    "reflect"
15    "sort"
16    "testing"
17
18    "golang.org/x/tools/internal/typeparams"
19    "golang.org/x/tools/refactor/satisfy"
20)
21
22// This test exercises various operations on core types of type parameters.
23// (It also provides pretty decent coverage of the non-generic operations.)
24func TestGenericCoreOperations(t *testing.T) {
25    if !typeparams.Enabled {
26        t.Skip("!typeparams.Enabled")
27    }
28
29    const src = `package foo
30
31import "unsafe"
32
33type I interface { f() }
34
35type impl struct{}
36func (impl) f() {}
37
38// A big pile of single-serving types that implement I.
39type A struct{impl}
40type B struct{impl}
41type C struct{impl}
42type D struct{impl}
43type E struct{impl}
44type F struct{impl}
45type G struct{impl}
46type H struct{impl}
47type J struct{impl}
48type K struct{impl}
49type L struct{impl}
50type M struct{impl}
51type N struct{impl}
52type O struct{impl}
53type P struct{impl}
54type Q struct{impl}
55type R struct{impl}
56type S struct{impl}
57type T struct{impl}
58type U struct{impl}
59type V struct{impl}
60
61type Generic[T any] struct{impl}
62func (Generic[T]) g(T) {}
63
64type GI[T any] interface{
65    g(T)
66}
67
68func _[Slice interface{ []I }](s Slice) Slice {
69    s[0] = L{} // I <- L
70    return append(s, A{}) // I <- A
71}
72
73func _[Func interface{ func(I) B }](fn Func) {
74    b := fn(C{}) // I <- C
75    var _ I = b // I <- B
76}
77
78func _[Chan interface{ chan D }](ch Chan) {
79    var i I
80    for i = range ch {} // I <- D
81    _ = i
82}
83
84func _[Chan interface{ chan E }](ch Chan) {
85    var _ I = <-ch // I <- E
86}
87
88func _[Chan interface{ chan I }](ch Chan) {
89    ch <- F{} // I <- F
90}
91
92func _[Map interface{ map[G]H }](m Map) {
93    var k, v I
94    for k, v = range m {} // I <- G, I <- H
95    _, _ = k, v
96}
97
98func _[Map interface{ map[I]K }](m Map) {
99    var _ I = m[J{}] // I <- J, I <- K
100    delete(m, R{}) // I <- R
101    _, _ = m[J{}]
102}
103
104func _[Array interface{ [1]I }](a Array) {
105    a[0] = M{} // I <- M
106}
107
108func _[Array interface{ [1]N }](a Array) {
109    var _ I = a[0] // I <- N
110}
111
112func _[Array interface{ [1]O }](a Array) {
113    var v I
114    for _, v = range a {} // I <- O
115    _ = v
116}
117
118func _[ArrayPtr interface{ *[1]P }](a ArrayPtr) {
119    var v I
120    for _, v = range a {} // I <- P
121    _ = v
122}
123
124func _[Slice interface{ []Q }](s Slice) {
125    var v I
126    for _, v = range s {} // I <- Q
127    _ = v
128}
129
130func _[Func interface{ func() (S, bool) }](fn Func) {
131    var i I
132    i, _ = fn() // I <- S
133    _ = i
134}
135
136func _() I {
137    var _ I = T{} // I <- T
138    var _ I = Generic[T]{} // I <- Generic[T]
139    var _ I = Generic[string]{} // I <- Generic[string]
140    return U{} // I <- U
141}
142
143var _ GI[string] = Generic[string]{} //  GI[string] <- Generic[string]
144
145// universally quantified constraints:
146// the type parameter may appear on the left, the right, or both sides.
147
148func  _[T any](g Generic[T]) GI[T] {
149    return g // GI[T] <- Generic[T]
150}
151
152func  _[T any]() {
153    type GI2[T any] interface{ g(string) }
154    var _ GI2[T] = Generic[string]{} // GI2[T] <- Generic[string]
155}
156
157type Gen2[T any] struct{}
158func (f Gen2[T]) g(string) { global = f } // GI[string] <- Gen2[T]
159
160var global GI[string]
161
162func _() {
163    var x [3]V
164    // golang/go#56227: the finder should visit calls in the unsafe package.
165    _ = unsafe.Slice(&x[0], func() int { var _ I = x[0]; return 3 }()) // I <- V
166}
167`
168    got := constraints(tsrc)
169    want := []string{
170        "p.GI2[T] <- p.Generic[string]"// implicitly "forall T" quantified
171        "p.GI[T] <- p.Generic[T]",       // implicitly "forall T" quantified
172        "p.GI[string] <- p.Gen2[T]",     // implicitly "forall T" quantified
173        "p.GI[string] <- p.Generic[string]",
174        "p.I <- p.A",
175        "p.I <- p.B",
176        "p.I <- p.C",
177        "p.I <- p.D",
178        "p.I <- p.E",
179        "p.I <- p.F",
180        "p.I <- p.G",
181        "p.I <- p.Generic[p.T]",
182        "p.I <- p.Generic[string]",
183        "p.I <- p.H",
184        "p.I <- p.J",
185        "p.I <- p.K",
186        "p.I <- p.L",
187        "p.I <- p.M",
188        "p.I <- p.N",
189        "p.I <- p.O",
190        "p.I <- p.P",
191        "p.I <- p.Q",
192        "p.I <- p.R",
193        "p.I <- p.S",
194        "p.I <- p.T",
195        "p.I <- p.U",
196        "p.I <- p.V",
197    }
198    if !reflect.DeepEqual(gotwant) {
199        t.Fatalf("found unexpected constraints: got %s, want %s"gotwant)
200    }
201}
202
203func constraints(t *testing.Tsrc string) []string {
204    // parse
205    fset := token.NewFileSet()
206    ferr := parser.ParseFile(fset"p.go"src0)
207    if err != nil {
208        t.Fatal(err// parse error
209    }
210    files := []*ast.File{f}
211
212    // type-check
213    info := &types.Info{
214        Types:      make(map[ast.Expr]types.TypeAndValue),
215        Defs:       make(map[*ast.Ident]types.Object),
216        Uses:       make(map[*ast.Ident]types.Object),
217        Implicits:  make(map[ast.Node]types.Object),
218        Scopes:     make(map[ast.Node]*types.Scope),
219        Selectionsmake(map[*ast.SelectorExpr]*types.Selection),
220    }
221    typeparams.InitInstanceInfo(info)
222    conf := types.Config{
223        Importerimporter.Default(),
224    }
225    if _err := conf.Check("p"fsetfilesinfo); err != nil {
226        t.Fatal(err// type error
227    }
228
229    // gather constraints
230    var finder satisfy.Finder
231    finder.Find(infofiles)
232    var constraints []string
233    for c := range finder.Result {
234        constraints = append(constraintsfmt.Sprintf("%v <- %v"c.LHSc.RHS))
235    }
236    sort.Strings(constraints)
237    return constraints
238}
239
MembersX
constraints.t
constraints.fset
constraints.f
constraints.info
constraints.constraints
importer
testing
TestGenericCoreOperations.t
TestGenericCoreOperations.src
TestGenericCoreOperations.got
TestGenericCoreOperations.want
constraints.err
parser
satisfy
constraints.finder
constraints.RangeStmt_5016.c
reflect
constraints.files
constraints
constraints.src
constraints.conf
constraints._
sort
TestGenericCoreOperations
Members
X