I'm surprised Go doesn't compile down to an IR language where these differences in syntax are represented in a single manner. Seems like different ways to write the same thing.
Go 1.5 was the first self-hosting release, with the Go compiler auto-translated from C to Go. But it was still fundamentally Ken's C compiler in Go syntax.
Every release since (Go 1.6, Go 1.7, Go 1.8, Go 1.9) has been cleaning it up and making it more Go like and less C like.
So, it keeps improving. Just remember the Hello World compiler we started with.
Also amusing in retrospect is that when Go first came out, despite having a very basic compiler at the time, people coming from scripting languages thought we were so fast.
Just for what it's worth, the way I'd fix that problem in the compiler would be to implement dead store elimination via global value numbering. With trivial alias analysis, the compiler would be able to detect that the result of the "duffzero" instruction (which I assume is a memset) is always killed by the "duffcopy" instructions and would eliminate it.
Not my area of expertise and it is yours, but if you eliminate a zero instruction before a copy instruction how can you be sure that doesn't affect other threads?
var x Int
// Pass x to a thread by reference
x = 0
time.Sleep(1000)
x = 1
How can you be sure that the other threads ever see it in time? they might be suspended for a whole second because a HDD needs to spin up or something like that.
So threads never seeing the value is already a valid outcome, so the compiler might as well always do that.
The answer to that one would be to embed thread-safety in the type system, aka. Rust.
For languages with less sophisticated type systems you get a choice between inefficiency (Go), or complicated rules which state that the programmer is wrong for coding that way (C).
Your "solution" is possible in many languages. It's just to give threads complete ownership of data they use. It doesn't require a special type system.
In general I don't think Rust actually adds much abstraction that isn't already in say Python. What it does is enforce tight constraints.
Not sure those optimisations are worth much. And it's only safety by forcing lowest common denominator code and making you justify everything to a dumb compiler. Rust serves a niche, but it is a tight niche IMO.
The memory dependence analysis must prove the memory is unaliased, which ensures among other things that no other thread can have a reference to it. Presumably in Go return pointers are guaranteed to be unaliased.
I hope this won't come out harsher than I intend to, but I'm so tired to hear this expression "not reinventing the wheel" to justify using third party code. This is not what it means.
Note that there is not a single wheel that was built once in prehistory and now every human gets it lent when they need it. People build wheels everyday to fit their needs, reusing the concept of wheel, that is, knowing that a circular object allows for smooth movements with less friction. The analogy in software development means that you've better know of designs that help you solve your problem, not that you should blindly use code built by someone else to bypass the whole problem solving. This is basically trying to use a bicycle wheel for everything. This may work well on an other bicycle, not on a car.
I thought the SSA backend was not replacing the Plan9 assembly, but that it was a phase that happened before the assembly was output (presumably SSA is a phase and not an IR?).
We should just fix the compiler.