Skip to content

impl_trait_in_bindings is a breaking change #83021

Closed

Description

@oli-obk

The following program compiles without the impl_trait_in_bindings feature, but not with that feature. I believe this is because the way impl_trait_in_bindings is set up. If you look at

let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
self.fcx.instantiate_opaque_types_from_value(self.parent_id, o_ty, ty.span)
} else {
o_ty
};

you can see that enabling the feature gate runs a completely different algorithm instead of emitting a feature error when the feature gate is not active. Before stabilizing type_alias_impl_trait we need to make sure that we change all such occurrences of feature-gate based type processing.

#![allow(incomplete_features)]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_bindings)]
use std::marker::PhantomData;

trait MyIndex<T> {
    type O;
    fn my_index(self) -> Self::O;
}
trait MyFrom<T>: Sized {
    type Error;
    fn my_from(value: T) -> Result<Self, Self::Error>;
}

trait F {}
impl F for () {}
type DummyT<T> = impl F;
fn _dummy_t<T>() -> DummyT<T> {}

struct Phantom1<T>(PhantomData<T>);
struct Phantom2<T>(PhantomData<T>);
struct Scope<T>(Phantom2<DummyT<T>>);

impl<T> Scope<T> {
    fn new() -> Self {
        unimplemented!()
    }
}

impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
    type Error = ();
    fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
        unimplemented!()
    }
}

impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
    type O = T;
    fn my_index(self) -> Self::O {
        MyFrom::my_from(self.0).ok().unwrap()
    }
}

fn main() {
    let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0282]: type annotations needed
  --> src/main.rs:45:38
   |
7  |     type O;
   |     ------- `<Self as MyIndex<T>>::O` defined here
...
45 |     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
   |                                      ^^^^^^^^^^-------------
   |                                      |
   |                                      this method call resolves to `<Self as MyIndex<T>>::O`
   |                                      cannot infer type for type parameter `T`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Activity

  1. added
    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
    C-bugCategory: This is a bug.
    on Mar 11, 2021
  2. kpreid commented on Jul 10, 2024

    @kpreid
    Contributor

    This could probably be closed, because the feature in question was removed by #86729.

  3. Ralith commented on Sep 25, 2025

    @Ralith
    Contributor

    The feature was reimplemented in #134185. Should this be reopened? The playground link still fails to compile, although the errors are different, and no longer seem to depend on the feature being enabled.

  4. theemathas commented on Sep 25, 2025

    @theemathas
    Contributor

    @Ralith Changing the code as follows causes the code to compile, with or without the impl_trait_in_bindings feature.

    type DummyT<T> = impl F;
    #[define_opaque(DummyT)]
    fn _dummy_t<T>() -> DummyT<T> {}

    So, this issue can stay closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.F-impl_trait_in_bindings`#![feature(impl_trait_in_bindings)]`

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions