Should an assignment from int to a type based on int succeed?

185 views
Skip to first unread message

christoph...@gmail.com

unread,
May 8, 2020, 8:47:02 AM5/8/20
to golang-nuts
Hi folks,

I am not sure but to me it seems that the third assignment in the below code adheres to assignability rule #2 from the spec, yet it fails to compile:

package main

import "fmt"

/*
Assignability rule #2 (https://golang.org/ref/spec#Assignability):

A value x is assignable to a variable of type T if one of the following conditions applies:
x's type V and T have identical underlying types and at least one of V or T is not a defined type.
*/


type intp
*int
type integer
int

func main
() {
    i
:= 1
   
var ip1 *int
   
var ip2 intp
   
var i2 integer

    ip1
= &i // (1) assign *int to *int: ok - expected, both var expressions are of identical type *int
    ip2
= &i // (2) assign *int to intp: ok - expected, rule #2 satisfied
    i2
= i   // (4) assign int to integer: fail - unexpected, rule #2 should allow this:
   
//              underlying type of integer is int and the type of i (int) is not a defined type
   
//              error: ./prog.go:23:5: cannot use i (type int) as type integer in assignment
    fmt
.Println(ip1, ip2, i2) // avoid "variable declared but not used" error
}


For pointers the rule works but not for non-pointer types.

Or do I just fail to see the obvious...

Thoughts?

Thanks,
Christoph

Jan Mercl

unread,
May 8, 2020, 8:57:35 AM5/8/20
to christoph...@gmail.com, golang-nuts
On Fri, May 8, 2020 at 2:46 PM <christoph...@gmail.com> wrote:

> Or do I just fail to see the obvious...

'int' _is_ a defined type. It's predeclared in the universe scope.

Christoph Berger

unread,
May 8, 2020, 9:30:15 AM5/8/20
to Jan Mercl, golang-nuts
Thanks for the quick reply Jan.

So I conclude that the assignment of *int to intp succeeds because *int is not a defined type and both *int and intp have the same underlying type *int.

Looking through the ref spec I found a couple of places that mention some defined types (esp., all numeric types and string). Is there an exhaustive list available of all predefined types that technically count as defined types?

Jan Mercl

unread,
May 8, 2020, 10:02:57 AM5/8/20
to Christoph Berger, golang-nuts
On Fri, May 8, 2020 at 3:29 PM Christoph Berger
<christoph...@gmail.com> wrote:

> So I conclude that the assignment of *int to intp succeeds because *int is not a defined type and both *int and intp have the same underlying type *int.
>
> Looking through the ref spec I found a couple of places that mention some defined types (esp., all numeric types and string). Is there an exhaustive list available of all predefined types that technically count as defined types?

Predeclared types are listed here:
https://golang.org/ref/spec#Predeclared_identifiers in the section
"Types:"

Note that they do not "technically count". If 'name' is binded to a
type in a declaration then type 'name' is a defined type. The rule is
universal. The difference is that eg. `*int` is not a name
(identifier), so it's a type literal defining a pointer to a
named/defined type.

Christoph Berger

unread,
May 8, 2020, 10:32:16 AM5/8/20
to Jan Mercl, golang-nuts
Thank you Jan, this helped me a lot.

Unfortunately, the connection between "predeclared" (or "implicitly declared" as the first paragraph says) and "defined" is not at all obvious. Especially as the definition of "defined type" refers to types explicitly declared via the "type" keyword.

I conclude that the difference between assigning int to number (which fails) and *int to intp (which works) in the original example is subtle, well hidden in the spec, and probably quite difficult to explain to newcomers. (Especially the logic behind it.)

Jan Mercl

unread,
May 8, 2020, 10:43:28 AM5/8/20
to Christoph Berger, golang-nuts
On Fri, May 8, 2020 at 4:31 PM Christoph Berger
<christoph...@gmail.com> wrote:

> Unfortunately, the connection between "predeclared" (or "implicitly declared" as the first paragraph says) and "defined" is not at all obvious. Especially as the definition of "defined type" refers to types explicitly declared via the "type" keyword.

