1// Copyright 2021 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
5package types2_test
6
7import (
8	"bytes"
9	"cmd/compile/internal/syntax"
10	"cmd/compile/internal/types2"
11	"errors"
12	"fmt"
13	"strings"
14	"testing"
15)
16
17func checkMono(t *testing.T, body string) error {
18	src := "package x; import `unsafe`; var _ unsafe.Pointer;\n" + body
19	file, err := syntax.Parse(syntax.NewFileBase("x.go"), strings.NewReader(src), nil, nil, syntax.AllowGenerics)
20	if err != nil {
21		t.Fatal(err)
22	}
23	files := []*syntax.File{file}
24
25	var buf bytes.Buffer
26	conf := types2.Config{
27		Error:    func(err error) { fmt.Fprintln(&buf, err) },
28		Importer: defaultImporter(),
29	}
30	conf.Check("x", files, nil)
31	if buf.Len() == 0 {
32		return nil
33	}
34	return errors.New(strings.TrimRight(buf.String(), "\n"))
35}
36
37func TestMonoGood(t *testing.T) {
38	for i, good := range goods {
39		if err := checkMono(t, good); err != nil {
40			t.Errorf("%d: unexpected failure: %v", i, err)
41		}
42	}
43}
44
45func TestMonoBad(t *testing.T) {
46	for i, bad := range bads {
47		if err := checkMono(t, bad); err == nil {
48			t.Errorf("%d: unexpected success", i)
49		} else {
50			t.Log(err)
51		}
52	}
53}
54
55var goods = []string{
56	"func F[T any](x T) { F(x) }",
57	"func F[T, U, V any]() { F[U, V, T](); F[V, T, U]() }",
58	"type Ring[A, B, C any] struct { L *Ring[B, C, A]; R *Ring[C, A, B] }",
59	"func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte }",
60	"func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte; var _ U[int] }",
61	"type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[U[int]] }",
62	"func F[T any]() { type A = int; F[A]() }",
63}
64
65// TODO(mdempsky): Validate specific error messages and positioning.
66
67var bads = []string{
68	"func F[T any](x T) { F(&x) }",
69	"func F[T any]() { F[*T]() }",
70	"func F[T any]() { F[[]T]() }",
71	"func F[T any]() { F[[1]T]() }",
72	"func F[T any]() { F[chan T]() }",
73	"func F[T any]() { F[map[*T]int]() }",
74	"func F[T any]() { F[map[error]T]() }",
75	"func F[T any]() { F[func(T)]() }",
76	"func F[T any]() { F[func() T]() }",
77	"func F[T any]() { F[struct{ t T }]() }",
78	"func F[T any]() { F[interface{ t() T }]() }",
79	"type U[_ any] int; func F[T any]() { F[U[T]]() }",
80	"func F[T any]() { type U int; F[U]() }",
81	"func F[T any]() { type U int; F[*U]() }",
82	"type U[T any] int; func (U[T]) m() { var _ U[*T] }",
83	"type U[T any] int; func (*U[T]) m() { var _ U[*T] }",
84	"type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }",
85	"func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }",
86	"type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })",
87	"func F[T any]() { type A = *T; F[A]() }",
88	"type A[T any] struct { _ A[*T] }",
89}
90