Also replace derived types (map_type, collection_type, etc.). As we'll change data_type's definition, this reduces the number of places that need to be modified later, and is more readable.
Since origin tends to cast around, we should allow that too, by exposing the implementation type and using a shared_ptr instead of a value class.