]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: ensure we have an interface before checking constraints
authorRobert Griesemer <gri@golang.org>
Mon, 7 Feb 2022 19:28:14 +0000 (11:28 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 7 Feb 2022 21:00:02 +0000 (21:00 +0000)
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>
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/typeparam.go
src/go/types/instantiate.go
src/go/types/testdata/fixedbugs/issue51048.go2 [new file with mode: 0644]
src/go/types/typeparam.go

index 90a669f7541799ce7215a6e66f84e258a02f145c..f54938b6e198ae8349cadc8b71f64bb997153633 100644 (file)
@@ -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
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2
new file mode 100644 (file)
index 0000000..5830837
--- /dev/null
@@ -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]() {}
index e32063a0af1dc85dbd9d00ffc53bacbfa6109e50..971fdaec739f8bbe69bb7aa141a5add51e692199 100644 (file)
@@ -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
                }
index aeb30fa412ee2bc14ffad09c3093ebca1843a06a..4aeaeb7f1169ca91d5424718fed63a810329e268 100644 (file)
@@ -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
diff --git a/src/go/types/testdata/fixedbugs/issue51048.go2 b/src/go/types/testdata/fixedbugs/issue51048.go2
new file mode 100644 (file)
index 0000000..5830837
--- /dev/null
@@ -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]() {}
index 03ba9be55c564d669ae8ba33bd0c2add2bfb5415..71e6861b87f40fe1c84cc3a18ff0bdc4a1db218f 100644 (file)
@@ -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
                }