Implementation of dyn Trait "not general enough"

So I get this error:

error: implementation of `Role` is not general enough
  --> xtask\tests\expanded\successes\basic.rs:74:21
   |
74 |         let join_handle = ::tokio::task::spawn(event_loop);
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Role` is not general enough
   |
   = note: `dyn basic::BasicRole` must implement `Role`
   = note: ...but `Role` is actually implemented for the type `(dyn basic::BasicRole + 'static)`

error: implementation of `Role` is not general enough
  --> xtask\tests\expanded\successes\basic.rs:74:21
   |
74 |         let join_handle = ::tokio::task::spawn(event_loop);
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Role` is not general enough
   |
   = note: `(dyn basic::BasicRole + '0)` must implement `Role`, for any lifetime `'0`...
   = note: ...but `Role` is actually implemented for the type `(dyn basic::BasicRole + 'static)`

With the following item relations:

pub trait Role: 'static + Sync + Send { ... }

pub trait BasicRole: 'static + Send + Sync { ... }
impl Role for dyn BasicRole {...}

pub trait Accepts<T> { ...} 
// This trait isn't directly involved but things broke when I introduced it
impl Accepts<usize> for dyn BasicRole {}

struct Actor { ... }
impl BasicRole for Actor { ... }

This is very confusing to me, because searching for that error text brings up examples where the traits involved have lifetime bounds which are missing here. However, the call to spawn that is triggering the error has very complicated lifetimes involved. As best as I can reduce it, it looks like this:

pub fn start(...) -> /*... */ {
		use ::std::sync::Arc;
		use ::tokio::time::{sleep, Duration, Instant};
		use ::tokio::{pin, select};
		let (basic_role_input, mut basic_role_output) = unbounded_channel(); // The items for this channel are Send
		let actor = Arc::new_cyclic(|weak| Actor {
			this:       weak.clone(),
			basic_role: basic_role_input,
		});
		let stored_actor = Arc::clone(&actor);
		let event_loop = async move {
			let loop_lambda = async {
				loop {
					select! { 
                        Some (msg) = basic_role_output . recv () => { /* ... */},
						else => { break ; }
					};
				}
			};
			AssertUnwindSafe(loop_lambda).await
		};
		let join_handle = ::tokio::task::spawn(event_loop);
		unimplemented!()
	}

Can anyone suggest how to fix this or what other avenues I might investigate about where the problem is?

I don't think you've supplied enough information to reproduce the problem.

Thanks, I didn't realize that it was so non-local. Here's a playground link that reproduces it:

I can't explain why, but the compiler seems to want a higher-ranked implementation here, even though the elided lifetime must be 'static due to the bounds on the trait.

-impl Role for dyn BasicRole {
+impl Role for dyn BasicRole + '_ {
     type Return = ();
 }

As a very vague guess, it's erasing lifetimes as some sort of borrow-check inside the async block and finding your single-lifetime implementation and thinking that's a problem due to not taking into account the 'static bound ... or something.

1 Like

I think it's this or very related, but must admit I didn't read the whole thing. It matches this summary though. Click through to danielhenrymantilla's comment for a more technical discussion and a workaround (which you may or may not need).

2 Likes

I came back to this recently and discovered that this change indeed works, but only on stable, still breaking on nightly. I don't understand at all how that can be possible given that AFAIK its supposed to be guaranteed to be the other way around.

Yeah, I can see that in the last playground link. That would be a stable-to-beta regression. I didn't see anything offhand when I skimmed the label, so I strongly suggest filing a new issue.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.