> So, MapOfMaps is compatible with map[int] map[int] int, but MyInt is
> not compatible with int.
Yes.
Type compatibility is less stringent than type identity:
a named and an unnamed type are compatible if the
respective type literals are compatible.
http://golang.org/doc/go_spec.html#Type_identity_and_compatibility
"int" and "MyInt" are both named types, so this sentence
doesn't apply in that case.
Why is it like this? Because much of the time type names
for composite types like
type MapOfMaps map[int] map[int] int
are serving only as shorthands, not trying to introduce a
distinct type. But if a type has two different names
that is clearly not a shorthand and shouldn't be converted
silently (in particular, it could change the meaning of
methods from one to the other). The case that comes
up in practice is giving names to functions, like
type Op func(int, int) int
This is obviously a kludge: there should be two different ways
to introduce names, one that is just a shorthand and
one that creates a distinct (not compatible) type.
But we had a very hard time coming up with a shorthand
mechanism that we liked. The syntax is only a small
part: the big semantic problem is that once you introduce
these shorthands (let's call them typedefs), you can now
have two spellings that mean the same type (are identical types,
in the language of the spec). When you print a compiler error
or a type diagnostic or any of the other places that a type
is spelled out, which spelling do you use? How do you decide?
This seems like a tiny thing but C (and especially C++)
compilers struggle mightily with it [1], and they only have to
print types in error messages (there are no runtime concerns).
Go avoids all that complexity by not having typedef. The
named + unnamed compatibility rule is a small nod to
compensate for that lack in the situations where typedef
is most missed. In practice, it seems to be a good trade,
but it's certainly not the most principled part of the language.
Two types T2 and T3 can never be compatible: they are
both named, and the names are different (see definition
above).
Russ
[1] g++ x.cc
#include <string>
#include <vector>
using namespace std;
int f(vector<string>* v);
int g(vector<string> v) { f(g); }