Skip to content

Commit 190cb93

Browse files
committed
cmd/compile/internal/types2: fix type inference
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 <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 760d3b2 commit 190cb93

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
5+
package p
6+
7+
func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {}
8+
9+
func _() {
10+
f[*float64, *int](1, 2)
11+
f[*float64](1, 2)
12+
f(1, 2)
13+
}

src/cmd/compile/internal/types2/infer.go

+19
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,25 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty
451451
dirty = dirty[:n]
452452
}
453453

454+
// Once nothing changes anymore, we may still have type parameters left;
455+
// e.g., a structural constraint *P may match a type parameter Q but we
456+
// don't have any type arguments to fill in for *P or Q (issue #45548).
457+
// Don't let such inferences escape, instead nil them out.
458+
for i, typ := range types {
459+
if typ != nil && isParameterized(tparams, typ) {
460+
types[i] = nil
461+
}
462+
}
463+
464+
// update index
465+
index = -1
466+
for i, typ := range types {
467+
if typ == nil {
468+
index = i
469+
break
470+
}
471+
}
472+
454473
return
455474
}
456475

src/cmd/compile/internal/types2/unify.go

+18
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package types2
88

9+
import "bytes"
10+
911
// The unifier maintains two separate sets of type parameters x and y
1012
// which are used to resolve type parameters in the x and y arguments
1113
// provided to the unify call. For unidirectional unification, only
@@ -69,6 +71,22 @@ type tparamsList struct {
6971
indices []int // len(d.indices) == len(d.tparams)
7072
}
7173

74+
// String returns a string representation for a tparamsList. For debugging.
75+
func (d *tparamsList) String() string {
76+
var buf bytes.Buffer
77+
buf.WriteByte('[')
78+
for i, tname := range d.tparams {
79+
if i > 0 {
80+
buf.WriteString(", ")
81+
}
82+
writeType(&buf, tname.typ, nil, nil)
83+
buf.WriteString(": ")
84+
writeType(&buf, d.at(i), nil, nil)
85+
}
86+
buf.WriteByte(']')
87+
return buf.String()
88+
}
89+
7290
// init initializes d with the given type parameters.
7391
// The type parameters must be in the order in which they appear in their declaration
7492
// (this ensures that the tparams indices match the respective type parameter index).

0 commit comments

Comments
 (0)