go/test/typeparam/nested.go
Matthew Dempsky 49ade6b298 [dev.typeparams] test: add expected failure mechanism
This CL changes the existing excluded-test mechanism into a
known-failure mechanism instead. That is, it runs the test regardless,
but only reports if it failed (or succeeded) unexpectedly.

It also splits the known failures list into fine-grain failure lists
for types2, types2 w/ 32-bit target, -G=3, and unified.

Updates #46704.

Change-Id: I1213cbccf1bab6a92d9bfcf0d971a2554249bbff
Reviewed-on: https://go-review.googlesource.com/c/go/+/332551
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
2021-07-07 11:12:13 +00:00

135 lines
3 KiB
Go

// run -gcflags=-G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This test case stress tests a number of subtle cases involving
// nested type-parameterized declarations. At a high-level, it
// declares a generic function that contains a generic type
// declaration:
//
// func F[A intish]() {
// type T[B intish] struct{}
//
// // store reflect.Type tuple (A, B, F[A].T[B]) in tests
// }
//
// It then instantiates this function with a variety of type arguments
// for A and B. Particularly tricky things like shadowed types.
//
// From this data it tests two things:
//
// 1. Given tuples (A, B, F[A].T[B]) and (A', B', F[A'].T[B']),
// F[A].T[B] should be identical to F[A'].T[B'] iff (A, B) is
// identical to (A', B').
//
// 2. A few of the instantiations are constructed to be identical, and
// it tests that exactly these pairs are duplicated (by golden
// output comparison to nested.out).
//
// In both cases, we're effectively using the compiler's existing
// runtime.Type handling (which is well tested) of type identity of A
// and B as a way to help bootstrap testing and validate its new
// runtime.Type handling of F[A].T[B].
//
// This isn't perfect, but it smoked out a handful of issues in
// gotypes2 and unified IR.
package main
import (
"fmt"
"reflect"
)
type test struct {
TArgs [2]reflect.Type
Instance reflect.Type
}
var tests []test
type intish interface{ ~int }
type Int int
type GlobalInt = Int // allow access to global Int, even when shadowed
func F[A intish]() {
add := func(B, T interface{}) {
tests = append(tests, test{
TArgs: [2]reflect.Type{
reflect.TypeOf(A(0)),
reflect.TypeOf(B),
},
Instance: reflect.TypeOf(T),
})
}
type Int int
type T[B intish] struct{}
add(int(0), T[int]{})
add(Int(0), T[Int]{})
add(GlobalInt(0), T[GlobalInt]{})
add(A(0), T[A]{}) // NOTE: intentionally dups with int and GlobalInt
type U[_ any] int
type V U[int]
type W V
add(U[int](0), T[U[int]]{})
add(U[Int](0), T[U[Int]]{})
add(U[GlobalInt](0), T[U[GlobalInt]]{})
add(U[A](0), T[U[A]]{}) // NOTE: intentionally dups with U[int] and U[GlobalInt]
add(V(0), T[V]{})
add(W(0), T[W]{})
}
func main() {
type Int int
F[int]()
F[Int]()
F[GlobalInt]()
type U[_ any] int
type V U[int]
type W V
F[U[int]]()
F[U[Int]]()
F[U[GlobalInt]]()
F[V]()
F[W]()
type X[A any] U[X[A]]
F[X[int]]()
F[X[Int]]()
F[X[GlobalInt]]()
for j, tj := range tests {
for i, ti := range tests[:j+1] {
if (ti.TArgs == tj.TArgs) != (ti.Instance == tj.Instance) {
fmt.Printf("FAIL: %d,%d: %s, but %s\n", i, j, eq(ti.TArgs, tj.TArgs), eq(ti.Instance, tj.Instance))
}
// The test is constructed so we should see a few identical types.
// See "NOTE" comments above.
if i != j && ti.Instance == tj.Instance {
fmt.Printf("%d,%d: %v\n", i, j, ti.Instance)
}
}
}
}
func eq(a, b interface{}) string {
op := "=="
if a != b {
op = "!="
}
return fmt.Sprintf("%v %s %v", a, op, b)
}