As I wrote in the previous post, I'm pretty convinced that racer should be using rustc to interrogate the type of expressions. This would enable racer to perform more accurate completions (and potentually complex refactorings in the future). Currently racer does some of its own type inference, but getting this right is error prone and I think long-term probably a dead end.
However the nice thing about racer doing its own type inference is that it can still work in the face of unfinished code, and also be very fast (because it can work incrementally, take shortcuts and avoid doing a lot of the work that rustc does). The downside is that hand-rolling rust type inference is a lot of work and I don't have much spare time.
Initially I was wondering if racer could approach the type inference problem by isolating the target expression and constructing a smaller representative program around it. The program would be quicker to compile by rustc but have same type expression output. This is essentially the approach racer currently takes with parsing.
Unfortunately after attempting a few hand written examples I realised this would be a very complex approach. E.g. consider this piece of code from libsyntax parse/parser.rs and imagine you want to construct a program to extract the type of the |p| argument:
let tts = try!(self.parse_seq_to_before_end( &token::CloseDelim(delim), seq_sep_none(), |p| p.parse_token_tree() ));
Racer would need to incrementaly resolve the types of a whole bunch of expressions before it could reasonably construct a representative program to run through rustc in order to find the type of 'p'. I suspect this work is similar in scope to completing racer's existing hand-rolled type analysis, which kind of defeats the point.
So the other approach is to run the rustc type inference over whole crates, including imports, and somehow get this fast enough for a good user experience. I'm trying to figure out how best to accomplish this. (Ignoring unfinished code for now)
I started by putting together a spike which attempts to use rustc to run a full type-inference pass on some code. I had to create a copy of the rustc_typeck crate (called mytypeck) in order to get access to the private innards.
(N.B. rustc changes frequently so it is likely that the mytypeck crate will get out-of-date very fast)
The approach I currently intend to persue is to maintain an ast and side tables of all the items in a crate, but no function bodies, (a 'skeleton ast' if you will), and then somehow patch the ast with an individual function body and get the side-tables updated in order to obtain the type of an expression contained within. The function body may be need to be artificially constructed by racer to handle unfinished code. The skeleton ast would need to be constantly updated as the item signatures are updated.
This is all uninformed speculation, but I'm a bit limited with spare time and wanted to get something written down to encourage some chat and input from people with more experience. Am I on the right track?