Trait bounds of type also applied to generic type parameters?

I'm hitting a wall with a weird-to-me compiler error. When creating a generic axum handler function, it requires that the type parameters be Send + Sync + 'static, even in examples where they are simple associated types that never need to be sent between threads. I found a minimum reproducible example where the type parameter isn't even ever used:

use std::sync::Arc;

use axum::{Router, extract::State, response::IntoResponse, routing::get};

trait Greeter: Send + Sync {
    type GreetType;
    fn greet(&self) -> String {
        format!("Hello World!")
    }
}

struct AppState<G> {
    greeter: Arc<dyn Greeter<GreetType = G>>,
}

impl<G> Clone for AppState<G> {
    fn clone(&self) -> Self {
        Self {
            greeter: Arc::clone(&self.greeter),
        }
    }
}

async fn handler<G>(State(state): State<AppState<G>>) -> impl IntoResponse {
    state.greeter.greet()
}

struct ConcreteGreter;

impl Greeter for ConcreteGreter {
    type GreetType = i8;
}

fn router<G>() -> Router<AppState<G>> {
    Router::new().route("/", get(handler::<G>))
}

#[tokio::main]
async fn main() {
    let state = AppState {
        greeter: Arc::new(ConcreteGreter),
    };
    let app = router::<i8>().with_state(state);
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

The compile error here is

error[E0310]: the parameter type `G` may not live long enough
  --> src/main.rs:35:5
   |
35 |     Router::new().route("/", get(reply::<G>))
   |     ^^^^^^^^^^^
   |     |
   |     the parameter type `G` must be valid for the static lifetime...
   |     ...so that the type `G` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
34 | fn router<G: 'static>() -> Router<AppState<G>> {
   |            +++++++++

I don't understand how the lifetime of G even matters here. It's an associated type, it's not contained in any struct, future, or function parameter and it's never held across an await point or returned. Here in this minimal example I could fix it by adding a 'static bound, but in my real life example I don't have that option because the associated type may be a reference (edit: i think that last sentence didn't make sense).

One that is never held across an await point or returned either, but the compiler doesn't seem to agree with me.

What am I missing here?

Router::<X>::new requires that X: 'static, and you're trying to call Router::<AppState<G>>::new. That requires AppState<G>: 'static which in turn requires G: 'static.

These outlives bounds are a type-level property, so what the code does with values is not a consideration. (Despite using the word "lifetime" a lot, an outlives violation isn't directly about when values are destructed.)

There's a tangential issue about parameters of dyn Trait<..> participating in outlives bounds, but I don't think it applies without restructuring your code, and I don't think it's going somewhere useful for you anyway. Certainly no time soon.

Thanks for the quick reply. I think I understand now

These outlives bounds are a type-level property, so what the code does with values is not a consideration.

I was mixing up 'static the lifetime with 'static the bound.

Something I thought of that might be applicable is to see if you can erase the associated type here...

struct AppState<G> {
    greeter: Arc<dyn Greeter<GreetType = G>>,
}

...by using some supertrait of Greeter, say. It seems unlikely (I imagine the associated type exists for a practical reason) but I thought I'd throw it out there.