mirror of
https://github.com/golang/go
synced 2024-11-26 05:07:59 -07:00
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 <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
760d3b2a16
commit
190cb937f7
13
src/cmd/compile/internal/types2/fixedbugs/issue45548.go2
Normal file
13
src/cmd/compile/internal/types2/fixedbugs/issue45548.go2
Normal file
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user