Source file
src/go/types/object_test.go
1
2
3
4
5 package types_test
6
7 import (
8 "fmt"
9 "internal/testenv"
10 "strings"
11 "testing"
12
13 . "go/types"
14 )
15
16 func TestIsAlias(t *testing.T) {
17 check := func(obj *TypeName, want bool) {
18 if got := obj.IsAlias(); got != want {
19 t.Errorf("%v: got IsAlias = %v; want %v", obj, got, want)
20 }
21 }
22
23
24 check(Unsafe.Scope().Lookup("Pointer").(*TypeName), false)
25 for _, name := range Universe.Names() {
26 if obj, _ := Universe.Lookup(name).(*TypeName); obj != nil {
27 check(obj, name == "any" || name == "byte" || name == "rune")
28 }
29 }
30
31
32 pkg := NewPackage("p", "p")
33 t1 := NewTypeName(nopos, pkg, "t1", nil)
34 n1 := NewNamed(t1, new(Struct), nil)
35 t5 := NewTypeName(nopos, pkg, "t5", nil)
36 NewTypeParam(t5, nil)
37 for _, test := range []struct {
38 name *TypeName
39 alias bool
40 }{
41 {NewTypeName(nopos, nil, "t0", nil), false},
42 {NewTypeName(nopos, pkg, "t0", nil), false},
43 {t1, false},
44 {NewTypeName(nopos, nil, "t2", NewInterfaceType(nil, nil)), true},
45 {NewTypeName(nopos, pkg, "t3", n1), true},
46 {NewTypeName(nopos, nil, "t4", Typ[Int32]), true},
47 {NewTypeName(nopos, nil, "int32", Typ[Int32]), false},
48 {NewTypeName(nopos, pkg, "int32", Typ[Int32]), true},
49 {NewTypeName(nopos, nil, "rune", Typ[Rune]), true},
50 {t5, false},
51 } {
52 check(test.name, test.alias)
53 }
54 }
55
56
57
58 func TestEmbeddedMethod(t *testing.T) {
59 const src = `package p; type I interface { error }`
60 pkg := mustTypecheck(src, nil, nil)
61
62
63 eface := Universe.Lookup("error")
64 orig, _, _ := LookupFieldOrMethod(eface.Type(), false, nil, "Error")
65 if orig == nil {
66 t.Fatalf("original error.Error not found")
67 }
68
69
70 iface := pkg.Scope().Lookup("I")
71 embed, _, _ := LookupFieldOrMethod(iface.Type(), false, nil, "Error")
72 if embed == nil {
73 t.Fatalf("embedded error.Error not found")
74 }
75
76
77 if orig != embed {
78 t.Fatalf("%s (%p) != %s (%p)", orig, orig, embed, embed)
79 }
80 }
81
82 var testObjects = []struct {
83 src string
84 obj string
85 want string
86 alias bool
87 }{
88 {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader", false},
89
90 {"const c = 1.2", "c", "const p.c untyped float", false},
91 {"const c float64 = 3.14", "c", "const p.c float64", false},
92
93 {"type t struct{f int}", "t", "type p.t struct{f int}", false},
94 {"type t func(int)", "t", "type p.t func(int)", false},
95 {"type t[P any] struct{f P}", "t", "type p.t[P any] struct{f P}", false},
96 {"type t[P any] struct{f P}", "t.P", "type parameter P any", false},
97 {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C", false},
98
99 {"type t = struct{f int}", "t", "type p.t = struct{f int}", false},
100 {"type t = func(int)", "t", "type p.t = func(int)", false},
101 {"type A = B; type B = int", "A", "type p.A = p.B", true},
102 {"type A[P ~int] = struct{}", "A", "type p.A[P ~int] = struct{}", true},
103
104 {"var v int", "v", "var p.v int", false},
105
106 {"func f(int) string", "f", "func p.f(int) string", false},
107 {"func g[P any](x P){}", "g", "func p.g[P any](x P)", false},
108 {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}", false},
109 {"", "any", "type any = interface{}", false},
110 }
111
112 func TestObjectString(t *testing.T) {
113 testenv.MustHaveGoBuild(t)
114
115 for i, test := range testObjects {
116 t.Run(fmt.Sprint(i), func(t *testing.T) {
117 if test.alias {
118 revert := setGOEXPERIMENT("aliastypeparams")
119 defer revert()
120 t.Setenv("GODEBUG", "gotypesalias=1")
121 }
122
123 src := "package p; " + test.src
124 pkg, err := typecheck(src, nil, nil)
125 if err != nil {
126 t.Fatalf("%s: %s", src, err)
127 }
128
129 names := strings.Split(test.obj, ".")
130 if len(names) != 1 && len(names) != 2 {
131 t.Fatalf("%s: invalid object path %s", test.src, test.obj)
132 }
133
134 var obj Object
135 for s := pkg.Scope(); s != nil && obj == nil; s = s.Parent() {
136 obj = s.Lookup(names[0])
137 }
138 if obj == nil {
139 t.Fatalf("%s: %s not found", test.src, names[0])
140 }
141
142 if len(names) == 2 {
143 if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok {
144 obj = lookupTypeParamObj(typ.TypeParams(), names[1])
145 if obj == nil {
146 t.Fatalf("%s: %s not found", test.src, test.obj)
147 }
148 } else {
149 t.Fatalf("%s: %s has no type parameters", test.src, names[0])
150 }
151 }
152
153 if got := obj.String(); got != test.want {
154 t.Errorf("%s: got %s, want %s", test.src, got, test.want)
155 }
156 })
157 }
158 }
159
160 func lookupTypeParamObj(list *TypeParamList, name string) Object {
161 for i := 0; i < list.Len(); i++ {
162 tpar := list.At(i)
163 if tpar.Obj().Name() == name {
164 return tpar.Obj()
165 }
166 }
167 return nil
168 }
169
View as plain text