
The Periodic Table of Rust Types - lifthrasiir
http://cosmic.mearie.org/2014/01/periodic-table-of-rust-types/
======
carterschonwald
I think this a great way of presenting type features that interact! props to
the author for cooking it up

~~~
_pmf_
> I think this a great way of presenting type features that interact! props to
> the author for cooking it up

It's a great way to present it, but like Scala's infamous "Periodic Table of
Dispatch Operators", stuff like is rather off putting. Why use crude sigils
when you could just as well use easily understood keywords (like ref, out,
unsafe etc. in C-Sharp)?

~~~
Ygg2
Funny enough, ~ sigil will probably be retiring in favor of box.

    
    
        let x = ~"Thing"; //old code
        let x = box Thing // new code probably
    

Note: I said probably because it's probably because:

A) Not sure it will be implemented

B) Not sure if that will be syntax

\--- PS. Any link to dispatch operator periodic table?

Also I take your scala and raise you a Perl:
[http://glyphic.s3.amazonaws.com/ozone/mark/periodic/Periodic...](http://glyphic.s3.amazonaws.com/ozone/mark/periodic/Periodic%20Table%20of%20the%20Operators%20A4%20300dpi.jpg)

~~~
Djehngo
That's a shame, I happen to like the use of sigils to denote pointer types, to
my eyes it makes code a lot easier to read.

Out of curiosity why are they making the change? And will they add the `let x
= box Thing` syntax or as an optional addition to the language or will it
fully replace the old `let = ~Thing` syntax?

~~~
Ygg2
I think the idea is to make heap allocation taxing to type. Basically the
sigil is too easy to type, so its easy for application to just allocates a
whup ass of memory. So, this way it might force you to think about each
allocation.

------
didgeoridoo
Aww, I thought this was going to be a table of metal oxides and their chemical
& physical properties.

~~~
kps
Ah, you're looking for Hacksaw News.

So… would a dialect of Ruby without side effects be called Corundum?

------
noelwelsh
This is great, and just what I needed to organise Rust types systems in my
head. This should definitely be a part of the official documentation.

------
dnautics
can we just make it "table"? There are no periodic trends that I can see.

~~~
dbaupp
There are some trends. Types to the right are "subsets" of types to the left;
e.g. a &mut T can coerce to a &T, similarly, you can box a T into a ~T, or
take references to get an &mut T or &T.

~~~
dnautics
periodicity refers to (originally) that the trends are cyclical with respect
to atomic mass - we now know that it's with respect to atomic number and that
the period increases (2 - 8 - 18 - much more) but nonetheless between multiple
rows there's an increasing valence. Hence there is a repeating aspect 'period'
driven by a connection between row n and n+1 (row n+1 immediately follows row
n in atomic number). There's no connection between row n and row n+1 in this
table of rust types. The vertical organization is completely arbitrary, there
is no ascending value across the table, and therefore it's not periodic.

------
mcguire
Structure types?

~~~
steveklabnik
They're of type T.

------
TylerE
This all seems like a mis-feature. Smells of C++.

~~~
pcwalton
Could you elaborate as to what you'd prefer instead?

~~~
TylerE
A simpler language.

~~~
dbaupp
And how do you propose to get a simpler* language with equal control and
safety?

*I actually think Rust is relatively simple: once one "gets" ownership, then most of the other hard things follow from it, including lifetimes.

~~~
TylerE
Look at nimrod ([http://www.nimrod-lang.org](http://www.nimrod-lang.org)).

~~~
girvo
I'm a massive Nimrod fan, but those safety guarantees are void once you use
manual memory management. What Rust gives you is safety _with_ memory
management. Nimrods GC and type system are both really powerful, but Araq and
I were chatting about Rusts type system on irc for a reason...

~~~
TylerE
I'm probably in the minority here, but I think the answer is "so use a GC".
The number of people on earth that I would trust with my life to correctly
manage memory in a complex application is very small.

~~~
pcwalton
> The number of people on earth that I would trust with my life to correctly
> manage memory in a complex application is very small.

The Rust compiler checks it for you, so you don't have to trust anyone. :)

~~~
tel
What kind of guarantees does the type system provide? Can I say that no
terminating/productive Rust program leaks memory, full stop?

~~~
kibwen
Rust's type system statically guarantees that memory will never be accessed
after it is freed, so no segfaults, no use-after-frees, no double-frees, no
iterator invalidation, etc. It also statically eliminates data races between
concurrent tasks.

In the past Rust has attempted to use the type system to prevent memory leaks
in certain cases, but the features that attempted to do so were deemed overly
restrictive to use for practical purposes. Nowadays I'm sure it's possible to
leak memory if you try. Honestly I've never heard of a Turing-complete
language whose type system can provide such a guarantee.

~~~
haberman
Doesn't it make a stronger guarantee, that you cannot cause an invalid
dereference? In addition to what you mentioned, this would also cover bounds-
checking, trying to dereference a pointer that was never allocated, etc.

Also does it enforce that memory is consistently used as a single type? Can
you allocate a byte array and then cast it to an appropriately sized array of
integers?

~~~
kibwen

      > Doesn't it make a stronger guarantee, that you cannot 
      > cause an invalid dereference?
    

I'm not knowledgeable enough to answer that question precisely.

However, I can tell you that Rust's type system is _not_ strong enough to
obviate bounds checking. I hear you'd need something like Idris' dependent
types for that. Rust bounds checks arrays dynamically (there are `unsafe`
functions available to index an array without bounds checks), and avoids
bounds checking on arithmetic by guaranteeing that fixed-sized integers will
wrap on overflow (which is gross, but might be changed to fail-on-overflow if
it doesn't hurt performance too much).

    
    
      > Can you allocate a byte array and then cast it to an 
      > appropriately sized array of integers?
    

You can't do this in safe code, but you can in `unsafe` code via the
`std::cast::transmute` function, which does still enforce that both types are
the same size.

~~~
haberman
> However, I can tell you that Rust's type system is not strong enough to
> obviate bounds checking.

That's a bummer. It seems doable, but maybe it is too complex.

> avoids bounds checking on arithmetic by guaranteeing that fixed-sized
> integers will wrap on overflow (which is gross, but might be changed to
> fail-on-overflow if it doesn't hurt performance too much).

That would be nice as a default, but I'd be afraid it would hurt performance
too much for numerical code. You'd definitely want a way to express arithmetic
should be allowed to overflow (ie. that omits the check).

On a related note, one thing that is sorely missing in C and C++ is a way to
test whether a value will overflow when converted to a different type (I wrote
a blog article about this point: [http://blog.reverberate.org/2012/12/testing-
for-integer-over...](http://blog.reverberate.org/2012/12/testing-for-integer-
overflow-in-c-and-c.html))

~~~
dbaupp
> That's a bummer. It seems doable, but maybe it is too complex.

In general, eliminating runtime bounds checking is solving the halting
problem.

    
    
      let v = [1, 2, 3];
      if halts(some_program) { v[1000] } else { v[0] }
    

Of course, this doesn't meant that it's impossible in a subset of cases, e.g.
people are doing work on fast range analysis for LLVM, which would be able to
remove some of the bounds checks sometimes: [http://code.google.com/p/range-
analysis/](http://code.google.com/p/range-analysis/) (that analysis also
applies to the arithmetic, and apparently only makes things single-digit
percent slower (3% iirc).)

~~~
haberman
> In general, eliminating runtime bounds checking is solving the halting
> problem.

Your example does not convince me that this follows. In cases where the
compiler cannot statically prove which branch will be taken, I would expect it
to require that either path can be executed without error (so in your example
compilation would fail). But you could use static range propagation to allow
code like this (given in C++ syntax since I'm a Rust novice):

    
    
      void f(int x[], unsigned int n) {
        n = min(len(x), n);
        for (int i = 0; i < n; i++) {
          x[i];
        }
      }
    

Maybe not the greatest example since I would hope that Rust+LLVM would hoist
its internal bounds-check to emit something very much like the above anyway. I
guess intuitively I just hope that there's more that can be done when it comes
to static bounds-checking.

