golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.99k stars 17.67k forks source link

spec: inaccurate assignability condition #31243

Closed RaduBerinde closed 5 years ago

RaduBerinde commented 5 years ago

One of the conditions for assignability defined in the spec is:

x's type V and T have identical underlying types and at least one of V or T is not a defined type.

I think that defined type is not accurate here because (for example) int is not a defined type, and you can't assign an int to a defined type with the same underlying type: https://play.golang.org/p/kWS5_tHmMgo

An earlier iteration of the spec used named type here instead of defined type which I think was correct at that time (int is a named type but it's not a defined type). The change was in this commit: https://github.com/golang/go/commit/56c9b51b937cca7d3db517add96bd9517bbffb80

Perhaps other uses of "named type" that were converted to "defined type" are now erroneous as well (w.r.t. built-in named types).

CC @griesemer

zigo101 commented 5 years ago

int is not a defined type,

int is exactly a defined type. It is defined here: https://golang.org/pkg/builtin/#int

And I have the impressions that @griesemer has ever confirmed this.

If this is not true, then my book Go 101 is spreading mistakes.

@griesemer, Could you confirm whether or not the builtin int is a defined type? For my book will get a formal release soon, I don't want it contains such mistakes.

RaduBerinde commented 5 years ago

Interesting. I looked at the spec some more, and indeed it says:

To avoid portability issues all numeric types are defined types and thus distinct except byte, which is an alias for uint8, and rune, which is an alias for int32.

RaduBerinde commented 5 years ago

Closing, I don't think any clarification is necessary, I just made the wrong assumption about what "defined type" means.

zigo101 commented 5 years ago

To avoid portability issues all numeric types are defined types and thus distinct except byte, which is an alias for uint8, and rune, which is an alias for int32.

Ah, it looks the "except" is not very necessary, for aliases of defined types should be also defined types, I think.

RaduBerinde commented 5 years ago

I think an alias is not a type at all, it's an identifier for another type. If byte was a defined type, then you wouldn't be able to assign between byte and uint8 which you can (the spec says "a defined type is always different from any other type").

zigo101 commented 5 years ago

The wording is some subtle, and hard to be accurate. If we make every wording accurate, then many explanations will become much verbose. byte values and uint8 values can be converted to each other's type, for their types are identical.

griesemer commented 5 years ago

The spec is clear that boolean types (https://golang.org/ref/spec#Boolean_types), numeric types (https://golang.org/ref/spec#Numeric_types), string types (https://golang.org/ref/spec#String_types), and the error type (https://tip.golang.org/ref/spec#Errors) are "defined types". The respective sections state that explicitly.

The spec doesn't talk about "alias types", it talks only about "alias declarations" and "aliases". An alias is an alternative name for a defined type.

Another way to look at defined types is to imagine that they are painted a specific new color, which is different from any other color used in the program, which thus makes such a colored type different from any other type (even if that other type "looks the same" but for the color). We can't see that color in the program, so instead we give those types names, and then we look at the declaration of those names and see if it is in fact a type definition or an alias declaration.

Other languages have similar concepts and sometimes what we call a "defined type" is called a "branded type" elsewhere; with the "branding" being exactly a unique marker on that type, similar to a unique color.

Go uses a mix of nominal and structural typing (see e.g. this article, for a short, easy to read essay on this ). A Go type definition introduces exactly a new nominal type. It may have been better to call them "nominal" rather than "defined".

Hope this helps. I agree that there's nothing to do here.

zigo101 commented 5 years ago

@griesemer

If aliases shouldn't be called types, then is the terminology "named type" still relevant. The terminology is seldom used in Go official documentations now. I just made a search, only found it is used in efficient Go and two wiki articles.