From d49c915592f568ee7f2cb7ca89a59989d7ed2d09 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 11 Dec 2019 14:05:56 -0800 Subject: [PATCH] go/types: a type arg type list must be a subset of the type param type list The original implementation (commit 65377ae6e0) checked the wrong way around. Added more tests. Change-Id: I59e1fd6d7e646f2e8e0ff68a0bbcf9ff9def0eff --- src/go/types/examples/contracts.go2 | 2 ++ src/go/types/subst.go | 11 +++++------ src/go/types/testdata/contracts.go2 | 14 ++++++++++---- src/go/types/testdata/tmp.go2 | 19 ------------------- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/go/types/examples/contracts.go2 b/src/go/types/examples/contracts.go2 index 408c901e65..ef3b6b2c01 100644 --- a/src/go/types/examples/contracts.go2 +++ b/src/go/types/examples/contracts.go2 @@ -53,6 +53,8 @@ type AltGraph (type Node NodeFace(Edge), Edge EdgeFace(Node)) struct { } func AltNew (type Node NodeFace(Edge), Edge EdgeFace(Node)) (nodes []Node) *AltGraph(Node, Edge) { panic("unimplemented") } +// func (g *AltGraph(N, E)) ShortestPath(from, to N) []E { panic("unimplemented") } + type NodeFace(type Edge) interface { Edges() []Edge } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 05e33a256c..1258c32a2b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -97,12 +97,11 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist break // nothing to do } - // if targ is a type parameter, the list of iface types must be a subset of the - // list of targ types - if t, _ := targ.Underlying().(*TypeParam); t != nil { - targFace := t.Interface() - for _, t := range iface.types { - if !includesType(t, targFace) { + // if targ is itself a type parameter, each of its possible types must be in the + // list of iface types (i.e., the targ type list must be a subset of the iface types) + if targ, _ := targ.Underlying().(*TypeParam); targ != nil { + for _, t := range targ.Interface().types { + if !includesType(t, iface) { check.softErrorf(pos, "%s does not satisfy %s (missing type %s)", targ, tpar.bound, t) break } diff --git a/src/go/types/testdata/contracts.go2 b/src/go/types/testdata/contracts.go2 index 37d62010d4..a3351d35b5 100644 --- a/src/go/types/testdata/contracts.go2 +++ b/src/go/types/testdata/contracts.go2 @@ -202,13 +202,19 @@ type T3(type P B1) P func _(type P B1)(x T3(P)) -contract B2(T) { - T int + +type B2 interface{type int, string} + +func _(type P B2)(x T3(P /* ERROR missing type string */ )) + + +contract B3(T) { + T int, string } -type T4(type P B2) P +type T4(type P B1) P -func _(type P B2)(x T4(P)) +func _(type P B3)(x T4(P /* ERROR missing type string */ )) // -------------------------------------------------------------------------------------- // Type parameters may be from different parameterized objects diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index 3325ef93a4..cbb358b144 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -3,22 +3,3 @@ // license that can be found in the LICENSE file. package p - -contract C(T) { - T int -} - -type Cm(type T C) T - -func (a Cm(T /* ERROR does not satisfy */ )) m() T - -// TODO(gri) make this work -/* -type C interface { - type int -} - -type Cm(type T C) T - -func (a Cm(T)) m() T -*/ \ No newline at end of file