`type` alias vs `use`


#1

Suppose I use a crate, that defines a type (struct or enum) Foo, is there a difference between:

extern crate foo;
pub type Bar = foo::Foo;

and

extern crate foo;
pub use foo::Foo as Bar;

?
I’m aware that type and use work differently for modules and generic types, but are they the same for simple types?

If not, in which one is preferred and why?

Also, why are there two very similar language features with such a different syntax?


#2

They are superficially similar, but only type can deal with type parameters.

use can not do this:

type Strings = Vec<String>;
type Map<I> where I: Iterator = HashMap<I::Item, String>;

I wouldn’t mind if use could serve both roles, but maybe its syntax would become quite contrived then.


#3

This is convergent behavior, really. pub use is for creating a module facade where the internal structure is different; type is for creating a new name for a type, especially one that’s quite lengthy (usually because of type parameters).

If what you’re doing is literally re-exporting another type under a new name, I think pub use as is more appropriate. But if you’re “constructing” a type by specifying type parameters, which pub use as does not support, you’re really not ‘re-exporting,’ and that’s why type is more appropriate.


#4

There’s a particularly annoying limitation related to generic enums that I thought I’d mention as I’ve run into it a few times:

If you have pub enum Foo<T> { Bar(T), Baz }, and you wish to re-export (or alias) this enum with the type parameter filled, there is no way to do so that will also allow downstream users to access the aliased enum’s variants.

pub type Qux = Foo<i32>; will provide you with a type Qux that you can use solely as a type, however you cannot use it to access the enum’s variants (Qux::Baz will fail to compile).

On the other hand, pub use path::to::Foo as Qux; does let you access variants via Qux, but of course does not provide a way to fill in the type parameter.

You can find some discussion around the issue here.


#5

I’d argue that both use cases are essentially the same thing.
It would have been nice to have a unified syntax but I guess it’s too late now.

In C++ there’s a similar “issue” with typedef and using.
I think the trend is to use using for everything, because it is strictly more powerful.


#6

What’s the reason for this limitation of type aliases?


#7

Something to do with enum variant resolution occurring at a different stage to type item resolution. I believe that it is now considered a bug, and that eventually this “limitation” of type aliases will be lifted. The issue I linked to goes through this in more detail.