The definition of "defined type" is correct and simple, no special
rules exists. The predeclared identifier `int` is declared that way,
except it's done by the compiler without the need to do it in user
code. See here: https://godoc.org/builtin#int

Of course, the builtin package is only a formal definiton, it has
special treatment by the compiler, so doing the same in user code
would be invalid. Still `int` is defined and treated as `type int
something` and it's thus a defined(named) type.

In the first approximation, any type represented by a name is a
defined type. Later came type aliases, so now it's a bit more
complicated b/c one can write also `type T = []U` where T is not a
defined type b/c []U is not a defined type.

Axel Wagner

unread,
May 8, 2020, 11:42:53 AM5/8/20
to Jan Mercl, Christoph Berger, golang-nuts
> A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it. […] The new type is called a defined type. It is different from any other type, including the type it is created from.

This seems to imply, when taking as the sole definition of the word "defined type", that predeclared identifiers are in fact *not* defined types, as they don't originate from a type definition. I agree with Christoph here - if you follow any "defined type" link to this definition, which is formatted as a definition (italics are a classical typographical hint to denote a term being defined), that definition prevents any of the predeclared types from being considered "defined types".

However:

> […] The predeclared boolean type is bool; it is a defined type.
https://golang.org/ref/spec#Numeric_types
> […] To avoid portability issues all numeric types are defined types […]
> […] The predeclared string type is string; it is a defined type. […]
…hmmmmmmmm. I assume it doesn't make a difference here, as it's an interface type, so other parts of the spec apply wherever it's important. I'll play around for a bit :)

So, while the actual definition *is* ambiguous, the spec as a whole is not - it very clearly states that the predeclared types are defined types.
Note, that the section "predeclared identifiers" itself is not important here - being declared and being defined are different words and `errors` is predeclared, but, apparently, not defined. Language lawyering this way is annoying, but it's also what writing a spec is all about. "defined" and "declared" are similar, but distinct terms.

For clarity, it might make sense to amend the definition-looking section of the spec with a blurb in the spirit of "defined types are those arising from a type definition, or the predeclared types yadayadayada" (where yadayadayada could be a list, could be the empty string if we resolve the error ambiguity or could be "except error"). That way, if someone uses a "defined type" link to see what it means (as Christoph did here for assignability) they'll get an immediate answer about the implications.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAA40n-WzJAWpg4TEcW%2BZ2G-1zcUFNiSS0ezJtz6077Z4U3uwUQ%40mail.gmail.com.

Axel Wagner

unread,
May 8, 2020, 11:58:01 AM5/8/20
to Jan Mercl, Christoph Berger, golang-nuts
I'm happy to report, that I *think* I found an inconsistency with error not being a defined type:

One of the assignability rules is
> x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.

In this case, T is (say) chan error and V is `chan interface{ Error() string }`. Neither of them are defined types. So we have to check if V and T have identical element types.

The rules for type identity are a) A defined type is always different from any other type - `interface{ Error() string }` is definitely not a defined type and as stated, `error` also *should not* be one, with the spec as-is. So this part doesn't take. We then move to b) Two interface types are identical if they have the same set of methods with the same names and identical function types. This is clearly the case here.

So, I would argue, that per spec, the program linked above should compile. And as a corollary, I would argue that the spec should probably also be amended by "error is a defined type" in the appropriate section. Which makes things easier, because we can just talk about predeclared types in general - they are all defined.

(okay, I just realized that technically, the spec says "the type error is defined as…". Personally, I'd argue that it should specifically use the term "defined type" or link to the "defined type" section as the sections on ints/string/bool do, to disambiguate it from the colloquial use of "defined", if that was intended)

Christoph Berger

unread,
May 8, 2020, 12:07:44 PM5/8/20
to Jan Mercl, golang-nuts
All agreed, Jan. I have not meant to indicate that the definition of "defined type" is incorrect or complicated. The problem lies in the fact that a type like int, that is commonly recognized as a built-in type, happens to be a "defined type". This, plus the fact that a pointer to int is not a defined type, and thus two seemingly similar assignments obey to different rules.

I started this thread as I need to explain to someone if they can assign cmdline flags to defined types. With the flag functions that return pointers it is possible, with the *Var variations (IntVar, StringVar) it is not. This is quite difficult to explain without having to admit that the type system is not that straightforward as it might seem for a language like Go.

I know, a static type system is never easy, and AFAIR, even Eiffel's type system is not entirely consistent, but still...

Jan Mercl

unread,
May 8, 2020, 12:09:19 PM5/8/20
to Axel Wagner, Christoph Berger, golang-nuts
On Fri, May 8, 2020 at 5:57 PM Axel Wagner
<axel.wa...@googlemail.com> wrote:
>
> I'm happy to report, that I *think* I found an inconsistency with error not being a defined type:
> https://play.golang.org/p/gpy6S17wzIM

I don't follow. Type of x is not a defined type and neither is type of
y. The underlying type of x is not the same as the underlying type of
y.

Christoph Berger

unread,
May 8, 2020, 12:16:01 PM5/8/20
to Jan Mercl, Axel Wagner, golang-nuts
For clarity, it might make sense to amend the definition-looking section of the spec with a blurb in the spirit of "defined types are those arising from a type definition, or the predeclared types yadayadayada" (where yadayadayada could be a list, could be the empty string if we resolve the error ambiguity or could be "except error"). That way, if someone uses a "defined type" link to see what it means (as Christoph did here for assignability) they'll get an immediate answer about the implications.

This.

I agree it is all somewhere in the spec if I search long enough, but having the important parts in one place would definitely be an enormous time saver.


Thanks Axel for your input.

Axel Wagner

unread,
May 8, 2020, 12:20:31 PM5/8/20
to Jan Mercl, Christoph Berger, golang-nuts
Correct. I don't understand why you are saying that, though.
The argument I'm making is that x and y's *types* (not underlying) types are identical (actually, the argument I *was* making was different, but still had little to do with underlying types).

> A defined type is always different from any other type. Otherwise, two types are identical if their underlying type literals are structurally equivalent; that is, they have the same literal structure and corresponding components have identical types. In detail:
Now, as neither x's nor y's types are defined, the first sentence doesn't apply. So we have to compare the structure of their underlying types. The relevant part of that list is
> Two channel types are identical if they have identical element types and the same direction.
So we have to check whether `error` and `interface{ Error() string }` are identical. And that's where the question of whether error is a defined type comes in (as I said, I'd argue that with the spec as-is it *probably* isn't. It's at least not clearly stated).
If `error` is defined, then the two types are different; a defined type is different from any other type.
If `error` is *not* defined, then we fall back to comparing the structure of their underlying types. The structural comparison says they *are* different.

So, really, using channels was maybe a bit of a red-herring. As I said, the argument I was making still applies. But the argument that `error` and `interface{ Error() string }` *should* be identical if error is not defined is easier to make.

Axel Wagner

unread,
May 8, 2020, 12:22:03 PM5/8/20
to Jan Mercl, Christoph Berger, golang-nuts
sorry, that last sentence of the second paragraph should be "The structural comparison says they *are* identical".

Brian Candler

unread,
May 8, 2020, 1:32:13 PM5/8/20
to golang-nuts
On Friday, 8 May 2020 16:58:01 UTC+1, Axel Wagner wrote:
I'm happy to report, that I *think* I found an inconsistency with error not being a defined type:

Could you explain why error is not a defined type?  Is it something special about "error" specifically, or something about interface types in general?

Interface *values* can be assigned interchangeably, even between two different defined types:

But that falls out from the assignment rules for interface values:
"A variable of interface type can store a value of any type with a method set that is any superset of the interface"

Informally, I think of defined types as "named types".  I don't see anything which excludes interface types from being "defined types".  However, I also can't think of a case when it would make a difference whether a named interface type like error is actually a "defined type" or not.

Brian Candler

unread,
May 8, 2020, 1:34:58 PM5/8/20
to golang-nuts
Plus there is an explicit assignability rule for interface types:

* T is an interface type and x implements T.

I don't see why any of this implies that error is not a "defined type".

Axel Wagner

