Heads up: 2024 edition will change `impl Trait` behavior

156 points watermelon_exe

Posting this here for more awareness, since I think there are some people that might not know about this change.

This is about: lifetime_capture_rules_2024 / rendered

The rfc is quite long so I'll demonstrate the core changes with this code snippet:

// 2021 - works because `impl Sized` doesn't capture `'a`.
// 2024 - errors because `impl Sized` captures *all* generics.

fn foo<'a>(a: &'a usize) -> impl Sized {
    *a
}

fn main() {
    let val = {
        let a = 0;
        foo(&a)
        //   ^ error[E0597]: `a` does not live long enough (edition 2024)
    };
}

plaground

Afaik, there are two nightly-only workarounds for "precise" capturing (opposed to capturing all by default):

#![feature(type_alias_impl_trait, precise_capturing)]

// First workaround relies on `type_alias_impl_trait` (TAIT).

type FooRet = impl Sized;

fn foo<'a>(a: &'a usize) -> FooRet {
    *a
}

// Second workaround relies on a new feature called "precise capturing",
// which has landed some days ago on nightly.

fn foo2<'a>(a: &'a usize) -> impl use<> Sized {
    *a
}

fn main() {
    let val = {
        let a = 0;
        foo(&a)
    };
    
    let val = {
        let a = 0;
        foo2(&a)
    };
}

playground

EDIT:

Extra demo with impl Trait in traits: playground.