Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/exp/apidiff: resolution of type aliases depends on type names #37138

Open
neild opened this issue Feb 8, 2020 · 3 comments
Open

x/exp/apidiff: resolution of type aliases depends on type names #37138

neild opened this issue Feb 8, 2020 · 3 comments
Labels
NeedsInvestigation
Milestone

Comments

@neild
Copy link
Contributor

@neild neild commented Feb 8, 2020

package v1
type T interface { F() }
func F(T) {}
package v2
import "example.com/x/common"
type T = common.T2
func F(T) {}
package common
type T2 interface { F() }
$ apidiff example.com/x/v1 example.com/x/v2
Incompatible changes:
- F: changed from func(T) to func(example.com/x/common.T2)
- T: changed from T to example.com/x/common.T2

This is obviously wrong: v1 and v2 have identical APIs; we've just extracted the v2.T type into a separate package.

At first I thought apidiff wasn't keeping track of type aliases, but if I keep the exact same API but keep the name of the type the same (common.T, not common.T2) then it reports no API change.

@gopherbot gopherbot added this to the Unreleased milestone Feb 8, 2020
@bcmills
Copy link
Member

@bcmills bcmills commented Feb 10, 2020

CC @jba @griesemer @jayconrod @matloob

@bcmills bcmills added the NeedsInvestigation label Feb 10, 2020
@jba jba self-assigned this Feb 10, 2020
@bcmills
Copy link
Member

@bcmills bcmills commented Aug 17, 2020

Unfortunately, apidiff may be correct here. The change described here can introduce a compile-time error.


Per https://golang.org/ref/spec#Type_switches:

The types listed in the cases of a type switch must all be different.

And, per https://golang.org/ref/spec#Type_identity:

A defined type is always different from any other type.

So changing T from a defined type to an alias of common.T2 can introduce a compilation error in consumer code by causing two case statements within a type-switch to no longer name different types. For example, compare https://play.golang.org/p/8XvlKYtEOT8 and https://play.golang.org/p/BXfun4_eWkd:

package main

import (
	"fmt"

	"example.com/x/common"
	"example.com/x/v"
)

func main() {
	var x interface{} = v.F
	switch x.(type) {
	case func(common.T2):
		fmt.Println("common")
	case func(v.T):
		fmt.Println("v")
	}
}

After the change, that program fails with the error

# example.com/x
./prog.go:15:2: duplicate case func(common.T2) in type switch
	previous case at ./prog.go:13:2

@neild
Copy link
Contributor Author

@neild neild commented Aug 17, 2020

If common is an entirely new package, then there can be no existing references to common.T2.

But regardless of that question, the bug here is that apidiff cares about the name of the target of the alias. Whether the alias is to common.T or commont.T2 shouldn't be relevant.

@rsc rsc unassigned jba Jun 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation
Projects
None yet
Development

No branches or pull requests

4 participants