unread,
May 8, 2020, 4:58:42 PM5/8/20
to Brian Candler, golang-nuts
On Fri, May 8, 2020 at 7:32 PM Brian Candler <b.ca...@pobox.com> wrote:
Could you explain why error is not a defined type?  Is it something special about "error" specifically, or something about interface types in general?

First, the disclaimer again: I'm now coming around that there *is* a reading of a spec that error is a defined type. I also think it could be more explicit. So anything I say now is not to language-lawyer the spec, but to explain why I think it could be made more precise.

I said `error` is not a defined type ("the spec can be read as saying it isn't") based on the quotes I posted above.
• The section on type definitions, which is IMO closest to a definition of "defined type" says that a type declaration creates a new type, which is a defined type.
• The section on predeclared identifiers doesn't say anything really on the topic. Note, that even with a surrounding virtual universe-block, you can't actually write down a syntactical type declaration for int/int32/… - they have to be built into the language. I'd argue that there is no type declaration that you could point to for saying they conform to the definition.
• OTOH, the sections introducing bool, numeric types and string *specifically point out* that these types are defined types. So even if they don't conform to the definition in and off itself, the spec does state they are defined types. This also, FWIW, gives a hint that there is a need to state so. Being predeclared doesn't make them so.
• The section on error *doesn't* specifically point this out. This, really, is where we can argue about reading the spec.
- It doesn't use the specific word "defined type" at least and it doesn't link to type definitions, as the other sections doing this. IMO this is an argument that it's not a defined type per spec
- However, it does actually use a type definition to define the type, which is an argument that it *is* a defined type per spec (i.e. it conforms to the general definition even without specific mention).

The only reason I mentioned `error` being an interface, is because I was wondering *why* the spec doesn't specifically mention that it is a defined type, given that it does so for the other types. I guessed that it might not be necessary, because it's an interface - that guess was wrong, I think.

So, in conclusion:
• I believe it would at least be clearer that `error` is a defined type, if the word "defined" in the section on `error` would link to the section on type-definitions, or would mention the specific term "defined type".
• I believe the section on type definitions could clarify, that defined types are not *only* introduced by type-definitions, but also include predeclared types. There's no ambiguity in regards to this, but it would IMO be clearer - it's natural to arrive at this section via the various "defined types" links and getting an actual comprehensive answer on what they are would be helpful.

Informally, I think of defined types as "named types". 

Well, that's what the nomenclature used to be. It was changed, because the term got ambiguous and confusing once type-aliases got introduced. Turns out, it's still confusing because people confuse "defined" and "declared".

Jan Mercl

unread,
May 9, 2020, 2:39:44 AM5/9/20
to Axel Wagner, Brian Candler, golang-nuts
On Fri, May 8, 2020 at 10:58 PM 'Axel Wagner' via golang-nuts
<golan...@googlegroups.com> wrote:

> Well, that's what the nomenclature used to be. It was changed, because the term got ambiguous and confusing once type-aliases got introduced. Turns out, it's still confusing because people confuse "defined" and "declared".

Every name that represents a type and does not stand for a type alias
is a defined, formerly named type. The essence is in the existence of
the name for the type. If it's declared in user code of magically by
the compiler does not matter.

Brian Candler

unread,
May 9, 2020, 4:39:27 AM5/9/20
to golang-nuts
On Friday, 8 May 2020 21:58:42 UTC+1, Axel Wagner wrote:
• The section on error *doesn't* specifically point this out. This, really, is where we can argue about reading the spec.
- It doesn't use the specific word "defined type" at least and it doesn't link to type definitions, as the other sections doing this. IMO this is an argument that it's not a defined type per spec
- However, it does actually use a type definition to define the type, which is an argument that it *is* a defined type per spec (i.e. it conforms to the general definition even without specific mention).


The term "defined type" doesn't mean that there must be a corresponding type declaration/definition.  "int" is a "defined type", but you cannot write

type int int

I believe this is what you were saying when you said "I'd argue that there is no type declaration that you could point to for saying they conform to the definition", and I agree.  However, the spec doesn't actually say that every "defined type" must have a corresponding definition - only that type definitions are a way to create new defined types.

