[rust-dev] Bikeshed proposal to simplify syntax

Graydon Hoare graydon at mozilla.com
Fri Jul 13 17:18:25 PDT 2012

On 12-07-12 11:41 PM, Sebastian Sylvan wrote:
> Hi Rust team! First of all, congratulations on the 0.3 release!

Thanks. The whole team continues to impress me too, the amount of work 
this time around should not be understated (and not just churn; really 
thoughtful and high-quality refactorings, a lot of hard problems).

> I have a bikeshed proposal to selectively simplify Rust's syntax in a
> way that has the side benefit of applying "negative syntactic
> pressure" on expensive constructs. It boils down to this: remove all
> special syntax for heap allocations and heap pointers.

Thus ~T becomes uniq<T>, ~expr becomes uniq(expr), etc?

> Allocating a block of
> uninitialized memory of type T might be heap_alloc<T>(), with the
> normal literals used to initialize it.

Note: we don't support allocating uninitialized memory.

> Now, this sounds a bit crazy, and I'm pretty sure it won't be adopted,
> but I'd appreciate it if you gave it a moment's serious consideration
> and thought about what the impact would really be. I don't think it
> would cost as much as you might initially think (modern C++ does
> essentially this with all the shared_ptr etc., and many of the actual
> allocation calls are hidden behind constructor functions anyway) and
> there are strong wins.

I agree that modern C++ does this, and it does relieve some syntactic 
pressure (slack which C++11 seems to have gleefully soaked up). I don't 
think that users having to write shared_ptr<foo> rather than @foo is 
quite so clearly a "strong win" in our case, though.

> 1. Reduce the complexity of the syntax. In particular, reduce the
> amount of "special symbols". You've all heard jokes about Perl looking
> like line-noise, I'm sure.

I think this is a bit unfair; perl isn't even a context-free grammar. I 
think we're in the same ballpark as Objective-C right now. And shrinking.

> Reducing the amount of special characters
> you need to know about before understanding code is a win.

True, but it's in tension with conciseness / expressivity. I initially 
erred very much on the side of maintenance programmers in the design 
(verbosity and clarity over expressivity) and am gradually being dragged 
back towards the expressive side. This is one of numerous tensions in a 
language; almost nothing is a pure win/lose, all is tradeoffs.

> Getting rid
> of some of the symbols and treating those types in a more regular way
> would also kill a lot of design problems like "what does a heap
> allocated fixed-sized vector literal look like"?

Unless you're planning on making our type parameters carry integer types 
-- danger! -- this proposal doesn't help there.

> importantly, it would make it easier to see what a complicated type
> means because it would follow simple nesting rules that you already
> understand, because it's the same rules that apply to user-defined
> types. It would also make library-pointer types look like the "real
> thing" (e.g. arc<T>).

But they aren't. The compiler is doing a bunch of open-coding on those 
pointer types, including reasoning about the initialization-state of the 
pointee memory, enforcing kinds, generating visitors that walk through 
them, and pattern-matching on the structure.

> 2. Apply selective negative pressure to constructs which should be
> avoided if possible.

Yeah. Again, this is in tension with "letting users write what they need 
to". Rust initially prohibited even _cyclic_ memory and made all private 
memory copy-on-write. Guess what was the first and most pressing request?

Second-guessing users and telling them they don't want to do what they 
_do_ want to do is ... generally a losing game. @ and ~ are not 
beautiful, and surely if someone can avoid reaching for them I wager the 
noisiness and measurable performance cost is sufficient deterrence to 
make the user think twice. I might be wrong, but ... the largest single 
case of allocation is "", for example, and we _just_ started making it 
obvious that those allocate.

(And we still have essentially _no_ code that emits static constants as 
read-only memory, aside from fixed-size and slice-strings, and integer 
constants. So ~"abc" actually hits the allocator every time, despite 
being a constant.)

> preferred pointer should be the borrowed pointer. IMO, Rust makes it
> far too easy to allocate memory on various heaps - just add a little
> sigil and you're done. C makes you appreciate the implications of what
> you're about to do when you type "malloc".

Fair. It's true that we allocate too much presently. I believe a lot of 
this comes from a combination of incomplete constant optimization (see 
above), hiding the uniqueness of vectors and strings (no longer done as 
of 0.3), and not having had the requisite technologies at our disposal 
when writing the compiler, first-pass: our closures were weak, 
borrowed-pointers nonexistent, interior-vectors nonexistent, arenas 
nonexistent, etc. I would like to get some experience with using the new 
technology in earnest, before looking at blunter instruments as you're 
suggesting here.

(Also: nobody's done the no-gc lint pass yet, but I fully intend to 
provide it. Might just do so idly now, it's quick work)

> Anyway, as I said, I don't think this will gain much traction, but
> it's one of those small niggles that I would do differently if I was
> designing the language, so I thought I'd float it for consideration.

Sure. I appreciate the concern, I just think the weight of evidence 
isn't _so_ clear that rust code "always" allocates too much, vs. the 
current code doing so. I think it'll take some time to see. Also there 
are a bunch of other factors at work, as I point out above (in terms of 
the compiler knowing all about these pointers).


More information about the Rust-dev mailing list