Skip to content

Commit ffaf185

Browse files
committed
Bump MSRV to Rust 1.88 (#3376)
Rust 1.88 stabilizes let chains and clippy will lint places they can be used.
1 parent 0376818 commit ffaf185

File tree

22 files changed

+228
-241
lines changed

22 files changed

+228
-241
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ name: CI
33
on: [push, pull_request]
44

55
env:
6-
rust_min: 1.85.0
7-
rust_nightly: nightly-2025-02-19
6+
rust_min: 1.88.0
7+
rust_nightly: nightly-2025-06-25
88

99
jobs:
1010
test:

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ repository = "https://github.com/serenity-rs/serenity.git"
2424
keywords = ["discord", "api"]
2525
license = "ISC"
2626
edition = "2024"
27-
rust-version = "1.85"
27+
rust-version = "1.88"
2828

2929
[dependencies]
3030
# Required dependencies

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
101101

102102
## MSRV Policy
103103

104-
Serenity's minimum supported Rust version (MSRV) is Rust 1.85.
104+
Serenity's minimum supported Rust version (MSRV) is Rust 1.88.
105105

106106
We opt to keep MSRV stable on the `current` branch. This means it will remain
107107
unchanged between minor releases. Occasionally, dependencies may violate SemVer
@@ -244,5 +244,5 @@ a Rust-native cloud development platform that allows deploying Serenity bots for
244244
[repo:andesite]: https://github.com/natanbc/andesite
245245
[repo:lavaplayer]: https://github.com/sedmelluq/lavaplayer
246246
[logo]: https://raw.githubusercontent.com/serenity-rs/serenity/current/logo.png
247-
[rust-version-badge]: https://img.shields.io/badge/rust-1.85.0+-93450a.svg?style=flat-square
248-
[rust-version-link]: https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html
247+
[rust-version-badge]: https://img.shields.io/badge/rust-1.88.0+-93450a.svg?style=flat-square
248+
[rust-version-link]: https://blog.rust-lang.org/2025/06/26/Rust-1.88.0.html

examples/e14_message_components/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use serenity::futures::StreamExt;
1717
use serenity::model::prelude::*;
1818
use serenity::prelude::*;
1919

20-
fn sound_button(name: &str, emoji: ReactionType) -> CreateButton {
20+
fn sound_button(name: &str, emoji: ReactionType) -> CreateButton<'_> {
2121
// To add an emoji to buttons, use .emoji(). The method accepts anything ReactionType or
2222
// anything that can be converted to it. For a list of that, search Trait Implementations in
2323
// the docs for From<...>.

src/builder/create_attachment.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<'a> CreateAttachment<'a> {
115115
/// # Errors
116116
///
117117
/// See [`CreateAttachment::get_data`] for details.
118-
pub async fn encode(&self) -> Result<ImageData> {
118+
pub async fn encode(&self) -> Result<ImageData<'_>> {
119119
use base64::engine::{Config, Engine};
120120

121121
const PREFIX: &str = "data:image/png;base64,";
@@ -162,14 +162,15 @@ impl<'a> ImageData<'a> {
162162
/// docs](https://discord.com/developers/docs/reference#image-data).
163163
pub fn from_base64(s: impl Into<Cow<'a, str>>) -> Result<Self> {
164164
let s = s.into();
165-
if let Some(("data", tail)) = s.split_once(':') {
166-
if let Some((mimetype, encoding)) = tail.split_once(';') {
167-
if mimetype.split_once('/').is_some() && encoding.starts_with("base64,") {
168-
return Ok(Self(s));
169-
}
170-
}
165+
if let Some(("data", tail)) = s.split_once(':')
166+
&& let Some((mimetype, encoding)) = tail.split_once(';')
167+
&& mimetype.split_once('/').is_some()
168+
&& encoding.starts_with("base64,")
169+
{
170+
Ok(Self(s))
171+
} else {
172+
Err(Error::Url(UrlError::InvalidDataURI))
171173
}
172-
Err(Error::Url(UrlError::InvalidDataURI))
173174
}
174175
}
175176

src/builder/create_interaction_response.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@ impl CreateInteractionResponse<'_> {
136136
_ => Vec::new(),
137137
};
138138

139-
if let Self::Message(msg) | Self::Defer(msg) | Self::UpdateMessage(msg) = &mut self {
140-
if msg.allowed_mentions.is_none() {
141-
msg.allowed_mentions.clone_from(&http.default_allowed_mentions);
142-
}
139+
if let Self::Message(msg) | Self::Defer(msg) | Self::UpdateMessage(msg) = &mut self
140+
&& msg.allowed_mentions.is_none()
141+
{
142+
msg.allowed_mentions.clone_from(&http.default_allowed_mentions);
143143
}
144144

145145
http.create_interaction_response(interaction_id, interaction_token, &self, files).await

src/builder/edit_message.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,12 @@ impl<'a> EditMessage<'a> {
230230
self.check_length()?;
231231

232232
#[cfg(feature = "cache")]
233-
if let Some(user_id) = user_id {
234-
if let Some(cache) = cache_http.cache() {
235-
if user_id != cache.current_user().id && !self.is_only_suppress_embeds() {
236-
return Err(Error::Model(ModelError::InvalidUser));
237-
}
238-
}
233+
if let Some(user_id) = user_id
234+
&& let Some(cache) = cache_http.cache()
235+
&& user_id != cache.current_user().id
236+
&& !self.is_only_suppress_embeds()
237+
{
238+
return Err(Error::Model(ModelError::InvalidUser));
239239
}
240240

241241
let files = self.attachments.as_ref().map_or(Vec::new(), EditAttachments::new_attachments);

src/cache/event.rs

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,17 @@ impl CacheUpdate for ChannelPinsUpdateEvent {
8888
type Output = std::convert::Infallible;
8989

9090
fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
91-
if let Some(guild_id) = self.guild_id {
92-
if let Some(mut guild) = cache.guilds.get_mut(&guild_id) {
93-
let (channel_id, thread_id) = self.channel_id.split();
94-
if let Some(mut channel) = guild.channels.get_mut(&channel_id) {
95-
channel.base.last_pin_timestamp = self.last_pin_timestamp;
96-
return None;
97-
}
91+
if let Some(guild_id) = self.guild_id
92+
&& let Some(mut guild) = cache.guilds.get_mut(&guild_id)
93+
{
94+
let (channel_id, thread_id) = self.channel_id.split();
95+
if let Some(mut channel) = guild.channels.get_mut(&channel_id) {
96+
channel.base.last_pin_timestamp = self.last_pin_timestamp;
97+
return None;
98+
}
9899

99-
if let Some(mut thread) = guild.threads.get_mut(&thread_id) {
100-
thread.base.last_pin_timestamp = self.last_pin_timestamp;
101-
}
100+
if let Some(mut thread) = guild.threads.get_mut(&thread_id) {
101+
thread.base.last_pin_timestamp = self.last_pin_timestamp;
102102
}
103103
}
104104

@@ -270,10 +270,10 @@ impl CacheUpdate for GuildRoleUpdateEvent {
270270
type Output = Role;
271271

272272
fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
273-
if let Some(mut guild) = cache.guilds.get_mut(&self.role.guild_id) {
274-
if let Some(mut role) = guild.roles.get_mut(&self.role.id) {
275-
return Some(std::mem::replace(&mut *role, self.role.clone()));
276-
}
273+
if let Some(mut guild) = cache.guilds.get_mut(&self.role.guild_id)
274+
&& let Some(mut role) = guild.roles.get_mut(&self.role.id)
275+
{
276+
return Some(std::mem::replace(&mut *role, self.role.clone()));
277277
}
278278

279279
None
@@ -422,39 +422,39 @@ impl CacheUpdate for PresenceUpdateEvent {
422422
type Output = Presence;
423423

424424
fn update(&mut self, cache: &Cache) -> Option<Presence> {
425-
if let Some(guild_id) = self.presence.guild_id {
426-
if let Some(mut guild) = cache.guilds.get_mut(&guild_id) {
427-
let old = guild.presences.get(&self.presence.user.id).cloned();
428-
429-
// If the member went offline, remove them from the presence list.
430-
if self.presence.status == OnlineStatus::Offline {
431-
guild.presences.remove(&self.presence.user.id);
432-
} else {
433-
guild.presences.insert(self.presence.clone());
434-
}
425+
if let Some(guild_id) = self.presence.guild_id
426+
&& let Some(mut guild) = cache.guilds.get_mut(&guild_id)
427+
{
428+
let old = guild.presences.get(&self.presence.user.id).cloned();
435429

436-
// Create a partial member instance out of the presence update data.
437-
if let Some(user) = self.presence.user.to_user() {
438-
if !guild.members.contains_key(&self.presence.user.id) {
439-
guild.members.insert(Member {
440-
guild_id,
441-
joined_at: None,
442-
nick: None,
443-
user,
444-
roles: FixedArray::default(),
445-
premium_since: None,
446-
permissions: None,
447-
avatar: None,
448-
communication_disabled_until: None,
449-
flags: GuildMemberFlags::default(),
450-
unusual_dm_activity_until: None,
451-
__generated_flags: MemberGeneratedFlags::empty(),
452-
});
453-
}
454-
}
430+
// If the member went offline, remove them from the presence list.
431+
if self.presence.status == OnlineStatus::Offline {
432+
guild.presences.remove(&self.presence.user.id);
433+
} else {
434+
guild.presences.insert(self.presence.clone());
435+
}
455436

456-
return old;
437+
// Create a partial member instance out of the presence update data.
438+
if let Some(user) = self.presence.user.to_user()
439+
&& !guild.members.contains_key(&self.presence.user.id)
440+
{
441+
guild.members.insert(Member {
442+
guild_id,
443+
joined_at: None,
444+
nick: None,
445+
user,
446+
roles: FixedArray::default(),
447+
premium_since: None,
448+
permissions: None,
449+
avatar: None,
450+
communication_disabled_until: None,
451+
flags: GuildMemberFlags::default(),
452+
unusual_dm_activity_until: None,
453+
__generated_flags: MemberGeneratedFlags::empty(),
454+
});
457455
}
456+
457+
return old;
458458
}
459459

460460
None

src/gateway/client/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,16 @@ impl IntoFuture for ClientBuilder {
300300
let presence = self.presence;
301301
let http = self.http;
302302

303-
if let Some(ratelimiter) = &http.ratelimiter {
304-
if let Some(event_handler) = &self.event_handler {
305-
let event_handler = Arc::clone(event_handler);
306-
ratelimiter.set_ratelimit_callback(Box::new(move |info| {
307-
let event_handler = Arc::clone(&event_handler);
308-
spawn_named("ratelimit::dispatch", async move {
309-
event_handler.ratelimit(info).await;
310-
});
311-
}));
312-
}
303+
if let Some(ratelimiter) = &http.ratelimiter
304+
&& let Some(event_handler) = &self.event_handler
305+
{
306+
let event_handler = Arc::clone(event_handler);
307+
ratelimiter.set_ratelimit_callback(Box::new(move |info| {
308+
let event_handler = Arc::clone(&event_handler);
309+
spawn_named("ratelimit::dispatch", async move {
310+
event_handler.ratelimit(info).await;
311+
});
312+
}));
313313
}
314314

315315
#[cfg(feature = "cache")]

src/gateway/sharding/mod.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,12 @@ impl Shard {
246246
Ok(())
247247
},
248248
Err(why) => {
249-
if let Error::Tungstenite(err) = &why {
250-
if let TungsteniteError::Io(err) = &**err {
251-
if err.raw_os_error() != Some(32) {
252-
debug!("[{:?}] Err heartbeating: {:?}", self.info, err);
253-
return Err(Error::Gateway(GatewayError::HeartbeatFailed));
254-
}
255-
}
249+
if let Error::Tungstenite(err) = &why
250+
&& let TungsteniteError::Io(err) = &**err
251+
&& err.raw_os_error() != Some(32)
252+
{
253+
debug!("[{:?}] Err heartbeating: {:?}", self.info, err);
254+
return Err(Error::Gateway(GatewayError::HeartbeatFailed));
256255
}
257256

258257
warn!("[{:?}] Other err w/ keepalive: {:?}", self.info, why);
@@ -522,10 +521,10 @@ impl Shard {
522521

523522
// If a duration of time less than the heartbeat_interval has passed, then don't perform a
524523
// keepalive or attempt to reconnect.
525-
if let Some(last_sent) = self.last_heartbeat_sent {
526-
if last_sent.elapsed() <= heartbeat_interval {
527-
return true;
528-
}
524+
if let Some(last_sent) = self.last_heartbeat_sent
525+
&& last_sent.elapsed() <= heartbeat_interval
526+
{
527+
return true;
529528
}
530529

531530
// If the last heartbeat didn't receive an acknowledgement, then auto-reconnect.
@@ -552,10 +551,11 @@ impl Shard {
552551
// <https://github.com/abalabahaha/eris/commit/0ce296ae9a542bcec0edf1c999ee2d9986bed5a6>
553552
#[cfg_attr(feature = "tracing_instrument", instrument(skip(self)))]
554553
pub fn latency(&self) -> Option<StdDuration> {
555-
if let (Some(sent), Some(received)) = (self.last_heartbeat_sent, self.last_heartbeat_ack) {
556-
if received > sent {
557-
return Some(received - sent);
558-
}
554+
if let Some(sent) = self.last_heartbeat_sent
555+
&& let Some(received) = self.last_heartbeat_ack
556+
&& received > sent
557+
{
558+
return Some(received - sent);
559559
}
560560

561561
None

0 commit comments

Comments
 (0)