mirror of
https://github.com/golang/go.git
synced 2025-05-31 23:25:39 +00:00
go/types, types2: ensure we have an interface before checking constraints
Due to delayed computation of constraint type sets it is possible that a type argument is checked against a constraint before that constraint has been wrapped into an implicit interface (if needed). When the type checker is about to check whether a type argument implements a constraint, it's always safe to force wrapping of a constraint in an implicit interface (if necessary) before doing the implements check. Also, use a better position for tracing output related to constraint type set computation. Fixes #51048. Change-Id: I52fecbf57814f09b62762452d7e17c2a230fdd59 Reviewed-on: https://go-review.googlesource.com/c/go/+/383834 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
49030c87e0
commit
7db75b368d
@ -135,6 +135,8 @@ func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool
|
||||
func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) (int, error) {
|
||||
smap := makeSubstMap(tparams, targs)
|
||||
for i, tpar := range tparams {
|
||||
// Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
|
||||
tpar.iface()
|
||||
// The type parameter bound is parameterized with the same type parameters
|
||||
// as the instantiated type; before we can use it for bounds checking we
|
||||
// need to instantiate it with the type arguments with which we instantiated
|
||||
|
11
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2
vendored
Normal file
11
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2022 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 _[P int]() {
|
||||
_ = f[P]
|
||||
}
|
||||
|
||||
func f[T int]() {}
|
@ -124,8 +124,9 @@ func (t *TypeParam) iface() *Interface {
|
||||
|
||||
// compute type set if necessary
|
||||
if ityp.tset == nil {
|
||||
// use the (original) type bound position if we have one
|
||||
pos := nopos
|
||||
// pos is used for tracing output; start with the type parameter position.
|
||||
pos := t.obj.pos
|
||||
// use the (original or possibly instantiated) type bound position if we have one
|
||||
if n, _ := bound.(*Named); n != nil {
|
||||
pos = n.obj.pos
|
||||
}
|
||||
|
@ -135,6 +135,8 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool
|
||||
func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) {
|
||||
smap := makeSubstMap(tparams, targs)
|
||||
for i, tpar := range tparams {
|
||||
// Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
|
||||
tpar.iface()
|
||||
// The type parameter bound is parameterized with the same type parameters
|
||||
// as the instantiated type; before we can use it for bounds checking we
|
||||
// need to instantiate it with the type arguments with which we instantiated
|
||||
|
11
src/go/types/testdata/fixedbugs/issue51048.go2
vendored
Normal file
11
src/go/types/testdata/fixedbugs/issue51048.go2
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2022 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 _[P int]() {
|
||||
_ = f[P]
|
||||
}
|
||||
|
||||
func f[T int]() {}
|
@ -5,7 +5,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
@ -127,8 +126,9 @@ func (t *TypeParam) iface() *Interface {
|
||||
|
||||
// compute type set if necessary
|
||||
if ityp.tset == nil {
|
||||
// use the (original) type bound position if we have one
|
||||
pos := token.NoPos
|
||||
// pos is used for tracing output; start with the type parameter position.
|
||||
pos := t.obj.pos
|
||||
// use the (original or possibly instantiated) type bound position if we have one
|
||||
if n, _ := bound.(*Named); n != nil {
|
||||
pos = n.obj.pos
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user