From ce04ca3bf6ebee16c13bf570b010e9dffa939d2e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 14 Oct 2021 17:46:40 -0400 Subject: [PATCH] go/internal/gcimporter: normalize implicit interfaces in export tests The export data format does not yet support capturing whether interfaces are implicit, so normalize them for the purposes of comparing type parameter constraints. Change-Id: I678fb5f5fe6481b9a1479176ca056a31d17bbd77 Reviewed-on: https://go-review.googlesource.com/c/tools/+/355971 Trust: Robert Findley Run-TryBot: Robert Findley gopls-CI: kokoro TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- go/internal/gcimporter/bexport_test.go | 29 ++++++++++++++++++-- go/internal/gcimporter/iexport_go118_test.go | 4 +++ internal/typeparams/typeparams_go117.go | 5 ++++ internal/typeparams/typeparams_go118.go | 5 ++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/go/internal/gcimporter/bexport_test.go b/go/internal/gcimporter/bexport_test.go index 116a009cfc..7300ba8929 100644 --- a/go/internal/gcimporter/bexport_test.go +++ b/go/internal/gcimporter/bexport_test.go @@ -200,6 +200,9 @@ func equalType(x, y types.Type) error { return fmt.Errorf("mismatched %s method: %s", xm.Name(), err) } } + // Constraints are handled explicitly in the *TypeParam case below, so we + // don't yet need to consider embeddeds here. + // TODO(rfindley): consider the type set here. case *types.Array: y := y.(*types.Array) if x.Len() != y.Len() { @@ -315,9 +318,12 @@ func equalType(x, y types.Type) error { return fmt.Errorf("unequal named types: %s vs %s", x, y) } // For now, just compare constraints by type string to short-circuit - // cycles. - xc := sanitizeName(x.Constraint().String()) - yc := sanitizeName(y.Constraint().String()) + // cycles. We have to make interfaces explicit as export data currently + // doesn't support marking interfaces as implicit. + // TODO(rfindley): remove makeExplicit once export data contains an + // implicit bit. + xc := sanitizeName(makeExplicit(x.Constraint()).String()) + yc := sanitizeName(makeExplicit(y.Constraint()).String()) if xc != yc { return fmt.Errorf("unequal constraints: %s vs %s", xc, yc) } @@ -328,6 +334,23 @@ func equalType(x, y types.Type) error { return nil } +// makeExplicit returns an explicit version of typ, if typ is an implicit +// interface. Otherwise it returns typ unmodified. +func makeExplicit(typ types.Type) types.Type { + if iface, _ := typ.(*types.Interface); iface != nil && typeparams.IsImplicit(iface) { + var methods []*types.Func + for i := 0; i < iface.NumExplicitMethods(); i++ { + methods = append(methods, iface.Method(i)) + } + var embeddeds []types.Type + for i := 0; i < iface.NumEmbeddeds(); i++ { + embeddeds = append(embeddeds, iface.EmbeddedType(i)) + } + return types.NewInterfaceType(methods, embeddeds) + } + return typ +} + func equalTypeArgs(x, y *typeparams.TypeList) error { if x.Len() != y.Len() { return fmt.Errorf("unequal lengths: %d vs %d", x.Len(), y.Len()) diff --git a/go/internal/gcimporter/iexport_go118_test.go b/go/internal/gcimporter/iexport_go118_test.go index 50ac0f752d..b3617170ec 100644 --- a/go/internal/gcimporter/iexport_go118_test.go +++ b/go/internal/gcimporter/iexport_go118_test.go @@ -36,6 +36,10 @@ func ToInt[P interface{ ~int }](p P) int { return int(p) } var IntID = ToInt[int] type G[C comparable] int + +func ImplicitFunc[T ~int]() {} + +type ImplicitType[T ~int] int ` testExportSrc(t, []byte(src)) } diff --git a/internal/typeparams/typeparams_go117.go b/internal/typeparams/typeparams_go117.go index 5a536526c5..214eab6667 100644 --- a/internal/typeparams/typeparams_go117.go +++ b/internal/typeparams/typeparams_go117.go @@ -132,6 +132,11 @@ func IsMethodSet(*types.Interface) bool { return true } +// IsImplicit returns false, as no interfaces are implicit at this Go version. +func IsImplicit(*types.Interface) bool { + return false +} + // ForNamed returns an empty type parameter list, as type parameters are not // supported at this Go version. func ForNamed(*types.Named) *TypeParamList { diff --git a/internal/typeparams/typeparams_go118.go b/internal/typeparams/typeparams_go118.go index e3c48221dd..55c0398e62 100644 --- a/internal/typeparams/typeparams_go118.go +++ b/internal/typeparams/typeparams_go118.go @@ -125,6 +125,11 @@ func IsMethodSet(iface *types.Interface) bool { return iface.IsMethodSet() } +// IsImplicit calls iface.IsImplicit(). +func IsImplicit(iface *types.Interface) bool { + return iface.IsImplicit() +} + // ForNamed extracts the (possibly empty) type parameter object list from // named. func ForNamed(named *types.Named) *TypeParamList {