Skip to content

Commit f66d83c

Browse files
committed
apidiff: avoid comparing instantiated aliases
During the initial step of comparing APIs, we associate named types in both the old and new worlds. This doesn't work if the named type is an alias to an instantiated type, so skip that case. The proper comparison will happen subsequently. Fixes golang/go#67051. Change-Id: Ia405f842e8bf5e258cbcc0748a644d2cea83117a Reviewed-on: https://go-review.googlesource.com/c/exp/+/618617 Reviewed-by: Tim King <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 225e2ab commit f66d83c

File tree

4 files changed

+29
-8
lines changed

4 files changed

+29
-8
lines changed

apidiff/apidiff.go

+14
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,27 @@ func (d *differ) checkPackage(oldRootPackagePath string) {
146146
// from T to T", which can happen if a correspondence between an alias
147147
// and a named type is established first.
148148
// See testdata/order.go.
149+
// Example of what this loop looks for:
150+
// type A = B // old
151+
// type B ... // new
152+
//
153+
// We want to ensure that old B and new B correspond.
154+
//
155+
// This loop is unnecessary for correctness; skipping symbols will not introduce bugs.
149156
for _, name := range d.old.Scope().Names() {
150157
oldobj := d.old.Scope().Lookup(name)
151158
if tn, ok := oldobj.(*types.TypeName); ok {
152159
if oldn, ok := tn.Type().(*types.Named); ok {
153160
if !oldn.Obj().Exported() {
154161
continue
155162
}
163+
// Skip aliases to instantiated generic types. They end up getting
164+
// compared to the origin type, which will fail.
165+
// For example, we don't want to try to make A[int] correspond with
166+
// A[T any].
167+
if tn.IsAlias() && isInstantiated(oldn) {
168+
continue
169+
}
156170
// Does new have a named type of the same name? Look up using
157171
// the old named type's name, oldn.Obj().Name(), not the
158172
// TypeName tn, which may be an alias.

apidiff/apidiff_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func splitIntoPackages(t *testing.T, file, dir string) (incompatibles, compatibl
129129
if err := os.MkdirAll(filepath.Join(dir, "src", "apidiff"), 0700); err != nil {
130130
t.Fatal(err)
131131
}
132-
if err := os.WriteFile(filepath.Join(dir, "src", "apidiff", "go.mod"), []byte("module apidiff\ngo 1.18\n"), 0600); err != nil {
132+
if err := os.WriteFile(filepath.Join(dir, "src", "apidiff", "go.mod"), []byte("module apidiff\ngo 1.22\n"), 0600); err != nil {
133133
t.Fatal(err)
134134
}
135135

apidiff/correspondence.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,14 @@ func (d *differ) establishCorrespondence(old *types.Named, new types.Type) bool
208208
// Two generic named types correspond if their type parameter lists correspond.
209209
// Since one or the other of those lists will be empty, it doesn't hurt
210210
// to check both.
211-
oldOrigin := old.Origin()
212-
newOrigin := newn.Origin()
213-
if oldOrigin != old {
214-
// old is an instantiated type.
215-
if newOrigin == newn {
216-
// new is not; they cannot correspond.
211+
if isInstantiated(old) {
212+
if !isInstantiated(new) {
213+
// old is an instantiated type but new is not; they cannot correspond.
217214
return false
218215
}
219216
// Two instantiated types correspond if their origins correspond and
220217
// their type argument lists correspond.
221-
if !d.correspond(oldOrigin, newOrigin) {
218+
if !d.correspond(old.Origin(), new.Origin()) {
222219
return false
223220
}
224221
if !d.typeListsCorrespond(old.TypeArgs(), newn.TypeArgs()) {
@@ -301,3 +298,8 @@ type ifacePair struct {
301298
func (p *ifacePair) identical(q *ifacePair) bool {
302299
return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
303300
}
301+
302+
// isInstantiated reports whether t is instantiated from a generic type.
303+
func isInstantiated(t *types.Named) bool {
304+
return t.Origin() != t
305+
}

apidiff/testdata/aliases.go

+5
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ type C int
2727
// new
2828
// OK: merging types
2929
type C = int
30+
31+
// both
32+
// OK: identical (but this fails on 07ab4e7)
33+
type TypedBucketRateLimiter[T comparable] struct{}
34+
type BucketRateLimiter = TypedBucketRateLimiter[any]

0 commit comments

Comments
 (0)