diff --git a/crates/axum-utils/src/cookies.rs b/crates/axum-utils/src/cookies.rs index 97f1db830..07b1a9526 100644 --- a/crates/axum-utils/src/cookies.rs +++ b/crates/axum-utils/src/cookies.rs @@ -1,3 +1,4 @@ +// Copyright 2025, 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2022-2024 The Matrix.org Foundation C.I.C. // @@ -6,7 +7,7 @@ //! Private (encrypted) cookie jar, based on axum-extra's cookie jar -use std::convert::Infallible; +use std::{convert::Infallible, future::ready}; use axum::{ extract::{FromRef, FromRequestParts}, @@ -71,9 +72,12 @@ where { type Rejection = Infallible; - async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + fn from_request_parts( + parts: &mut Parts, + state: &S, + ) -> impl Future> + Send { let cookie_manager = CookieManager::from_ref(state); - Ok(cookie_manager.cookie_jar_from_headers(&parts.headers)) + ready(Ok(cookie_manager.cookie_jar_from_headers(&parts.headers))) } } diff --git a/crates/cli/src/app_state.rs b/crates/cli/src/app_state.rs index 25a295d0c..6a9b455fa 100644 --- a/crates/cli/src/app_state.rs +++ b/crates/cli/src/app_state.rs @@ -1,11 +1,11 @@ -// Copyright 2026 Element Creations Ltd. +// Copyright 2025, 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2022-2024 The Matrix.org Foundation C.I.C. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // Please see LICENSE files in the repository root for full details. -use std::{convert::Infallible, net::IpAddr, sync::Arc}; +use std::{convert::Infallible, future::ready, net::IpAddr, sync::Arc}; use axum::extract::{FromRef, FromRequestParts, State}; use ipnetwork::IpNetwork; @@ -224,28 +224,30 @@ impl FromRef for AppVersion { impl FromRequestParts for BoxClock { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, _state: &AppState, - ) -> Result { + ) -> impl Future> + Send { let clock = SystemClock::default(); - Ok(Box::new(clock)) + let clock: Self = Box::new(clock); + ready(Ok(clock)) } } impl FromRequestParts for BoxRng { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, _state: &AppState, - ) -> Result { + ) -> impl Future> + Send { // This rng is used to source the local rng #[expect(clippy::disallowed_methods)] let rng = rand::thread_rng(); let rng = rand_chacha::ChaChaRng::from_rng(rng).expect("Failed to seed RNG"); - Ok(Box::new(rng)) + let rng: Self = Box::new(rng); + ready(Ok(rng)) } } @@ -264,11 +266,11 @@ impl FromRequestParts for Policy { impl FromRequestParts for ActivityTracker { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, state: &AppState, - ) -> Result { - Ok(state.activity_tracker.clone()) + ) -> impl Future> + Send { + ready(Ok(state.activity_tracker.clone())) } } diff --git a/crates/handlers/src/bin/api-schema.rs b/crates/handlers/src/bin/api-schema.rs index 1b73c05c3..20f56cd96 100644 --- a/crates/handlers/src/bin/api-schema.rs +++ b/crates/handlers/src/bin/api-schema.rs @@ -1,3 +1,4 @@ +// Copyright 2025, 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2024 The Matrix.org Foundation C.I.C. // @@ -29,11 +30,11 @@ macro_rules! impl_from_request_parts { impl axum::extract::FromRequestParts for $type { type Rejection = std::convert::Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, _state: &DummyState, - ) -> Result { - unimplemented!("This is a dummy state, it should never be used") + ) -> impl Future> + Send { + async { unimplemented!("This is a dummy state, it should never be used") } } } }; diff --git a/crates/handlers/src/graphql/mod.rs b/crates/handlers/src/graphql/mod.rs index 4d4479fd8..b541500c3 100644 --- a/crates/handlers/src/graphql/mod.rs +++ b/crates/handlers/src/graphql/mod.rs @@ -5,7 +5,12 @@ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // Please see LICENSE files in the repository root for full details. -#![allow(clippy::module_name_repetitions)] +#![allow( + clippy::module_name_repetitions, + // async-graphql's `#[Object]` requires resolvers to be `async fn`, and its + // `Enum` derive emits async trait impls without awaits + clippy::unused_async_trait_impl, +)] use std::{net::IpAddr, ops::Deref, sync::Arc}; diff --git a/crates/handlers/src/oauth2/introspection.rs b/crates/handlers/src/oauth2/introspection.rs index 04ff851e6..12772c3a4 100644 --- a/crates/handlers/src/oauth2/introspection.rs +++ b/crates/handlers/src/oauth2/introspection.rs @@ -515,7 +515,7 @@ pub(crate) async fn post( .ok_or(RouteError::CantLoadUser(session.user_id))?; if !user.is_valid() { - return Err(RouteError::InvalidUser(user.id))?; + return Err(RouteError::InvalidUser(user.id)); } // Grant the synapse admin scope if the session has the admin flag set. @@ -599,7 +599,7 @@ pub(crate) async fn post( .ok_or(RouteError::CantLoadUser(session.user_id))?; if !user.is_valid() { - return Err(RouteError::InvalidUser(user.id))?; + return Err(RouteError::InvalidUser(user.id)); } // Grant the synapse admin scope if the session has the admin flag set. diff --git a/crates/handlers/src/preferred_language.rs b/crates/handlers/src/preferred_language.rs index 8ea38c990..9663da61c 100644 --- a/crates/handlers/src/preferred_language.rs +++ b/crates/handlers/src/preferred_language.rs @@ -1,10 +1,11 @@ +// Copyright 2025, 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2023, 2024 The Matrix.org Foundation C.I.C. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // Please see LICENSE files in the repository root for full details. -use std::{convert::Infallible, sync::Arc}; +use std::{convert::Infallible, future::ready, sync::Arc}; use axum::{ extract::{FromRef, FromRequestParts}, @@ -23,7 +24,10 @@ where { type Rejection = Infallible; - async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + fn from_request_parts( + parts: &mut Parts, + state: &S, + ) -> impl Future> + Send { let translator: Arc = FromRef::from_ref(state); let accept_language = parts.headers.typed_get::(); @@ -45,6 +49,6 @@ where let locale = translator.choose_locale(iter); - Ok(PreferredLanguage(locale)) + ready(Ok(PreferredLanguage(locale))) } } diff --git a/crates/handlers/src/rate_limit.rs b/crates/handlers/src/rate_limit.rs index a405589a4..07acc1bc3 100644 --- a/crates/handlers/src/rate_limit.rs +++ b/crates/handlers/src/rate_limit.rs @@ -1,11 +1,11 @@ -// Copyright 2026 Element Creations Ltd. +// Copyright 2025, 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2024 The Matrix.org Foundation C.I.C. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // Please see LICENSE files in the repository root for full details. -use std::{convert::Infallible, net::IpAddr, sync::Arc, time::Duration}; +use std::{convert::Infallible, future::ready, net::IpAddr, sync::Arc, time::Duration}; use axum::extract::FromRequestParts; use governor::{RateLimiter, clock::QuantaClock, state::keyed::DashMapStateStore}; @@ -82,22 +82,24 @@ impl RequesterFingerprint { impl FromRequestParts for RequesterFingerprint { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( parts: &mut axum::http::request::Parts, _state: &S, - ) -> Result { + ) -> impl Future> + Send { let ip = parts.extensions.get::().and_then(|ip| ip.0); - if let Some(ip) = ip { - Ok(Self::new(ip)) + let fingerprint = if let Some(ip) = ip { + Self::new(ip) } else { // If we can't infer the IP address, we'll just use an empty fingerprint and // warn about it tracing::warn!( "Could not infer client IP address for an operation which rate-limits based on IP addresses" ); - Ok(Self::EMPTY) - } + Self::EMPTY + }; + + ready(Ok(fingerprint)) } } diff --git a/crates/handlers/src/test_utils.rs b/crates/handlers/src/test_utils.rs index b08f8086e..56df8d652 100644 --- a/crates/handlers/src/test_utils.rs +++ b/crates/handlers/src/test_utils.rs @@ -7,6 +7,7 @@ use std::{ convert::Infallible, + future::ready, net::IpAddr, sync::{Arc, Mutex, RwLock}, task::{Context, Poll}, @@ -655,35 +656,37 @@ impl FromRef for AppVersion { impl FromRequestParts for ActivityTracker { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, state: &TestState, - ) -> Result { - Ok(state.activity_tracker.clone()) + ) -> impl Future> + Send { + ready(Ok(state.activity_tracker.clone())) } } impl FromRequestParts for BoxClock { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, state: &TestState, - ) -> Result { - Ok(Box::new(state.clock.clone())) + ) -> impl Future> + Send { + let clock: Self = Box::new(state.clock.clone()); + ready(Ok(clock)) } } impl FromRequestParts for BoxRng { type Rejection = Infallible; - async fn from_request_parts( + fn from_request_parts( _parts: &mut axum::http::request::Parts, state: &TestState, - ) -> Result { + ) -> impl Future> + Send { let mut parent_rng = state.rng.lock().expect("Failed to lock RNG"); let rng = ChaChaRng::from_rng(&mut *parent_rng).expect("Failed to seed RNG"); - Ok(Box::new(rng)) + let rng: Self = Box::new(rng); + ready(Ok(rng)) } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c0b6afb91..44d11ea41 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -4,7 +4,7 @@ # Please see LICENSE files in the repository root for full details. [toolchain] -channel = "1.96.0" +channel = "1.98.1" profile = "minimal" # No rustfmt: .rustfmt.toml uses nightly-only options, so formatting runs as `cargo +nightly fmt`. # No cross-compilation targets: the Dockerfile and build.yaml add the ones they need.