-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
Proposal Details
I had recently decided to give a try on this language, because I have been hearing many positive things about it, specially about its performance, so I thought why not give it a chance. But when I tried to make my first non trivial program something very strange occurred to me. A cryptic error message: err is not a type. How can this be? — I thought to myself — isn't err part of standard library of the language itself?
example of the code I had when I first experienced this problem:
// example.go
package program
import "fmt"
type error struct {} // here only for the purpose of illustration. in my specific case, the type was `err` and it was imported from io/fs.
func main() {
var error *error
if error != nil {
fmt.Println("An error occurred")
}
var anotherError *error
if anotherError != nil {
fmt.Println("Another error ocurred")
}
}As all experienced users already know, golang works with flat namespaces which means that all identifiers (for types, variables and functions) lives in the same space and are all subjected to shadowing from each other. this in itself is fine. might be strange to someone from a C++ background, but its something we can learn to deal with.
But here is the thing, I didn't know this at first and I strongly believe that no beginner would know this too. So I spent a couple hours trying to figure out why this was hapenning.
At first I thought I had a broken golang installation, so I reinstalled it. Still had the problem. Then I thought it was something on my OS which was causing this problem, maybe a conflict due to outdated packages (I use Debian, btw), so I tried compiling the code online through compiler explorer. Still same problem.
Then at this point I had pretty much given up on the language and uninstalled it from my machine.
... But this still annoyed me. I had to get this to work, there is no way I can't get this thing to compile. I then came back at it and spent a couple more minutes searching, which led me to this issue: #33668 where a guy named @bcmills replied with the following:
Go has a flat namespace: variable names and and type-names can (and do) shadow each other.
That's it!
I finally had discovered the problem. Went back to my code and fixed the issue.
But this shouldn't have happened at all. All this waste of time happened because the compiler gave a meaningless error message. So my proposal here is to improve on this.
instead of reporting:
./example.go:16:23: error is not a type
why not
./example.go:16: error refers to a variable, but is being used as type here.
./example.go:10: error was re-declared here as a variable (originally declared as a type at example.go:7).
or anything similar to this, really. would make the life of many beginners way easier and potentially save time of many users who came from a language where flat namespaces is not a thing.
And that's pretty much it! thanks to everyone who read this through. I really hope you guys consider this as it would make the language more accessible in my opinion. 😁.
Template
-
Would you consider yourself a novice, intermediate, or experienced Go programmer?
Novice.
-
What other languages do you have experience with?
C++, C, C#, TypeScript
-
Would this change make Go easier or harder to learn, and why?
It would certainly make the life of a beginner easier, because a good error message is way more convenient than having to spend hours trying to figure out something that is a language design decision.
-
Has this idea, or one like it, been proposed before?
A similar idea had been discussed back in 2017, cmd/compile: add hint to type errors when builtin identifiers are shadowed #22822
-
If so, how does this proposal differ?
Rather than differing, my proposal is a continuation of the suggestion given here.
-
-
Who does this proposal help, and why?
Beginners, for the same reason given before. Good error messages makes any language more approachable.
-
What is the proposed change?
-
Please describe as precisely as possible the change to the language.
Extend the compiler diagnostics capabilities to add ways for detecting and warning about identifier collisions resultant from shadowing.
-
What would change in the language spec?
Nothing. This is about compiler diagnostic messages, which does not depend on changing the specification of the language itself.
-
Please also describe the change informally, as in a class teaching Go.
We should add a diagnostic message to inform the user when a type identifier shadowing occurred and where it occurred.
-
-
Is this change backward compatible?
Yes. Any code that already compiled before this change will continue to compile without problems.
- Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
-
Show example code before and after the change.
There would be no changes to any code what so ever.
-
What is the cost of this proposal? (Every language change has a cost).
-
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
Only the compiler itself would be affected as far as I am concerned.
-
What is the compile time cost?
Would increase the compilation time a bit the since the compiler now would have to traverse back the AST to find where the identifier was first declared and check against its re-declaration which caused the shadowing.
-
What is the run time cost?
Zero.
-
-
Can you describe a possible implementation?
I would have to get more familiar with how the compiler is implemented, so right now I am unable to give any meaningful suggestion on how such extension would be implemented. That said, this should be fairly straight forward to anyone who picks this issue and understand how the diagnostic emission process is handled internally.
-
Is the goal of this change a performance improvement?
No.
-
Does this affect error handling?
No.
-
Is this about generics?
No