[rust-dev] Typeclasses turn trait-er: status update

Lindsey Kuper lindsey at rockstargirl.org
Mon Aug 20 17:01:01 PDT 2012


Hi everyone,

I thought I'd post a progress report on traits in Rust.  For a
high-level overview of what traits are and where Rust is headed with
them, I'll quote from the development roadmap [0]:

  Traits are interfaces that carry method implementations and
  requirements on the self-type; they can be used to achieve code reuse
  without introducing much of the pain that comes from conventional
  inheritance: they can be mixed in any order, can be declared
  independent from the type they affect, and are compiled independently
  for each type that implements them (indeed, will inline and specialize
  exactly as any other method will). This work will replace the iface
  keyword with trait and provide (hopefully) most of what people miss
  when writing rust in OO style.

The "method implementations ... on the self-type" mentioned in that
description are the "default methods" that I described in my talk a
week and a half ago [1].  They're also called "provided methods" in
the traits literature, whereas method signatures like the ones Rust
has had in ifaces all along are called "required methods".  I use the
terms "default method" and "provided method" interchangeably.

In the talk, I said that I was going to try to get default methods
working by the time I left.  Since my internship ended on Friday, you
might be wondering: did I manage to do that?  Sort of!  As of last
week, trivial default methods work; for instance, you can write:

  trait Cat {
      fn meow() -> bool;
      fn scratch() -> bool;
      fn purr() -> bool { true } // a default method
  }

  impl int : Cat {
      fn meow() -> bool {
	  self.scratch()
      }
      fn scratch() -> bool {
	  self.purr()
      }
      // notice that we don't have to implement purr
  }

  fn main() {
      assert 5.meow();
  }

(For comparison, the equivalent Haskell would be something like
https://gist.github.com/3346078 .)

For default methods to actually be useful, though, we have to be able
to use "self" in them.  For instance, in the example I gave in my talk
of an Eq typeclass with a provided method `isNotEq`, we want the body
of `isNotEq` to be something like `!self.isEq(a)`.  This is still not
working in Rust.  Right now, methods that make self-calls raise an
"unimplemented type_of: ty_self" ICE in trans.  (In the specific case
of Eq, there's an additional issue to confront, because the provided
method also takes an argument of type self, and right now the
typechecker is unhappy with provided methods that take or return
arguments of type self; that will also need to be fixed.)  So, as of
today, it is hard to write code with nontrivial default methods.  But
it should not be terribly difficult to fix, and I'll be working on it
later this week.

Now that default methods are beginning to work, it is becoming more
clear that certain patches of awkward code in the compiler are awkward
because they are workarounds for a lack of default methods.  It would
be useful to keep track of those so that we can more easily fix them
up once default methods are fully working.  So, if you see one, you
can help by opening an issue, adding a FIXME in the code tagged with
the issue, and marking the issue as blocked on issue #2794 (and thanks
to everyone who has already started to do this).

Finally, as of Friday, the "iface" keyword no longer parses; it's all
"trait" all the time, now.

Cheers,
Lindsey

[0]: https://github.com/mozilla/rust/wiki/Note-development-roadmap,
"Extend interfaces to full traits" under "OO-system changes"
[1]: https://air.mozilla.org/rust-typeclasses/


More information about the Rust-dev mailing list