Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
cmd/compile: provide a more explanatory error message on trying to take the address of an unaddressable value e.g. constants, integer and string literals #28393
What version of Go are you using (
Thank you @deanveloper for filing this bug and welcome to the Go project!
Sounds like a plan, I've updated the title of this issue with the premise of providing a more explanatory error message for trying to take the address of an unaddressable value
cannot take the address of integer literal 5
cannot take the address of 5 (unaddressable because it is an integer literal)
I can work on this sometime soon when I get some free cycles.
Oh my, I really need to start sleeping enough, I didn't mean to type that and even thought about it in my head as a counter example but mis-coordinated the typing
I'm sympathetic to making error messages more accessible to new users, but it's not obvious to me that this proposal accomplishes that.
I'm not sure I understand how "cannot take the address of the constant value 5" or "cannot take the address of integer literal 5" is clearer to beginners than "cannot take the address of 5", or how it explains why the value is not addressable. All it does is further emphasize that "5" is a constant value or integer literal, which I expect users already know. (If not, should we emphasize that every time they misuse 5?)
I also don't really like the "unaddressable because it is an integer literal." It's actually unaddressable because it's not one of the cases the Go spec enumerates as addressable: https://golang.org/ref/spec#Address_operators
Is there objective evidence that any of these error messages would be more intuitive to users? What error messages do compilers for other languages emit in similar situations?
It's also noteworthy that constants are not addressable, not just literals.
A better error message would be a lot more useful though in the following case, which is probably what I should have led with: https://play.golang.org/p/G_IxBn_xRz1
I don't have any objective evidence right now. Currently doing this from my phone, I'll look into it when I can though.
I'll admit named constants are a little more compelling, since names can also refer to variables, which are addressable. Similarly, for certain indexing expressions (map and string indexing, and indexing of non-addressable arrays), since other syntactically identical index expressions are addressable.
I think elaborating the error messages could be reasonable when syntax alone is insufficient to explain why the expression isn't addressable.
However, I'm curious what error folks suggest to use for:
Maybe something like:
I.e., drill down past the field selections and array indexing to identify the root non-addressable expression.
What @mdempsky said.
I think the error message is pretty clear, but we could go along the route chosen for binary operators. For instance, for "a" - "b" we get:
Analogously, here we could report:
But it really says the same thing, slightly less elegantly.
But I'm also not clear which part of the error message is "repulsive" to newcomers. If one is truly a newcomer, I suspect it's not even clear that & means "take the address" - so a peek into the spec is warranted anyway. If one comes from C, the error message seems "obvious". Maybe this is better:
Either way, this doesn't need to be a proposal. If a convincingly better error message comes along, I'm ok with changing this; but I don't see the current error as overly problematic.
These aren't quite the same, if we make the second one more like the first, the error message is a lot more useful:
with literal values
with named constants
with function calls
a "catch all" error message for expressions that really fit with any the above
I'd argue against using "invalid operation" for more error messages. While technically accurate (the expression is an operation expression and it's invalid), I think when most users see "invalid operation," they think of https://www.google.com/search?tbm=isch&q="invalid+operation" and we might as well just say "error".
I think "cannot take address of foo (foo is a constant)" is better than "invalid operation: &foo (operator & not defined on constants)". The former tells you directly what the error was (cannot take address), and gives you additional details as to why that's the case (foo is a constant). The latter instead tells you something that experienced Go programmers already know (you can't take the address of constants) and leaves it to you to infer how that's relevant here (foo is a constant).
Also, I think the error message "invalid operation: &m.f (operator & not defined on map index expressions)" is misleading, because m.f is not a map index expression; it's a field selection expression. But it's non-addressable because of the m map index expression.
You're definitely right about that, and I've now removed that example. It should just be caught by the "catch-all" if we do the "invalid operation" route.
Something great about the