Where I strongly agree with you is that whenever you follow a hyperlink to "defined type", it takes you to the section on type definitions.  Effectively, the term "defined type" is not actually defined(*) in its own right, except in terms of the side effect of a type definition. It says that a "type definition" is a way to bring a new defined type into existence - but as you noted, there are pre-existing defined types (but not mentioned until later).  I suspect what has happened here is that it formerly said "named type" in which case it would have been much clearer.

I do think it would be helpful to be more up-front that the built-in (underlying) types are also defined types.  Otherwise it's easy to assume that "defined type" means "user-defined type" - anything defined *in terms of* the system underlying types - which is not true.  Again, when it said "named types", that problem would not have existed: it's clear that the type "int" has the name "int".  Whilst the spec is still valid, it certainly now has the flavour of requiring a pedantic / language lawyer interpretation.

As regards error, it says:

The predeclared type error is defined as

type error interface {
	Error() string
}

I don't think that implies there is a specific class of type which is a "predeclared type", in the same sense as there is a specific "defined type" (*).  It's just saying that this type has already been declared, in a hidden preamble to the user code. 

Secondly, even if there were a specific kind of type which is a "predeclared type", I do not think this would make it mutually exclusive with "defined type".

Therefore, I don't think this contradicts the earlier definition of "defined type", and by that definition, I conclude that "error" is a "defined type".  I suppose it could instead say "The predefined type error...", but that would also be confusing because it's not the fact that it's a "defined type" that matters, it's the fact that it has been declared and is available in all scopes.

In my opinion, clarity is not helped by having overlapping terms type definitions and type declarations.  "Type declarations" is the parent, with "Alias declarations" and "Type definitions" as the children.  Hence that code for "error" is both a type declaration (general, meaning it brings a type into existence) and a type definition (specific, meaning the result is not-an-alias, but is a "defined type").

Regards,

Brian.

(*) What I want to say is: in the spec, the term "defined type" has/has not been explicitly defined.  This is where English is tripping me up, as I would like to avoid re-using the word "defined", but cannot think of a good alternative.

Brian Candler

unread,
May 9, 2020, 5:34:52 AM5/9/20
to golang-nuts
From a language user's point of view, the following understanding seems to work:

- A named ("defined") type has one or more names ("identifiers")
- A type definition creates a new named type, distinct from all others
- An alias declaration adds a new name to an existing type

This does beg the question:

type Foo int
type Bar = Foo

var a Bar

What is the type of 'a'?  Is it "Bar", or is it "the-type-known-as-Foo-or-Bar"?  What type should error messages show?

Testing shows that the type of a "Foo":

So my simple understanding seems sufficient, at least in this simple case.  Error messages just show the first of the (perhaps many) names that the type has.

Axel Wagner

unread,
May 9, 2020, 6:52:35 AM5/9/20
to Brian Candler, golang-nuts
Every name that represents a type and does not stand for a type alias
is a defined, formerly named type. The essence is in the existence of
the name for the type. If it's declared in user code of magically by
the compiler does not matter.
 
Can you tell me where the spec says any of this? This thread isn't "please help me understand how the language works", it's "does the spec accurately and unambiguously define how the language works". So what you say may very well be true, but unless you can show how it arises from the spec, I don't really see what it's contributing.

And, FTR, the essence is certainly not the existence of the name - otherwise you wouldn't have to explicitly exclude type aliases. Just to show that waving hands at the question isn't really useful.

 I suspect what has happened here is that it formerly said "named type" in which case it would have been much clearer. 
 […]
 Again, when it said "named types", that problem would not have existed: it's clear that the type "int" has the name "int".

To re-iterate: Before type-aliases, this was true. But today, the current discussion is created by an ambiguity between "a defined type" and "a type which has a definition" and replacing that with the ambiguity between "a named type" and "a type which has a name" isn't clearer - a type alias is a name for a type.

I don't think that implies there is a specific class of type which is a "predeclared type",

