Lifetimes (typically referred to as "regions" in the literature) come most directly from Cyclone (which first applied Tofte & Talpin's work on regions for ML-ish languages to the systems space). Type-level ownership tracking goes back to ATS (or possibly one of its predecessors, not sure) as well.
What rust does well is package up a lot of this knowledge into something that's actually a usable tool. The ATS compiler spits out some of the worst error messages I've ever seen, and while Xi has done some really incredible groundbreaking stuff, he doesn't have the kind of design sense that it takes to make tools that developers can actually use. It's the little stuff, really -- error messages, tooling, documentation. Some of the instructional material reads like stream-of-conciousness, and clearly doesn't have a specific audience in mind:
http://ats-lang.sourceforge.net/DOCUMENT/INT2PROGINATS/HTML/...
The biggest fundamental technical difference is dependent types. The Rust community has been flirting with some more limited forms of this; search for "const generics" to see what they're up to.
ATS's version of dependent types is of a different flavor than what's available in e.g. Idris/Agda/Coq, and not as powerful, but still able to do some really impressive things. There are still a lot of low-level tricks that folks regularly pull in C that can't be done in a type/memory-safe way in Rust, but can in ATS. This paper gives a neat example of converting an array to a linked list in-place, which I think is pretty mind-blowing:
http://www.ats-lang.org/MYDATA/SPPSV-padl05.pdf
It's also one of the better descriptons of what's special about ATS.