mozilla/rust — pull request #2037 by nikomatsakis (2012-03-21 03:34:12+00:00)
Title: WIP: distinguish inferable types from non-inferable types

This is a "work in progress" refactoring I wanted some feedback on. The idea is to separate out the representation of types into "types used during inference" (`ty::t_i`) and "types during the rest of compilation" (`ty::t`). One immediate effect of this is that `ty_var` is no longer a member of `ty::t`, so we no longer need to check for it and "fail" all over the place, as we used to do. The eventual goal is to make more things inferable in a more powerful way: e.g., fn protos, integer literal suffixes, regions, etc, all without affecting the `ty::t` type as a whole.

Both `ty::t` and `ty::t_i` are defined based on a common base set of types called things like `ty::sty_base`, `ty::fn_ty_base` and so on. These types are parameterized by a generic type `T` which represents the "type of a type". This is the famous "Curiously Recurring Template Pattern", or CRTP as pcwalton likes to call it. For the most part there is very little duplication of code, though some of the type declarations can be a bit mind-bending. Generic functions that operate over both `ty::t` and `ty::t_i` (such as `fold_ty`, `walk_ty`, and even unification) are currently coded using ifaces and impls. This can probably be improved further and ultimately made much nicer using traits.

Currently the code type checks but I cannot run it because the stage0 compiler fails with an obscure error during trans. As far as I can tell the patch is exposing a bug in monomorphization. I have tried to narrow down the problem but so far haven't produced anything useful. @marijnh if you are interested in taking a look lemme' know. :)