The spec does have the specific notion of a predeclared identifier, and `error` is one of them. This doesn't contradict anything you say, I just wanted to point out that I don't think the use of "the predeclared type" is ambiguous in its meaning here - "predeclared" as an adjective has a language-level meaning. "defined" as an adjective has 1. a colloquial meaning and 2. a language-level meaning, but only when preceding "type".

Therefore, I don't think this contradicts the earlier definition of "defined type", and by that definition, I conclude that "error" is a "defined type".

I don't understand this argument. The question is if it *matches* a definition, not if it specifically contradicts it. If you want to know if ℤ is a Ring, you don't say "nothing about the definition of ℤ says it's not a Ring, therefore I conclude it is a Ring" - you look up the definition for being a Ring and prove that ℤ matches it.

I suppose it could instead say "The predefined type error...", but that would also be confusing because it's not the fact that it's a "defined type" that matters, it's the fact that it has been declared and is available in all scopes.

No, it is specifically not. What matters is if it is a "defined type" - which is a specific term in the spec used to ascribe special behavior to some types but not others. That's also why it wouldn't help if it said "predefined type" - this is not the term used in the spec to determine (for example) type identity and assignability.

To take a page out of Hilbert's book: We should be able to say "Chair" instead of "type-definition" and "Bierseidel" instead of "defined type" and still get a perfectly consistent spec. It's just a name. That would then remove any ambiguity when using the word "define" in a sentence and it would prevent any confusion of semantic overlap with "predeclared". And for the most part, you *can* do this replacement. You can then ask if error was a Bierseidel under this replacement. It can be argued it would be, at the end of the day, because the section would read "The predeclared type error is defined as `type error interface { Error() string }`" - so its definition would still be a Chair, which definitionally creates Bierseidels. I still feel it might be cleaner, to not rely on this argument and just explicitly add "`error` is a Bierseidel" as well.

Of course, the last paragraph reads ridiculously - at the end of the day, names matter, so we absolutely should use speaking names with intuitive understanding such as "defined type" and "type-definition". But once you *can* do the replacement without loss of information, you have at least avoided all confusion between the colloquial verb "define" and the specific language-level construct of a "defined type".

In my opinion, clarity is not helped by having overlapping terms type definitions and type declarations. 

Personally, given that any type definition is a type declaration - and given that both are syntactical constructs and thus unambiguously defined by the grammar - I don't find this super problematic.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Dan Kortschak

unread,
May 9, 2020, 7:42:07 AM5/9/20
to Axel Wagner, Brian Candler, golang-nuts
In https://golang.org/ref/spec#Types a Type is defined in terms of a
TypeName a TypeLit or a (Type). A TypeName is what makes a type a named
type. This is defined as either an identifier or a qualified
identifier. For the discussion here we can ignore the latter. An
identifier contains letters and unicode digits and must start with a
letter. From this we can see that an, e.g., int is a named type. The
alternative is a TypeLit, which is marked with a variety of keywords or
type punctuation (*, [] and [n]), these are unnamed types.

Brian Candler

unread,
May 9, 2020, 9:06:06 AM5/9/20
to golang-nuts
> This thread isn't "please help me understand how the language works", it's "does the spec accurately and unambiguously define how the language works".

Sure, I'm happy to stick to that.

Can you tell me if you agree that the spec is clear on this point: that if I write

type MyError interface {
    error() string
}

then MyError is a "defined type"?  I think it is clear: this is structurally a type definition, and the spec makes no distinction between interface types and other types in this context.

If you agree with that, then the question hinges on whether the built-in error interface being "predeclared" somehow emasculates its "defined type" nature which it would otherwise have from the structure of its (pre)declaration.  I don't see anything that suggests it does.

If there is ambiguity, it comes from the use of the term "predeclared type".  As you point out, there is a section on predeclared identifiers, but this includes a number of identifiers which are unambiguously "defined types" (such as "int").  So I don't see how "predeclared type" contradicts or cancels out "defined type".  As far as I can see, "error" is a defined type, which happens to have been predeclared or implicitly declared in the universe block.

> at the end of the day, names matter, so we absolutely should use speaking names with intuitive understanding such as "defined type" and "type-definition"

