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.
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
12 // func F[A intish]() {
13 // type T[B intish] struct{}
15 // // store reflect.Type tuple (A, B, F[A].T[B]) in tests
18 // It then instantiates this function with a variety of type arguments
19 // for A and B. Particularly tricky things like shadowed types.
21 // From this data it tests two things:
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').
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).
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].
36 // This isn't perfect, but it smoked out a handful of issues in
37 // gotypes2 and unified IR.
53 type intish interface{ ~int }
56 type GlobalInt = Int // allow access to global Int, even when shadowed
59 add := func(B, T interface{}) {
60 tests = append(tests, test{
61 TArgs: [2]reflect.Type{
65 Instance: reflect.TypeOf(T),
71 type T[B intish] struct{}
75 add(GlobalInt(0), T[GlobalInt]{})
76 add(A(0), T[A]{}) // NOTE: intentionally dups with int and GlobalInt
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]
107 type X[A any] U[X[A]]
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))
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)
128 func eq(a, b interface{}) string {
133 return fmt.Sprintf("%v %s %v", a, op, b)