]> Cypherpunks.ru repositories - gostls13.git/blob - test/typeparam/nested.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / typeparam / nested.go
1 // run
2
3 // Copyright 2021 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // This test case stress tests a number of subtle cases involving
8 // nested type-parameterized declarations. At a high-level, it
9 // declares a generic function that contains a generic type
10 // declaration:
11 //
12 //      func F[A intish]() {
13 //              type T[B intish] struct{}
14 //
15 //              // store reflect.Type tuple (A, B, F[A].T[B]) in tests
16 //      }
17 //
18 // It then instantiates this function with a variety of type arguments
19 // for A and B. Particularly tricky things like shadowed types.
20 //
21 // From this data it tests two things:
22 //
23 // 1. Given tuples (A, B, F[A].T[B]) and (A', B', F[A'].T[B']),
24 //    F[A].T[B] should be identical to F[A'].T[B'] iff (A, B) is
25 //    identical to (A', B').
26 //
27 // 2. A few of the instantiations are constructed to be identical, and
28 //    it tests that exactly these pairs are duplicated (by golden
29 //    output comparison to nested.out).
30 //
31 // In both cases, we're effectively using the compiler's existing
32 // runtime.Type handling (which is well tested) of type identity of A
33 // and B as a way to help bootstrap testing and validate its new
34 // runtime.Type handling of F[A].T[B].
35 //
36 // This isn't perfect, but it smoked out a handful of issues in
37 // gotypes2 and unified IR.
38
39 package main
40
41 import (
42         "fmt"
43         "reflect"
44 )
45
46 type test struct {
47         TArgs    [2]reflect.Type
48         Instance reflect.Type
49 }
50
51 var tests []test
52
53 type intish interface{ ~int }
54
55 type Int int
56 type GlobalInt = Int // allow access to global Int, even when shadowed
57
58 func F[A intish]() {
59         add := func(B, T interface{}) {
60                 tests = append(tests, test{
61                         TArgs: [2]reflect.Type{
62                                 reflect.TypeOf(A(0)),
63                                 reflect.TypeOf(B),
64                         },
65                         Instance: reflect.TypeOf(T),
66                 })
67         }
68
69         type Int int
70
71         type T[B intish] struct{}
72
73         add(int(0), T[int]{})
74         add(Int(0), T[Int]{})
75         add(GlobalInt(0), T[GlobalInt]{})
76         add(A(0), T[A]{}) // NOTE: intentionally dups with int and GlobalInt
77
78         type U[_ any] int
79         type V U[int]
80         type W V
81
82         add(U[int](0), T[U[int]]{})
83         add(U[Int](0), T[U[Int]]{})
84         add(U[GlobalInt](0), T[U[GlobalInt]]{})
85         add(U[A](0), T[U[A]]{}) // NOTE: intentionally dups with U[int] and U[GlobalInt]
86         add(V(0), T[V]{})
87         add(W(0), T[W]{})
88 }
89
90 func main() {
91         type Int int
92
93         F[int]()
94         F[Int]()
95         F[GlobalInt]()
96
97         type U[_ any] int
98         type V U[int]
99         type W V
100
101         F[U[int]]()
102         F[U[Int]]()
103         F[U[GlobalInt]]()
104         F[V]()
105         F[W]()
106
107         type X[A any] U[X[A]]
108
109         F[X[int]]()
110         F[X[Int]]()
111         F[X[GlobalInt]]()
112
113         for j, tj := range tests {
114                 for i, ti := range tests[:j+1] {
115                         if (ti.TArgs == tj.TArgs) != (ti.Instance == tj.Instance) {
116                                 fmt.Printf("FAIL: %d,%d: %s, but %s\n", i, j, eq(ti.TArgs, tj.TArgs), eq(ti.Instance, tj.Instance))
117                         }
118
119                         // The test is constructed so we should see a few identical types.
120                         // See "NOTE" comments above.
121                         if i != j && ti.Instance == tj.Instance {
122                                 fmt.Printf("%d,%d: %v\n", i, j, ti.Instance)
123                         }
124                 }
125         }
126 }
127
128 func eq(a, b interface{}) string {
129         op := "=="
130         if a != b {
131                 op = "!="
132         }
133         return fmt.Sprintf("%v %s %v", a, op, b)
134 }