A rose by any other name etc.  Suppose we changed the terminology to something silly, let's say "fluffy type", which avoids questions like "who defined it? when was it defined?"  The spec then becomes:

A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.

TypeDef = identifier Type .

The new type is called a fluffy type. It is different from any other type, including the type it is created from.


However, not all fluffy types are the result of type definitions, and to me this is unclear without a "language lawyer" reading.  As has already been suggested, it would be helpful to include a definition:

> fluffy types are those arising from a type definition, or the predeclared types yadayadayada" (where yadayadayada could be a list, could be the empty string if we resolve the error ambiguity or could be "except error")

I agree with this apart from "except error", since I still see nothing that says error is not a defined type.

Axel Wagner

unread,
May 9, 2020, 12:50:15 PM5/9/20
to golang-nuts
Dan:

I don't know why you are talking about "named type". The nomenclature is outdated and obsoleted by "defined type". The only reason I see to still use it is so you can make an argument that "it has a name" means "it's a defined type" - which isn't even a correct argument anymore since type aliases can give non-defined types names. That's the entire reason the term was abandoned.
The section you point to *is* however still relevant - that's why I quoted it myself in my first message. It *does* contain one definition of what a "defined type" is, by saying that a type definition creates one.

Brian:

If you agree with that, […]

I do agree. I actually made this argument myself upthread. I'm TBQH a bit exasperated here. Several intelligent people are seemingly (to me) ignoring what I actually wrote. And I'm fully willing to take the blame on this and accept that I wasn't being clear with what I've written or that I'm misreading what y'all are writing. I just I really don't understand how. I explicitly stated, that an argument can be made that the fact that `error` is defined in terms of a type definition in the spec, means it is a defined type. For example, my very first response to you contains the sentence

However, it does actually use a type definition to define the type, which is an argument that it *is* a defined type per spec (i.e. it conforms to the general definition even without specific mention).

And in regards to:

then the question hinges on whether the built-in error interface being "predeclared" somehow emasculates its "defined type" nature

Why are you bringing up "predeclared" here? I, at least, certainly never tried to pose this question (I don't think anyone ever did). I was only responding to people telling me that error is a defined type because it is predeclared (and hence has a name and hence is a named type…) and that's just not a valid argument. But me saying "¬(predeclared⇒defined)" is not the same as me saying "predeclared⇒¬defined". Those are two very different statements and I earnestly do not understand how what I said can be interpreted as the latter.

So, to once again be absolutely clear:
* I agree that there's a valid argument to be made that `error` is a defined type according to the spec.
* I initially thought the spec might not say errors is a defined type (specifically, because it doesn't use the term "defined type" with a link to type-definitions, as it does for every other predeclared defined type).
* I then realized that there are various arguments to be made to prove that it does and that some of those have counter-arguments.
* I believed (from the start) that either way, this argument isn't necessary if the Errors-section of the spec was changed to, for example:

The predeclared type error is defined as
type error interface {
    Error() string
}

(to state the obvious: There is no change in the text here. All I did was add a link to the word "defined")

I don't even superduper think it needs to be changed. I'm just confused by people seemingly arguing past me and because I have a pathological need to find common ground, this sort of DoSes my brain :)

And… lastly, just because

I agree with this apart from "except error", since I still see nothing that says error is not a defined type.

Note that in the blurb you quoted, I said that we can simply say "or the predeclared types", if the error ambiguity is resolved. If the Errors section is clarified, that would resolve that. If it's decided that the existing argument is enough, that would also resolve it. I feel the former is preferable, but it's definitely a mole hill that has seen far more than enough blood shed.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Dan Kortschak

unread,
May 9, 2020, 5:14:59 PM5/9/20
to Axel Wagner, golang-nuts
Yes, sorry. Eight years of habit is hard to break. I think I agree
with you; a small bit of text in
https://golang.org/ref/spec#Type_definitions linking to
https://golang.org/ref/spec#Predeclared_identifiers and saying that
there exist already defined types may ease this, or the suggestion you
have of making the word "defined" linked to defined types in
https://golang.org/ref/spec#Errors (or both).
Reply all
Reply to author
Forward
0 new messages