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 ssa_test |
6 | |
7 | import ( |
8 | "go/ast" |
9 | "go/parser" |
10 | "go/token" |
11 | "go/types" |
12 | "testing" |
13 | |
14 | "golang.org/x/tools/internal/typeparams" |
15 | ) |
16 | |
17 | func TestCoreType(t *testing.T) { |
18 | if !typeparams.Enabled { |
19 | t.Skip("TestCoreType requires type parameters.") |
20 | } |
21 | |
22 | const source = ` |
23 | package P |
24 | |
25 | type Named int |
26 | |
27 | type A any |
28 | type B interface{~int} |
29 | type C interface{int} |
30 | type D interface{Named} |
31 | type E interface{~int|interface{Named}} |
32 | type F interface{~int|~float32} |
33 | type G interface{chan int|interface{chan int}} |
34 | type H interface{chan int|chan float32} |
35 | type I interface{chan<- int|chan int} |
36 | type J interface{chan int|chan<- int} |
37 | type K interface{<-chan int|chan int} |
38 | type L interface{chan int|<-chan int} |
39 | type M interface{chan int|chan Named} |
40 | type N interface{<-chan int|chan<- int} |
41 | type O interface{chan int|bool} |
42 | type P struct{ Named } |
43 | type Q interface{ Foo() } |
44 | type R interface{ Foo() ; Named } |
45 | type S interface{ Foo() ; ~int } |
46 | |
47 | type T interface{chan int|interface{chan int}|<-chan int} |
48 | ` |
49 | |
50 | fset := token.NewFileSet() |
51 | f, err := parser.ParseFile(fset, "hello.go", source, 0) |
52 | if err != nil { |
53 | t.Fatal(err) |
54 | } |
55 | |
56 | var conf types.Config |
57 | pkg, err := conf.Check("P", fset, []*ast.File{f}, nil) |
58 | if err != nil { |
59 | t.Fatal(err) |
60 | } |
61 | |
62 | for _, test := range []struct { |
63 | expr string // type expression of Named type |
64 | want string // expected core type (or "<nil>" if none) |
65 | }{ |
66 | {"Named", "int"}, // Underlying type is not interface. |
67 | {"A", "<nil>"}, // Interface has no terms. |
68 | {"B", "int"}, // Tilde term. |
69 | {"C", "int"}, // Non-tilde term. |
70 | {"D", "int"}, // Named term. |
71 | {"E", "int"}, // Identical underlying types. |
72 | {"F", "<nil>"}, // Differing underlying types. |
73 | {"G", "chan int"}, // Identical Element types. |
74 | {"H", "<nil>"}, // Element type int has differing underlying type to float32. |
75 | {"I", "chan<- int"}, // SendRecv followed by SendOnly |
76 | {"J", "chan<- int"}, // SendOnly followed by SendRecv |
77 | {"K", "<-chan int"}, // RecvOnly followed by SendRecv |
78 | {"L", "<-chan int"}, // SendRecv followed by RecvOnly |
79 | {"M", "<nil>"}, // Element type int is not *identical* to Named. |
80 | {"N", "<nil>"}, // Differing channel directions |
81 | {"O", "<nil>"}, // A channel followed by a non-channel. |
82 | {"P", "struct{P.Named}"}, // Embedded type. |
83 | {"Q", "<nil>"}, // interface type with no terms and functions |
84 | {"R", "int"}, // interface type with both terms and functions. |
85 | {"S", "int"}, // interface type with a tilde term |
86 | {"T", "<-chan int"}, // Prefix of 2 terms that are identical before switching to channel. |
87 | } { |
88 | // Eval() expr for its type. |
89 | tv, err := types.Eval(fset, pkg, 0, test.expr) |
90 | if err != nil { |
91 | t.Fatalf("Eval(%s) failed: %v", test.expr, err) |
92 | } |
93 | |
94 | ct := typeparams.CoreType(tv.Type) |
95 | var got string |
96 | if ct == nil { |
97 | got = "<nil>" |
98 | } else { |
99 | got = ct.String() |
100 | } |
101 | if got != test.want { |
102 | t.Errorf("CoreType(%s) = %v, want %v", test.expr, got, test.want) |
103 | } |
104 | } |
105 | } |
106 |
Members