1
0
mirror of https://github.com/golang/go synced 2024-07-08 12:18:55 +00:00
go/test/typeparam/typelist.go
Robert Griesemer 0807986fe6 go/types, types2: correctly consider ~ (tilde) in constraint type inference
When doing constraint type inference, we must consider whether the
constraint's core type is precise (no tilde) or imprecise (tilde,
or not a single specific type). In the latter case, we cannot infer
an unknown type argument from the (imprecise) core type because there
are infinitely many possible types. For instance, given

        [E ~byte]

if we don't know E, we cannot infer that E must be byte (it could be
myByte, etc.). On the other hand, if we do know the type argument,
say for S in this example:

        [S ~[]E, E any]

we must consider the underlying type of S when matching against ~[]E
because we have a tilde.

Because constraint type inference may infer type arguments that were
not eligible initially (because they were unknown and the core type
is imprecise), we must iterate the process until nothing changes any-
more. For instance, given

        [S ~[]E, M ~map[string]S, E any]

where we initially only know the type argument for M, we must ignore
S (and E) at first. After one iteration of constraint type inference,
S is known at which point we can infer E as well.

The change is large-ish but the actual functional changes are small:

- There's a new method "unknowns" to determine the number of as of yet
  unknown type arguments.

- The adjCoreType function has been adjusted to also return tilde
  and single-type information. This is now conveniently returned
  as (*term, bool), and the function has been renamed to coreTerm.

- The original constraint type inference loop has been adjusted to
  consider tilde information.

- This adjusted original constraint type inference loop has been
  nested in another loop for iteration, together with some minimal
  logic to control termination.

The remaining changes are modifications to tests:

- There's a substantial new test for this issue.

- Several existing test cases were adjusted to accomodate the
  fact that they inferred incorrect types: tildes have been
  removed throughout. Most of these tests are for pathological
  cases.

- A couple of tests were adjusted where there was a difference
  between the go/types and types2 version.

Fixes #51229.

Change-Id: If0bf5fb70ec22913b5a2da89adbf8a27fbc921d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/387977
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-03-01 23:48:58 +00:00

139 lines
3.2 KiB
Go

// compile
// 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 file tests type lists & constraints with core types.
// Note: This test has been adjusted to use the new
// type set notation rather than type lists.
package p
// Assignability of an unnamed pointer type to a type parameter that
// has a matching underlying type.
func _[T interface{}, PT interface{ ~*T }](x T) PT {
return &x
}
// Indexing of generic types containing type parameters in their type list:
func at[T interface{ ~[]E }, E any](x T, i int) E {
return x[i]
}
// A generic type inside a function acts like a named type. Its underlying
// type is itself, its "operational type" is defined by the type list in
// the tybe bound, if any.
func _[T interface{ ~int }](x T) {
var _ int = int(x)
var _ T = 42
var _ T = T(myint(42))
}
// TODO: put this type declaration back inside the above function when issue 47631 is fixed.
type myint int
// Indexing a generic type which has a an array as core type.
func _[T interface{ ~[10]int }](x T) {
_ = x[9] // ok
}
// Dereference of a generic type which has a pointer as core type.
func _[T interface{ ~*int }](p T) int {
return *p
}
// Channel send and receive on a generic type which has a channel as core type.
func _[T interface{ ~chan int }](ch T) int {
// This would deadlock if executed (but ok for a compile test)
ch <- 0
return <-ch
}
// Calling of a generic type which has a function as core type.
func _[T interface{ ~func() }](f T) {
f()
go f()
}
// Same, but function has a parameter and return value.
func _[T interface{ ~func(string) int }](f T) int {
return f("hello")
}
// Map access of a generic type which has a map as core type.
func _[V any, T interface{ ~map[string]V }](p T) V {
return p["test"]
}
// Testing partial and full type inference, including the case where the types can
// be inferred without needing the types of the function arguments.
// Cannot embed stand-alone type parameters. Disabled for now.
/*
func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D)
func f0x() {
f := f0[string]
f("a", "b", "c", "d")
f0("a", "b", "c", "d")
}
func f1[A any, B interface{type A}](A, B)
func f1x() {
f := f1[int]
f(int(0), int(0))
f1(int(0), int(0))
f(0, 0)
f1(0, 0)
}
*/
func f2[A any, B interface{ []A }](_ A, _ B) {}
func f2x() {
f := f2[byte]
f(byte(0), []byte{})
f2(byte(0), []byte{})
f(0, []byte{})
// f2(0, []byte{}) - this one doesn't work
}
// Cannot embed stand-alone type parameters. Disabled for now.
/*
func f3[A any, B interface{type C}, C interface{type *A}](a A, _ B, c C)
func f3x() {
f := f3[int]
var x int
f(x, &x, &x)
f3(x, &x, &x)
}
*/
func f4[A any, B interface{ []C }, C interface{ *A }](_ A, _ B, c C) {}
func f4x() {
f := f4[int]
var x int
f(x, []*int{}, &x)
f4(x, []*int{}, &x)
}
func f5[A interface {
struct {
b B
c C
}
}, B any, C interface{ *B }](x B) A {
panic(0)
}
func f5x() {
x := f5(1.2)
var _ float64 = x.b
var _ float64 = *x.c
}
func f6[A any, B interface{ ~struct{ f []A } }](B) A { panic(0) }
func f6x() {
x := f6(struct{ f []string }{})
var _ string = x
}