]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: fix type inference
authorRobert Griesemer <gri@golang.org>
Tue, 20 Apr 2021 01:48:16 +0000 (18:48 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 21 Apr 2021 01:45:15 +0000 (01:45 +0000)
Don't let type parameters that are not filled in with concrete
type arguments escape from constraint type inference - such
inferred types are not "real".

While at it, implement a tparamsList.String method for debugging.

Fixes #45548.

Change-Id: I40f13ff7af08d0357a5c66234bfcdd0b7ed5fdd6
Reviewed-on: https://go-review.googlesource.com/c/go/+/311651
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/fixedbugs/issue45548.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/infer.go
src/cmd/compile/internal/types2/unify.go

diff --git a/src/cmd/compile/internal/types2/fixedbugs/issue45548.go2 b/src/cmd/compile/internal/types2/fixedbugs/issue45548.go2
new file mode 100644 (file)
index 0000000..b1e4249
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+package p
+
+func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {}
+
+func _() {
+       f[*float64, *int](1, 2)
+       f[*float64](1, 2)
+       f(1, 2)
+}
index 13a9ccda0c02b464513adefbc99c0f40fecfda7f..c136823fd8ecbd646ed8ec90306b8441049e536e 100644 (file)
@@ -451,6 +451,25 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty
                dirty = dirty[:n]
        }
 
+       // Once nothing changes anymore, we may still have type parameters left;
+       // e.g., a structural constraint *P may match a type parameter Q but we
+       // don't have any type arguments to fill in for *P or Q (issue #45548).
+       // Don't let such inferences escape, instead nil them out.
+       for i, typ := range types {
+               if typ != nil && isParameterized(tparams, typ) {
+                       types[i] = nil
+               }
+       }
+
+       // update index
+       index = -1
+       for i, typ := range types {
+               if typ == nil {
+                       index = i
+                       break
+               }
+       }
+
        return
 }
 
index d2ea2b952b095b7a5775afb126dd7ac832fcbe78..e1832bbb2a36232cd00a04e2e195ae51711938fe 100644 (file)
@@ -6,6 +6,8 @@
 
 package types2
 
+import "bytes"
+
 // The unifier maintains two separate sets of type parameters x and y
 // which are used to resolve type parameters in the x and y arguments
 // provided to the unify call. For unidirectional unification, only
@@ -69,6 +71,22 @@ type tparamsList struct {
        indices []int // len(d.indices) == len(d.tparams)
 }
 
+// String returns a string representation for a tparamsList. For debugging.
+func (d *tparamsList) String() string {
+       var buf bytes.Buffer
+       buf.WriteByte('[')
+       for i, tname := range d.tparams {
+               if i > 0 {
+                       buf.WriteString(", ")
+               }
+               writeType(&buf, tname.typ, nil, nil)
+               buf.WriteString(": ")
+               writeType(&buf, d.at(i), nil, nil)
+       }
+       buf.WriteByte(']')
+       return buf.String()
+}
+
 // init initializes d with the given type parameters.
 // The type parameters must be in the order in which they appear in their declaration
 // (this ensures that the tparams indices match the respective type parameter index).