Workarounds for #134890

I just ran into Impl has "stricter" requirement that is implied by existing requirement · Issue #134890 · rust-lang/rust · GitHub.

It's pretty silly. Rust Playground

trait Foo {
    type Bar;
    
    fn func<'a>() where Self::Bar: 'a;
}

impl<'d, T: ?Sized> Foo for &'d T {
    type Bar = &'d ();
    
    fn func<'a>() where Self::Bar: 'a {}
}

// Applying suggested fix for `&'d mut T` still does nothing:
impl<'d, T: ?Sized> Foo for &'d mut T {
    type Bar = &'d ();
    
    fn func<'a>() where <Self as Foo>::Bar: 'a {}
}

// Rephrasing trait bound doesn't help:
trait Baz {
    type Bar;
    
    fn func<'a>() where &'a Self::Bar:, <Self as Baz>::Bar: 'a;
}

impl<'d, T: ?Sized> Baz for &'d T {
    type Bar = &'d ();
    
    fn func<'a>() where &'a Self::Bar:, <Self as Baz>::Bar: 'a {}
}

Seems like you'd need to add a dummy parameter to the trait, which would be annoying for consumers of the trait:

trait Foo<P: ?Sized> {
    type Bar;
    
    fn func<'a>() where P: 'a;
}

impl<'d, T: ?Sized> Foo<&'d ()> for &'d T {
    type Bar = &'d ();
    
    fn func<'a>() where &'d (): 'a {}
}

If there happen to be any better workarounds, I'd be glad to hear them; otherwise, I just want to call a little attention to that bug.

3 Likes

Do you need the bound within the implementation? This works:

impl<'d, T: ?Sized> Foo for &'d T {
    type Bar = &'d ();
 
    //      vvvvvv needed for some nuance (I can link an issue if you care)
    fn func<'a: 'a>() {}
}

(You can supply an implementation with looser requirements than the trait. As far as I remember, callers can't take advantage of it.[1])

An alternative workaround is making the bound implied by a dummy argument.

impl<'d, T: ?Sized> Baz for &'d T {
    type Bar = &'d ();
    
    fn func<'a>(_: [&'a Self::Bar; 0]) {}
}

  1. Except for refined RPITITs which are linted upon. ↩︎

2 Likes

Here's another potential workaround. Can't explain why that particular combo works and the others don't...