compatiblesmessageSet
Correspondences between named types.
Even though it is the named types (*types.Named) that correspond, we use
*types.TypeName as a map key because they are canonical.
The values can be either named types or basic types.
Messages.
new*types.Packageold*types.Package(*differ) checkCompatible(otn *types.TypeName, old, new types.Type)(*differ) checkCompatibleBasic(otn *types.TypeName, old, new *types.Basic)(*differ) checkCompatibleChan(otn *types.TypeName, old, new *types.Chan)(*differ) checkCompatibleDefined(otn *types.TypeName, old *types.Named, new types.Type)
Interface compatibility:
If the old interface has an unexported method, the new interface is compatible
if its exported method set is a superset of the old. (Users could not implement,
only embed.)
If the old interface did not have an unexported method, the new interface is
compatible if its exported method set is the same as the old, and it has no
unexported methods. (Adding an unexported method makes the interface
unimplementable outside the package.)
TODO: must also check that if any methods were added or removed, every exposed
type in the package that implemented the interface in old still implements it in
new. Otherwise external assignments could fail.
Anything removed or change from the old set is an incompatible change.
Anything added to the new set is a compatible change.
We need to check three things for structs:
1. The set of exported fields must be compatible. This ensures that keyed struct
literals continue to compile. (There is no compatibility guarantee for unkeyed
struct literals.)
2. The set of exported *selectable* fields must be compatible. This includes the exported
fields of all embedded structs. This ensures that selections continue to compile.
3. If the old struct is comparable, so must the new one be. This ensures that equality
expressions and uses of struct values as map keys continue to compile.
An unexported embedded struct can't appear in a struct literal outside the
package, so it doesn't have to be present, or have the same name, in the new
struct.
Field tags are ignored: they have no compile-time implications.
(*differ) checkCorrespondence(obj types.Object, part string, old, new types.Type)(*differ) checkMethodSet(otn *types.TypeName, oldt, newt types.Type, addcompat bool)(*differ) checkObjects(old, new types.Object)(*differ) checkPackage()(*differ) compatible(obj types.Object, part, format string, args ...interface{})
Compare two constants.
corr determines whether old and new correspond. The argument p is a list of
known interface identities, to avoid infinite recursion.
corr calls itself recursively as much as possible, to establish more
correspondences and so check more of the API. E.g. if the new function has more
parameters than the old, compare all the old ones before returning false.
Compare this to the implementation of go/types.Identical.
Compare old and new field names. We are determining correspondence across packages,
so just compare names, not packages. For an unexported, embedded field of named
type (non-named embedded fields are possible with aliases), we check that the type
names correspond. We check the types for correspondence before this is called, so
we've established correspondence.
Two types are correspond if they are identical except for defined types,
which must correspond.
Two defined types correspond if they can be interchanged in the old and new APIs,
possibly after a renaming.
This is not a pure function. If we come across named types while traversing,
we establish correspondence.
Establish that old corresponds with new if it does not already
correspond to something else.
(*differ) incompatible(obj types.Object, part, format string, args ...interface{})(*differ) methodID(m *types.Func) string(*differ) sortedMethods(iface *types.Interface) []*types.Func(*differ) typeChanged(obj types.Object, part string, old, new types.Type)
func newDiffer(old, new *types.Package) *differ
There can be at most one message for each object or part thereof.
Parts include interface methods and struct fields.
The part thing is necessary. Method (Func) objects have sufficient info, but field
Vars do not: they just have a field name and a type, without the enclosing struct.
Add a message for obj and part, overwriting a previous message
(shouldn't happen).
obj is required but part can be empty.
( messageSet) collect() []string
func addMessage(ms messageSet, obj types.Object, part, format string, args []interface{})
Package-Level Functions (total 18, in which 1 are exported)
Changes reports on the differences between the APIs of the old and new packages.
It classifies each difference as either compatible or incompatible (breaking.) For
a detailed discussion of what constitutes an incompatible change, see the package
documentation.
exportedFields collects all the immediate fields of the struct that are exported.
This is also the set of exported keys for keyed struct literals.
exportedMethods collects all the exported methods of type's method set.
exportedSelectableFields collects all the exported fields of the struct, including
exported fields of embedded structs.
We traverse the struct breadth-first, because of the rule that a lower-depth field
shadows one at a higher depth.
go/types always includes the argument and result names when formatting a signature.
Since these can change without affecting compatibility, we don't want users to
be distracted by them, so we remove them.
Two list of type parameters match if they are the same length, and
the constraints of corresponding type parameters are identical.
typesEquivalent reports whether two types are identical, or if
the types have identical type param lists except that one type has nil
constraints.
This allows us to match a Type from a method receiver or arg to the Type from
the declaration.
Given a set of structs at the same depth, the unambiguous fields are the ones whose
names appear exactly once.
Return an unexported method from the method set of t, or nil if there are none.
Package-Level Variables (only one, which is unexported)
All pairs (old, new) of compatible basic types.
Package-Level Constants (total 2, neither is exported)