Bump Rust to 1.96.0 and fix clippy lints (#5733)

This commit is contained in:
Quentin Gliech
2026-06-17 14:04:45 +02:00
committed by GitHub
29 changed files with 120 additions and 81 deletions
+1 -1
View File
@@ -244,7 +244,7 @@ jobs:
# sync with Dockerfile.
#
# --override sets this as the default rust toolchain version in this directory.
run: rustup toolchain install 1.93.0 --profile minimal --component clippy --override
run: rustup toolchain install 1.96.0 --profile minimal --component clippy --override
- uses: ./.github/actions/build-policies
+1 -1
View File
@@ -14,7 +14,7 @@
ARG DEBIAN_VERSION=13
ARG DEBIAN_VERSION_NAME=trixie
# Keep in sync with .github/workflows/ci.yaml
ARG RUSTC_VERSION=1.93.0
ARG RUSTC_VERSION=1.96.0
# Keep in sync with .node-version
ARG NODEJS_VERSION=24.15.0
# Keep in sync with .github/actions/build-policies/action.yml and policies/Makefile
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -100,7 +101,7 @@ impl AppState {
if let Err(e) = metadata_cache
.warm_up_and_run(
&http_client,
std::time::Duration::from_secs(60 * 15),
std::time::Duration::from_mins(15),
&mut repo,
)
.await
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -204,7 +205,7 @@ impl Options {
// Activity is flushed every minute
let activity_tracker = ActivityTracker::new(
PgRepositoryFactory::new(pool.clone()).boxed(),
Duration::from_secs(60),
Duration::from_mins(1),
shutdown.task_tracker(),
shutdown.soft_shutdown_token(),
);
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -83,7 +84,7 @@ impl LifecycleManager {
let sigterm = tokio::signal::unix::signal(SignalKind::terminate())?;
let sigint = tokio::signal::unix::signal(SignalKind::interrupt())?;
let sighup = tokio::signal::unix::signal(SignalKind::hangup())?;
let timeout = Duration::from_secs(60);
let timeout = Duration::from_mins(1);
let task_tracker = TaskTracker::new();
notify(&[sd_notify::NotifyState::MainPid(std::process::id())]);
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -258,12 +259,12 @@ pub fn build_router(
// Cache 404s for 5 minutes
CacheControl::new()
.with_public()
.with_max_age(Duration::from_secs(5 * 60))
.with_max_age(Duration::from_mins(5))
} else {
// Cache assets for 1 year
CacheControl::new()
.with_public()
.with_max_age(Duration::from_secs(365 * 24 * 60 * 60))
.with_max_age(Duration::from_hours(365 * 24))
.with_immutable()
};
res.headers_mut().typed_insert(cache_control);
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -456,7 +457,7 @@ pub async fn load_policy_factory_dynamic_data_continuously(
load_policy_factory_dynamic_data(&policy_factory, &*repository_factory).await?;
task_tracker.spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(60));
let mut interval = tokio::time::interval(Duration::from_mins(1));
loop {
tokio::select! {
+5
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -257,6 +258,10 @@ impl ConfigurationSection for ClientsConfig {
#[cfg(test)]
mod tests {
// The closures passed to `Jail::expect_with` return `figment::Error`, which is
// large, and we can't change figment's API.
#![expect(clippy::result_large_err)]
use std::str::FromStr;
use figment::{
+7 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -29,12 +30,12 @@ fn default_connect_timeout() -> Duration {
#[expect(clippy::unnecessary_wraps)]
fn default_idle_timeout() -> Option<Duration> {
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
#[expect(clippy::unnecessary_wraps)]
fn default_max_lifetime() -> Option<Duration> {
Some(Duration::from_secs(30 * 60))
Some(Duration::from_mins(30))
}
impl Default for DatabaseConfig {
@@ -286,6 +287,10 @@ impl ConfigurationSection for DatabaseConfig {
}
#[cfg(test)]
mod tests {
// The closures passed to `Jail::expect_with` return `figment::Error`, which is
// large, and we can't change figment's API.
#![expect(clippy::result_large_err)]
use figment::{
Figment, Jail,
providers::{Format, Yaml},
+5
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -164,6 +165,10 @@ impl MatrixConfig {
#[cfg(test)]
mod tests {
// The closures passed to `Jail::expect_with` return `figment::Error`, which is
// large, and we can't change figment's API.
#![expect(clippy::result_large_err)]
use figment::{
Figment, Jail,
providers::{Format, Yaml},
+5
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -466,6 +467,10 @@ impl SecretsConfig {
#[cfg(test)]
mod tests {
// The closures passed to `Jail::expect_with` return `figment::Error`, which is
// large, and we can't change figment's API.
#![expect(clippy::result_large_err)]
use figment::{
Figment, Jail,
providers::{Format, Yaml},
@@ -719,6 +719,10 @@ impl Provider {
#[cfg(test)]
mod tests {
// The closures passed to `Jail::expect_with` return `figment::Error`, which is
// large, and we can't change figment's API.
#![expect(clippy::result_large_err)]
use std::str::FromStr;
use figment::{
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -195,7 +196,7 @@ where
CONTENT_LANGUAGE,
CONTENT_TYPE,
])
.max_age(Duration::from_secs(60 * 60)),
.max_age(Duration::from_hours(1)),
)
}
@@ -259,7 +260,7 @@ where
// Swagger will send this header, so we have to allow it to avoid CORS errors
HeaderName::from_static("x-requested-with"),
])
.max_age(Duration::from_secs(60 * 60)),
.max_age(Duration::from_hours(1)),
)
}
@@ -329,7 +330,7 @@ where
CONTENT_TYPE,
HeaderName::from_static("x-requested-with"),
])
.max_age(Duration::from_secs(60 * 60)),
.max_age(Duration::from_hours(1)),
);
Router::new().merge(human_router).merge(api_router)
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
@@ -145,7 +146,7 @@ impl Limiter {
let this = self.clone();
tokio::spawn(async move {
// Run the task every minute
let mut interval = tokio::time::interval(Duration::from_secs(60));
let mut interval = tokio::time::interval(Duration::from_mins(1));
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
loop {
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -244,7 +245,7 @@ impl TestState {
let activity_tracker = ActivityTracker::new(
PgRepositoryFactory::new(pool.clone()).boxed(),
std::time::Duration::from_secs(60),
std::time::Duration::from_mins(1),
&task_tracker,
shutdown_token.child_token(),
);
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -134,14 +135,10 @@ fn b64encode(bytes: &[u8]) -> String {
fn tlvdecode(bytes: &[u8]) -> Result<HashMap<Value, Value>, Error> {
let mut iter = bytes.iter().copied();
let mut ret = HashMap::new();
loop {
// TODO: this assumes the tag and the length are both single bytes, which is not
// always the case with protobufs. We should properly decode varints
// here.
let Some(tag) = iter.next() else {
break;
};
// TODO: this assumes the tag and the length are both single bytes, which is not
// always the case with protobufs. We should properly decode varints
// here.
while let Some(tag) = iter.next() {
let len = iter
.next()
.ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "Invalid ILV encoding"))?;
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -102,7 +103,7 @@ pub fn client() -> reqwest::Client {
.dns_resolver(Arc::new(TracingResolver::new()))
.use_preconfigured_tls(tls_config)
.user_agent(USER_AGENT)
.timeout(Duration::from_secs(60))
.timeout(Duration::from_mins(1))
.connect_timeout(Duration::from_secs(30))
.build()
.expect("failed to create HTTP client")
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -542,7 +543,7 @@ impl HomeserverConnection for SynapseConnection {
.post(&format!("_synapse/admin/v1/deactivate/{encoded_mxid}"))
.json(&SynapseDeactivateUserRequest { erase })
// Deactivation can take a while, so we set a longer timeout
.timeout(Duration::from_secs(60 * 5))
.timeout(Duration::from_mins(5))
.send_traced()
.await
.context("Failed to deactivate user in Synapse")?;
@@ -591,7 +592,7 @@ impl HomeserverConnection for SynapseConnection {
match response.status() {
StatusCode::CREATED | StatusCode::OK => Ok(()),
code => bail!("Unexpected HTTP code while reactivating user in Synapse: {code}",),
code => bail!("Unexpected HTTP code while reactivating user in Synapse: {code}"),
}
}
+2 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -165,9 +166,7 @@ impl Scope {
/// Whether this `Scope` contains the given value.
#[must_use]
pub fn contains(&self, token: &str) -> bool {
ScopeToken::from_str(token)
.map(|token| self.0.contains(&token))
.unwrap_or(false)
ScopeToken::from_str(token).is_ok_and(|token| self.0.contains(&token))
}
/// Inserts the given token in this `Scope`.
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -135,30 +136,34 @@ fn pass_full_authorization_url() {
fn is_valid_token_endpoint_request(req: &Request) -> bool {
let body = form_urlencoded::parse(&req.body).collect::<HashMap<_, _>>();
if body.get("client_id").filter(|s| *s == CLIENT_ID).is_none() {
if body
.get("client_id")
.as_ref()
.is_none_or(|s| *s != CLIENT_ID)
{
println!("Missing or wrong client ID");
return false;
}
if body
.get("grant_type")
.filter(|s| *s == "authorization_code")
.is_none()
.as_ref()
.is_none_or(|s| *s != "authorization_code")
{
println!("Missing or wrong grant type");
return false;
}
if body
.get("code")
.filter(|s| *s == AUTHORIZATION_CODE)
.is_none()
.as_ref()
.is_none_or(|s| *s != AUTHORIZATION_CODE)
{
println!("Missing or wrong authorization code");
return false;
}
if body
.get("redirect_uri")
.filter(|s| *s == REDIRECT_URI)
.is_none()
.as_ref()
.is_none_or(|s| *s != REDIRECT_URI)
{
println!("Missing or wrong redirect URI");
return false;
@@ -166,8 +171,8 @@ fn is_valid_token_endpoint_request(req: &Request) -> bool {
if body
.get("code_verifier")
.filter(|s| *s == CODE_VERIFIER)
.is_none()
.as_ref()
.is_none_or(|s| *s != CODE_VERIFIER)
{
println!("Missing or wrong code verifier");
return false;
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -36,32 +37,32 @@ async fn pass_access_token_with_client_credentials() {
if query_pairs
.get("grant_type")
.filter(|s| *s == "client_credentials")
.is_none()
.as_ref()
.is_none_or(|s| *s != "client_credentials")
{
println!("Wrong or missing grant type");
return false;
}
if query_pairs
.get("scope")
.filter(|s| *s == "profile")
.is_none()
.as_ref()
.is_none_or(|s| *s != "profile")
{
println!("Wrong or missing scope");
return false;
}
if query_pairs
.get("client_id")
.filter(|s| *s == CLIENT_ID)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_ID)
{
println!("Wrong or missing client ID");
return false;
}
if query_pairs
.get("client_secret")
.filter(|s| *s == CLIENT_SECRET)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_SECRET)
{
println!("Wrong or missing client secret");
return false;
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -32,24 +33,24 @@ async fn pass_refresh_access_token() {
if query_pairs
.get("grant_type")
.filter(|s| *s == "refresh_token")
.is_none()
.as_ref()
.is_none_or(|s| *s != "refresh_token")
{
println!("Wrong or missing grant type");
return false;
}
if query_pairs
.get("refresh_token")
.filter(|s| *s == REFRESH_TOKEN)
.is_none()
.as_ref()
.is_none_or(|s| *s != REFRESH_TOKEN)
{
println!("Wrong or missing refresh token");
return false;
}
if query_pairs
.get("client_id")
.filter(|s| *s == CLIENT_ID)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_ID)
{
println!("Wrong or missing client ID");
return false;
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -41,8 +42,8 @@ async fn pass_none() {
if query_pairs
.get("client_id")
.filter(|s| *s == CLIENT_ID)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_ID)
{
println!("Wrong or missing client ID");
return false;
@@ -132,16 +133,16 @@ async fn pass_client_secret_post() {
if query_pairs
.get("client_id")
.filter(|s| *s == CLIENT_ID)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_ID)
{
println!("Wrong or missing client ID");
return false;
}
if query_pairs
.get("client_secret")
.filter(|s| *s == CLIENT_SECRET)
.is_none()
.as_ref()
.is_none_or(|s| *s != CLIENT_SECRET)
{
println!("Wrong or missing client secret");
return false;
@@ -194,8 +195,8 @@ async fn pass_client_secret_jwt() {
}
if query_pairs
.get("client_assertion_type")
.filter(|s| *s == "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.is_none()
.as_ref()
.is_none_or(|s| *s != "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
{
println!("Wrong or missing client assertion type");
return false;
@@ -273,8 +274,8 @@ async fn pass_private_key_jwt() {
}
if query_pairs
.get("client_assertion_type")
.filter(|s| *s == "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.is_none()
.as_ref()
.is_none_or(|s| *s != "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
{
println!("Wrong or missing client assertion type");
return false;
+1 -1
View File
@@ -58,7 +58,7 @@ impl RunnableJob for CleanupQueueJobsJob {
}
fn timeout(&self) -> Option<Duration> {
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
+4 -4
View File
@@ -70,7 +70,7 @@ impl RunnableJob for CleanupOAuthAuthorizationGrantsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -123,7 +123,7 @@ impl RunnableJob for CleanupOAuthDeviceCodeGrantsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -167,7 +167,7 @@ impl RunnableJob for CleanupUpstreamOAuthSessionsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -211,6 +211,6 @@ impl RunnableJob for CleanupUpstreamOAuthLinksJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
+6 -6
View File
@@ -65,7 +65,7 @@ impl RunnableJob for CleanupFinishedCompatSessionsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -113,7 +113,7 @@ impl RunnableJob for CleanupFinishedOAuth2SessionsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -162,7 +162,7 @@ impl RunnableJob for CleanupFinishedUserSessionsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -203,7 +203,7 @@ impl RunnableJob for CleanupInactiveOAuth2SessionIpsJob {
}
fn timeout(&self) -> Option<Duration> {
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -244,7 +244,7 @@ impl RunnableJob for CleanupInactiveCompatSessionIpsJob {
}
fn timeout(&self) -> Option<Duration> {
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -285,6 +285,6 @@ impl RunnableJob for CleanupInactiveUserSessionIpsJob {
}
fn timeout(&self) -> Option<Duration> {
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
+4 -4
View File
@@ -63,7 +63,7 @@ impl RunnableJob for CleanupRevokedOAuthAccessTokensJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -115,7 +115,7 @@ impl RunnableJob for CleanupExpiredOAuthAccessTokensJob {
}
fn timeout(&self) -> Option<Duration> {
Some(Duration::from_secs(60))
Some(Duration::from_mins(1))
}
}
@@ -162,7 +162,7 @@ impl RunnableJob for CleanupRevokedOAuthRefreshTokensJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -209,6 +209,6 @@ impl RunnableJob for CleanupConsumedOAuthRefreshTokensJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
+3 -3
View File
@@ -69,7 +69,7 @@ impl RunnableJob for CleanupUserRegistrationsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -122,7 +122,7 @@ impl RunnableJob for CleanupUserRecoverySessionsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
@@ -176,6 +176,6 @@ impl RunnableJob for CleanupUserEmailAuthenticationsJob {
fn timeout(&self) -> Option<Duration> {
// This job runs every hour, so having it running it for 10 minutes is fine
Some(Duration::from_secs(10 * 60))
Some(Duration::from_mins(10))
}
}
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -526,7 +527,7 @@ impl Object for IncludeAsset {
// When a JSON is included at the top level (a translation), we preload it
let src = main.src(assets_base);
if tracker.mark_preloaded(&src) {
writeln!(output, r#"<link rel="preload" href="{src}" as="fetch" />"#,).unwrap();
writeln!(output, r#"<link rel="preload" href="{src}" as="fetch" />"#).unwrap();
}
}