Skip to content

Commit 7db75b3

Browse files
committed
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 <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 49030c8 commit 7db75b3

File tree

6 files changed

+32
-5
lines changed

6 files changed

+32
-5
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool
135135
func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) (int, error) {
136136
smap := makeSubstMap(tparams, targs)
137137
for i, tpar := range tparams {
138+
// Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
139+
tpar.iface()
138140
// The type parameter bound is parameterized with the same type parameters
139141
// as the instantiated type; before we can use it for bounds checking we
140142
// need to instantiate it with the type arguments with which we instantiated
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2022 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 _[P int]() {
8+
_ = f[P]
9+
}
10+
11+
func f[T int]() {}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@ func (t *TypeParam) iface() *Interface {
124124

125125
// compute type set if necessary
126126
if ityp.tset == nil {
127-
// use the (original) type bound position if we have one
128-
pos := nopos
127+
// pos is used for tracing output; start with the type parameter position.
128+
pos := t.obj.pos
129+
// use the (original or possibly instantiated) type bound position if we have one
129130
if n, _ := bound.(*Named); n != nil {
130131
pos = n.obj.pos
131132
}

src/go/types/instantiate.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool
135135
func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) {
136136
smap := makeSubstMap(tparams, targs)
137137
for i, tpar := range tparams {
138+
// Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
139+
tpar.iface()
138140
// The type parameter bound is parameterized with the same type parameters
139141
// as the instantiated type; before we can use it for bounds checking we
140142
// need to instantiate it with the type arguments with which we instantiated
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2022 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 _[P int]() {
8+
_ = f[P]
9+
}
10+
11+
func f[T int]() {}

src/go/types/typeparam.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package types
66

77
import (
8-
"go/token"
98
"sync/atomic"
109
)
1110

@@ -127,8 +126,9 @@ func (t *TypeParam) iface() *Interface {
127126

128127
// compute type set if necessary
129128
if ityp.tset == nil {
130-
// use the (original) type bound position if we have one
131-
pos := token.NoPos
129+
// pos is used for tracing output; start with the type parameter position.
130+
pos := t.obj.pos
131+
// use the (original or possibly instantiated) type bound position if we have one
132132
if n, _ := bound.(*Named); n != nil {
133133
pos = n.obj.pos
134134
}

0 commit comments

Comments
 (0)