GoPLS Viewer

Home|gopls/go/ssa/subst_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 ssa
6
7import (
8    "go/ast"
9    "go/parser"
10    "go/token"
11    "go/types"
12    "testing"
13
14    "golang.org/x/tools/internal/typeparams"
15)
16
17func TestSubst(t *testing.T) {
18    if !typeparams.Enabled {
19        return
20    }
21
22    const source = `
23package P
24
25type t0 int
26func (t0) f()
27type t1 interface{ f() }
28type t2 interface{ g() }
29type t3 interface{ ~int }
30
31func Fn0[T t1](x T) T {
32    x.f()
33    return x
34}
35
36type A[T any] [4]T
37type B[T any] []T
38type C[T, S any] []struct{s S; t T}
39type D[T, S any] *struct{s S; t *T}
40type E[T, S any] interface{ F() (T, S) }
41type F[K comparable, V any] map[K]V
42type G[T any] chan *T
43type H[T any] func() T
44type I[T any] struct{x, y, z int; t T}
45type J[T any] interface{ t1 }
46type K[T any] interface{ t1; F() T }
47type L[T any] interface{ F() T; J[T] }
48
49var _ L[int] = Fn0[L[int]](nil)
50`
51
52    fset := token.NewFileSet()
53    ferr := parser.ParseFile(fset"hello.go"source0)
54    if err != nil {
55        t.Fatal(err)
56    }
57
58    var conf types.Config
59    pkgerr := conf.Check("P"fset, []*ast.File{f}, nil)
60    if err != nil {
61        t.Fatal(err)
62    }
63
64    for _test := range []struct {
65        expr string   // type expression of Named parameterized type
66        args []string // type expressions of args for named
67        want string   // expected underlying value after substitution
68    }{
69        {"A", []string{"string"}, "[4]string"},
70        {"A", []string{"int"}, "[4]int"},
71        {"B", []string{"int"}, "[]int"},
72        {"B", []string{"int8"}, "[]int8"},
73        {"C", []string{"int8""string"}, "[]struct{s string; t int8}"},
74        {"C", []string{"string""int8"}, "[]struct{s int8; t string}"},
75        {"D", []string{"int16""string"}, "*struct{s string; t *int16}"},
76        {"E", []string{"int32""string"}, "interface{F() (int32, string)}"},
77        {"F", []string{"int64""string"}, "map[int64]string"},
78        {"G", []string{"uint64"}, "chan *uint64"},
79        {"H", []string{"uintptr"}, "func() uintptr"},
80        {"I", []string{"t0"}, "struct{x int; y int; z int; t P.t0}"},
81        {"J", []string{"t0"}, "interface{P.t1}"},
82        {"K", []string{"t0"}, "interface{F() P.t0; P.t1}"},
83        {"L", []string{"t0"}, "interface{F() P.t0; P.J[P.t0]}"},
84        {"L", []string{"L[t0]"}, "interface{F() P.L[P.t0]; P.J[P.L[P.t0]]}"},
85    } {
86        // Eval() expr for its type.
87        tverr := types.Eval(fsetpkg0test.expr)
88        if err != nil {
89            t.Fatalf("Eval(%s) failed: %v"test.exprerr)
90        }
91        // Eval() test.args[i] to get the i'th type arg.
92        var targs []types.Type
93        for _astr := range test.args {
94            tverr := types.Eval(fsetpkg0astr)
95            if err != nil {
96                t.Fatalf("Eval(%s) failed: %v"astrerr)
97            }
98            targs = append(targstv.Type)
99        }
100
101        T := tv.Type.(*types.Named)
102
103        subst := makeSubster(typeparams.NewContext(), typeparams.ForNamed(T), targstrue)
104        sub := subst.typ(T.Underlying())
105        if got := sub.String(); got != test.want {
106            t.Errorf("subst{%v->%v}.typ(%s) = %v, want %v"test.exprtest.argsT.Underlying(), gottest.want)
107        }
108    }
109}
110
MembersX
TestSubst.RangeStmt_1182.BlockStmt.RangeStmt_2504.BlockStmt.err
TestSubst.RangeStmt_1182.BlockStmt.sub
TestSubst.RangeStmt_1182.BlockStmt.got
TestSubst.t
TestSubst.RangeStmt_1182.BlockStmt.targs
TestSubst.RangeStmt_1182.test
TestSubst.RangeStmt_1182.BlockStmt.tv
TestSubst.RangeStmt_1182.BlockStmt.RangeStmt_2504.astr
TestSubst.RangeStmt_1182.BlockStmt.subst
TestSubst.source
TestSubst.err
TestSubst.RangeStmt_1182.BlockStmt.err
TestSubst.RangeStmt_1182.BlockStmt.RangeStmt_2504.BlockStmt.tv
TestSubst.f
TestSubst.conf
TestSubst.pkg
TestSubst
TestSubst.fset
Members
X