Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove the F-impl-trait-in-bindings code #86729

Closed
nikomatsakis opened this issue Jun 29, 2021 · 1 comment · Fixed by #87141
Closed

remove the F-impl-trait-in-bindings code #86729

nikomatsakis opened this issue Jun 29, 2021 · 1 comment · Fixed by #87141
Assignees
Labels
F-impl_trait_in_bindings `#![feature(impl_trait_in_bindings)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

This code is not implemented in the correct way, and it is common source of ICEs and other problems. We should remove this logic for now and simply report errors when impl Trait is used in let position.

@nikomatsakis nikomatsakis added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. F-impl_trait_in_bindings `#![feature(impl_trait_in_bindings)]` F-min_type_alias_impl_trait labels Jun 29, 2021
@spastorino spastorino self-assigned this Jun 29, 2021
@bors bors closed this as completed in a72c360 Jul 20, 2021
@oli-obk
Copy link
Contributor

oli-obk commented Jul 22, 2021

Some more explanation for future archeologists:

impl Trait in bindings does various things that are very different from each other.

const FOO: impl Trait = ...;

is an entirely different implementation from

let x: impl Trait = ...;
use(x) // doesn't know concrete type of X

But they attempted to share logic between each other and with type-alias-impl-trait and the already stable impl-trait-in-return-position.

Several refactorings and bug fixes later we ended up with spaghetti code. Attempts to refactor always ended up exploding. So we removed this feature (which works very differently on let bindings than the other features), and can now do the refactoring. We expect to reintroduce the feature in some form, but caveats may apply. The underlying problem is that impl-trait-in-bindings is expected to hide the type after the binding, but not before. All other uses of impl Trait have a clear boundary on the implementation side:

  • function return position: opaque outside the function, transparent inside
  • type alias impl trait: opaque outside the module, transparent inside
  • type alias impl trait in associated type: opaque outside the impl, transparent inside
  • const/static item type: opaque outside the item's initializer, transparent inside.

For let bindings, it is obvious for a human, but it gets weird for the compiler. Type-checking, in contrast to borrow-checking, has no real concept of the order of things. It simply builds up a graph for type inference and then kind of floods the graph with the information it has and either ends up successfully resolving everything or it gets an error. The problem is that once you know that a let binding's impl Trait is e.g. i32, this knowledge is commutative. So if you ask "is this specific impl Trait equal to i32" and you get yes, you will also get yes for "is i32 equal to this specific impl Trait". That also means that

let x: impl Debug = 5_i32;
let y = x + 1_i32;

will either compile (typeck likes this), or we have to patch typeck in weird (to me) ways in order to adhere the RFC.

Now... the question is how important that feature is. If it is mostly needed for tutorials and some rare cases, we could probably get away with

let x = hide!(5_i32, Debug);
let y = x + 1_i32; // ERROR

which expands to

let helper = || -> impl Debug { 5_i32 };
let x = helper();
let y = x + 1_i32; // ERROR

which could be more manageable on the compiler implementation side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-impl_trait_in_bindings `#![feature(impl_trait_in_bindings)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants