Rust: make `pub type foo = bar` and `pub use bar as foo` interchangable in next edition

Created on 10 Jun 2020  路  6Comments  路  Source: rust-lang/rust

Right now renaming a type and re-exporting it via a type alias can be a breaking change whereas re exporting it under the new name is not a breaking change. As far as I know the only difference between the two is how they interact with tuple-struct constructors:

pub struct MyStruct(u32);

pub use self::MyStruct as PubUse;
pub type PubType = MyStruct;

fn main() {
    let _ = PubUse(5); // OK
    // let _ = PubType(5); // Doesn't work
}

This happens because tuple struct constructors are just free functions with the same ident as the type they're constructing. use statements bring in items from all 3 namespaces that match the given ident but type items only alias the type itself.

This can be fixed by making it so that the compiler generates a constructor for the alias when it sees that the RHS of the type alias is a tuple-struct. This would be a breaking change because users can already define a free function with the same name as the type alias, which people do currently do to add the necessary constructor to work around this very issue.

To resolve this @joshtriplett has recommended the following steps:

  • [ ] implement the alias constructor fix as a feature gated PR
  • [ ] add an allow by default lint to detect free functions that would conflict with the newly generated constructors

    • [ ] do a crater run with the above lint set to deny to measure the impact of this change

    • [ ] add this lint to the future-compatibility lint group

T-lang lang-team-202x-edition

Most helpful comment

It it possible there's anyone relying on this for the opposite, exporting a type while intentionally not exporting the constructor? (And _not_ providing a function of the same name.)

I guess it doesn't hide PubType { 0: 5 }, though...

All 6 comments

It it possible there's anyone relying on this for the opposite, exporting a type while intentionally not exporting the constructor? (And _not_ providing a function of the same name.)

I guess it doesn't hide PubType { 0: 5 }, though...

Maybe a clippy rule suggesting to use pub use instead of pub type for trivial tuple struct reexports would help people avoid these pitfalls in the current edition?

@scottmcm If someone is relying on that, they could avoid exporting the tuple struct's fields, which makes the constructor private.

Doesn't pub type PubType = MyStruct; differ in semantics to the re-export if there are obligations introduced (or not included) in the type? We don't currently perform many checks on PubType or MyStruct until usage (which is why adding WF-check to types is a breaking change because if PubType isn't used but not WF we would start breaking builds).

Based on discussion in the lang team meeting today:

We'd like to take this through the new lang team process. (That should just involve moving this issue to the rust-lang/lang-team repository using the major change process template.)

This may potentially interact with name resolution. One challenge is that the name resolution code doesn鈥檛 (today) have to look at the RHS of a type alias. cc @petrochenkov

One common use case for this involves aliases that fill in specific type parameters for generic types:

struct Foo<T>(T);
type Bar = Foo<u32>;

The result doesn't currently work as a constructor (Bar(42)), or as a pattern.

This won't just interact with name resolution, this is almost entirely a name resolution feature.
It is possible to do this without heroic efforts, but with significant limitations (same limitations as imports of type-relative associated items).

type Alias = Something; will have to always reserve (possibly unusable) slots in both type and value namespaces regardless of the constructor actually existing or not.
So

type A = u8;
fn A() {}

will become ill-formed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

withoutboats picture withoutboats  路  308Comments

Mark-Simulacrum picture Mark-Simulacrum  路  681Comments

nikomatsakis picture nikomatsakis  路  236Comments

withoutboats picture withoutboats  路  213Comments

cramertj picture cramertj  路  512Comments