From 21876fcc64a163a8e8f99ac6278738c1733a4e16 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Sun, 18 Sep 2022 22:22:47 +0200 Subject: [PATCH] Clarify `Clone` requirements for using `State` (#1388) --- axum/src/extract/state.rs | 51 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/axum/src/extract/state.rs b/axum/src/extract/state.rs index aabeb000..afacffb1 100644 --- a/axum/src/extract/state.rs +++ b/axum/src/extract/state.rs @@ -22,7 +22,9 @@ use std::{ /// // /// // here you can put configuration, database connection pools, or whatever /// // state you need -/// // Note: the application state *must* derive `Clone` (or be wrapped in e.g. `Arc`) +/// // +/// // see "When states need to implement `Clone`" for more details on why we need +/// // `#[derive(Clone)]` here. /// #[derive(Clone)] /// struct AppState {} /// @@ -173,6 +175,53 @@ use std::{ /// // ... /// } /// ``` +/// +/// # When states need to implement `Clone` +/// +/// Your top level state type must implement `Clone` to be extractable with `State`: +/// +/// ``` +/// use axum::extract::State; +/// +/// // no substates, so to extract to `State` we must implement `Clone` for `AppState` +/// #[derive(Clone)] +/// struct AppState {} +/// +/// async fn handler(State(state): State) { +/// // ... +/// } +/// ``` +/// +/// This works because of [`impl FromRef for S where S: Clone`][`FromRef`]. +/// +/// This is also true if you're extracting substates, unless you _never_ extract the top level +/// state itself: +/// +/// ``` +/// use axum::extract::{State, FromRef}; +/// +/// // we never extract `State`, just `State`. So `AppState` doesn't need to +/// // implement `Clone` +/// struct AppState { +/// inner: InnerState, +/// } +/// +/// #[derive(Clone)] +/// struct InnerState {} +/// +/// impl FromRef for InnerState { +/// fn from_ref(app_state: &AppState) -> InnerState { +/// app_state.inner.clone() +/// } +/// } +/// +/// async fn api_users(State(inner): State) { +/// // ... +/// } +/// ``` +/// +/// In general however we recommend you implement `Clone` to all your state types to avoid +/// potential type errors. #[derive(Debug, Default, Clone, Copy)] pub struct State(pub S);