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

Missing implied lifetime bounds for method with GAT in return position #102968

Open
Pointerbender opened this issue Oct 12, 2022 · 1 comment
Open
Labels
C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@Pointerbender
Copy link
Contributor

The following example fails to compile:

pub trait Foo<'foo>: 'foo {
    type Bar<'bar>
    where
        'foo: 'bar;

    fn baz(&self) -> Self::Bar<'_>;
}

impl<'foo, T, U> Foo<'foo> for T
where
    T: Deref<Target = U> + 'foo,
    U: Foo<'foo>,
{
    type Bar<'bar> = <U as Foo<'foo>>::Bar<'bar>
    where
        'foo: 'bar;

    fn baz(&self) -> Self::Bar<'_> {
        (**self).baz()
    }
}

The error message is:

error[E0478]: lifetime bound not satisfied
  --> examples/implicit.rs:69:5
   |
69 | /     fn baz(&self) -> Self::Bar<'_> {
70 | |         (**self).baz()
71 | |     }
   | |_____^
   |
note: lifetime parameter instantiated with the lifetime `'foo` as defined here
  --> examples/implicit.rs:60:6
   |
60 | impl<'foo, T, U> Foo<'foo> for T
   |      ^^^^
note: but lifetime parameter must outlive the anonymous lifetime defined here
  --> examples/implicit.rs:69:12
   |
69 |     fn baz(&self) -> Self::Bar<'_> {
   |            ^^^^^

For more information about this error, try `rustc --explain E0478`.

This error message is a bit surprising, because the lifetime bounds are specified on the generic associated type: type Bar<'bar> where 'foo: 'bar; . I had expected that Rust would be able to automatically infer these bounds from the GAT declaration instead of giving an error. By using the information that the GAT is used in the return position, these implicit lifetime bounds could be automatically applied.

If we explicitly spell out all the implicit bounds on `fn baz`, then it does compile:
pub trait Foo<'foo>: 'foo {
    type Bar<'bar>
    where
        'foo: 'bar;

    fn baz<'bar>(&'bar self) -> Self::Bar<'bar>
    where
        'foo: 'bar;
}

impl<'foo, T, U> Foo<'foo> for T
where
    T: Deref<Target = U> + 'foo,
    U: Foo<'foo>,
{
    type Bar<'bar> = <U as Foo<'foo>>::Bar<'bar>
    where
        'foo: 'bar;

    fn baz<'bar>(&'bar self) -> Self::Bar<'bar>
    where
        'foo: 'bar,
    {
        (**self).baz()
    }
}
p.s. I am on this Rust version
rustc 1.66.0-nightly (0ca356586 2022-10-06)
binary: rustc
commit-hash: 0ca356586fed56002b10920fd21ddf6fb12de797
commit-date: 2022-10-06
host: x86_64-unknown-linux-gnu
release: 1.66.0-nightly
LLVM version: 15.0.2
@Rageking8
Copy link
Contributor

@rustbot label +T-types +C-bug +F-generic_associated_types

@rustbot rustbot added C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs T-types Relevant to the types team, which will review and decide on the PR/issue. labels Oct 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants