chore!: bump the MSRV to 1.88

let-chains ftw
This commit is contained in:
Benjamin Bouvier
2025-07-22 11:26:26 +02:00
parent 7c8f870d16
commit d19616da03
15 changed files with 169 additions and 168 deletions

View File

@@ -16,7 +16,7 @@ default-members = ["benchmarks", "crates/*", "labs/*"]
resolver = "2"
[workspace.package]
rust-version = "1.85"
rust-version = "1.88"
[workspace.dependencies]
anyhow = "1.0.95"

View File

@@ -25,6 +25,9 @@ All notable changes to this project will be documented in this file.
- `ClientBuilder::build_with_qr_code` has been removed. Instead, the Client should be built by passing
`QrCodeData::server_name` to `ClientBuilder::server_name_or_homeserver_url`, after which QR login can be performed by
calling `Client::login_with_qr_code`. ([#5388](https://github.com/matrix-org/matrix-rust-sdk/pull/5388))
- The MSRV has been bumped to Rust 1.88.
([#5431](https://github.com/matrix-org/matrix-rust-sdk/pull/5431))
## [0.13.0] - 2025-07-10

View File

@@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
## [Unreleased] - ReleaseDate
### Refactor
- [**breaking**] The MSRV has been bumped to Rust 1.88.
([#5431](https://github.com/matrix-org/matrix-rust-sdk/pull/5431))
## [0.13.0] - 2025-07-10
### Features

View File

@@ -747,10 +747,10 @@ impl NotificationClient {
timeline_event = decrypted_event;
}
if let Some(actions) = timeline_event.push_actions() {
if !actions.iter().any(|a| a.should_notify()) {
return Ok(NotificationStatus::EventFilteredOut);
}
if let Some(actions) = timeline_event.push_actions()
&& !actions.iter().any(|a| a.should_notify())
{
return Ok(NotificationStatus::EventFilteredOut);
}
let push_actions = timeline_event.push_actions().map(ToOwned::to_owned);

View File

@@ -377,13 +377,12 @@ impl Aggregations {
// If there was any redaction among the current aggregation, adding a new one
// should be a noop.
if let Some(previous_aggregations) = self.related_events.get(&related_to) {
if previous_aggregations
if let Some(previous_aggregations) = self.related_events.get(&related_to)
&& previous_aggregations
.iter()
.any(|agg| matches!(agg.kind, AggregationKind::Redaction))
{
return;
}
{
return;
}
self.inverted_map.insert(aggregation.own_id.clone(), related_to.clone());
@@ -553,26 +552,26 @@ impl Aggregations {
return false;
};
if let Some(aggregations) = self.related_events.get_mut(&target) {
if let Some(found) = aggregations.iter_mut().find(|agg| agg.own_id == from) {
found.own_id = to.clone();
if let Some(aggregations) = self.related_events.get_mut(&target)
&& let Some(found) = aggregations.iter_mut().find(|agg| agg.own_id == from)
{
found.own_id = to.clone();
match &mut found.kind {
AggregationKind::PollResponse { .. }
| AggregationKind::PollEnd { .. }
| AggregationKind::Edit(..)
| AggregationKind::Redaction => {
// Nothing particular to do.
}
match &mut found.kind {
AggregationKind::PollResponse { .. }
| AggregationKind::PollEnd { .. }
| AggregationKind::Edit(..)
| AggregationKind::Redaction => {
// Nothing particular to do.
}
AggregationKind::Reaction { reaction_status, .. } => {
// Mark the reaction as becoming remote, and signal that update to the
// caller.
*reaction_status = ReactionStatus::RemoteToRemote(event_id);
AggregationKind::Reaction { reaction_status, .. } => {
// Mark the reaction as becoming remote, and signal that update to the
// caller.
*reaction_status = ReactionStatus::RemoteToRemote(event_id);
let found = found.clone();
find_item_and_apply_aggregation(self, items, &target, found, room_version);
}
let found = found.clone();
find_item_and_apply_aggregation(self, items, &target, found, room_version);
}
}
}
@@ -754,16 +753,14 @@ pub(crate) fn find_item_and_apply_aggregation(
Some(new_event_item)
}
ApplyAggregationResult::Edit => {
if let Some(aggregations) = aggregations.related_events.get(target) {
if resolve_edits(aggregations, items, &mut cowed) {
let new_event_item = cowed.into_owned();
let new_item = TimelineItem::new(
new_event_item.clone(),
event_item.internal_id.to_owned(),
);
items.replace(idx, new_item);
return Some(new_event_item);
}
if let Some(aggregations) = aggregations.related_events.get(target)
&& resolve_edits(aggregations, items, &mut cowed)
{
let new_event_item = cowed.into_owned();
let new_item =
TimelineItem::new(new_event_item.clone(), event_item.internal_id.to_owned());
items.replace(idx, new_item);
return Some(new_event_item);
}
None
}

View File

@@ -318,21 +318,21 @@ impl TimelineMetadata {
timeline_items: &Vector<Arc<TimelineItem>>,
is_thread_focus: bool,
) -> (Option<InReplyToDetails>, Option<OwnedEventId>) {
if let AnySyncTimelineEvent::MessageLike(ev) = event {
if let Some(content) = ev.original_content() {
let remote_ctx = Some(RemoteEventContext {
event_id: ev.event_id(),
raw_event,
relations: ev.relations(),
bundled_edit_encryption_info,
});
return self.process_content_relations(
&content,
remote_ctx,
timeline_items,
is_thread_focus,
);
}
if let AnySyncTimelineEvent::MessageLike(ev) = event
&& let Some(content) = ev.original_content()
{
let remote_ctx = Some(RemoteEventContext {
event_id: ev.event_id(),
raw_event,
relations: ev.relations(),
bundled_edit_encryption_info,
});
return self.process_content_relations(
&content,
remote_ctx,
timeline_items,
is_thread_focus,
);
}
(None, None)
}

View File

@@ -850,12 +850,11 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
.await;
}
if track_read_markers {
if let Some(fully_read_event_id) =
if track_read_markers
&& let Some(fully_read_event_id) =
self.room_data_provider.load_fully_read_marker().await
{
state.handle_fully_read_marker(fully_read_event_id);
}
{
state.handle_fully_read_marker(fully_read_event_id);
}
}
@@ -1561,14 +1560,13 @@ impl TimelineController {
SendReceiptType::FullyRead => {
if let Some(prev_event_id) = self.room_data_provider.load_fully_read_marker().await
{
if let Some(relative_pos) = state.meta.compare_events_positions(
&& let Some(relative_pos) = state.meta.compare_events_positions(
&prev_event_id,
event_id,
state.items.all_remote_events(),
) {
return relative_pos == RelativePosition::After;
}
)
{
return relative_pos == RelativePosition::After;
}
}

View File

@@ -2008,10 +2008,10 @@ impl AllRemoteEvents {
) {
self.increment_all_timeline_item_index_after(new_timeline_item_index);
if let Some(event_index) = event_index {
if let Some(event_meta) = self.0.get_mut(event_index) {
event_meta.timeline_item_index = Some(new_timeline_item_index);
}
if let Some(event_index) = event_index
&& let Some(event_meta) = self.0.get_mut(event_index)
{
event_meta.timeline_item_index = Some(new_timeline_item_index);
}
}

View File

@@ -850,15 +850,14 @@ impl<'a, P: RoomDataProvider> TimelineStateTransaction<'a, P> {
TimelineItemPosition::UpdateAt { .. } => {
if let Some(event) =
self.items.get_remote_event_by_event_id_mut(&event_meta.event_id)
&& event.visible != event_meta.visible
{
if event.visible != event_meta.visible {
event.visible = event_meta.visible;
event.visible = event_meta.visible;
if settings.track_read_receipts {
// Since the event's visibility changed, we need to update the read
// receipts of the previous visible event.
self.maybe_update_read_receipts_of_prev_event(&event_meta.event_id);
}
if settings.track_read_receipts {
// Since the event's visibility changed, we need to update the read
// receipts of the previous visible event.
self.maybe_update_read_receipts_of_prev_event(&event_meta.event_id);
}
}
}

View File

@@ -297,16 +297,16 @@ impl DateDividerAdjuster {
if timestamp_to_date(*prev_ts) != event_date {
// The date divider is wrong. Should we replace it with the correct value, or
// remove it entirely?
if let Some(last_event_ts) = latest_event_ts {
if timestamp_to_date(last_event_ts) == event_date {
// There's a previous event with the same date: remove the divider.
trace!(
"removed date divider @ {item_index} between two events \
if let Some(last_event_ts) = latest_event_ts
&& timestamp_to_date(last_event_ts) == event_date
{
// There's a previous event with the same date: remove the divider.
trace!(
"removed date divider @ {item_index} between two events \
that have the same date"
);
self.ops.insert(insert_op_at, DateDividerOperation::Remove(item_index));
return;
}
);
self.ops.insert(insert_op_at, DateDividerOperation::Remove(item_index));
return;
}
// There's no previous event or there's one with a different date: replace
@@ -440,10 +440,10 @@ impl DateDividerAdjuster {
};
// 3. There's no trailing date divider.
if let Some(last) = items.last() {
if last.is_date_divider() {
report.errors.push(DateDividerInsertError::TrailingDateDivider);
}
if let Some(last) = items.last()
&& last.is_date_divider()
{
report.errors.push(DateDividerInsertError::TrailingDateDivider);
}
// 4. Items are properly separated with date dividers.
@@ -456,12 +456,12 @@ impl DateDividerAdjuster {
let ts = ev.timestamp();
// We have the same date as the previous event we've seen.
if let Some(prev_ts) = prev_event_ts {
if !self.is_same_date_divider_group_as(prev_ts, ts) {
report.errors.push(
DateDividerInsertError::MissingDateDividerBetweenEvents { at: i },
);
}
if let Some(prev_ts) = prev_event_ts
&& !self.is_same_date_divider_group_as(prev_ts, ts)
{
report.errors.push(
DateDividerInsertError::MissingDateDividerBetweenEvents { at: i },
);
}
// There is a date divider before us, and it's the same date as our timestamp.
@@ -484,12 +484,10 @@ impl DateDividerAdjuster {
item.kind()
{
// The previous date divider is for a different date.
if let Some(prev_ts) = prev_date_divider_ts {
if self.is_same_date_divider_group_as(prev_ts, *ts) {
report
.errors
.push(DateDividerInsertError::DuplicateDateDivider { at: i });
}
if let Some(prev_ts) = prev_date_divider_ts
&& self.is_same_date_divider_group_as(prev_ts, *ts)
{
report.errors.push(DateDividerInsertError::DuplicateDateDivider { at: i });
}
prev_event_ts = None;
@@ -500,15 +498,14 @@ impl DateDividerAdjuster {
// 5. If there was a read marker at the beginning, there should be one at the
// end.
if let Some(state) = &report.initial_state {
if state.iter().any(|item| item.is_read_marker())
&& !report
.final_state
.iter_remotes_and_locals_regions()
.any(|(_i, item)| item.is_read_marker())
{
report.errors.push(DateDividerInsertError::ReadMarkerDisappeared);
}
if let Some(state) = &report.initial_state
&& state.iter().any(|item| item.is_read_marker())
&& !report
.final_state
.iter_remotes_and_locals_regions()
.any(|(_i, item)| item.is_read_marker())
{
report.errors.push(DateDividerInsertError::ReadMarkerDisappeared);
}
if report.errors.is_empty() { None } else { Some(report) }

View File

@@ -773,14 +773,14 @@ impl ReactionsByKeyBySender {
sender: &UserId,
annotation: &str,
) -> Option<ReactionInfo> {
if let Some(by_user) = self.0.get_mut(annotation) {
if let Some(info) = by_user.swap_remove(sender) {
// If this was the last reaction, remove the annotation entry.
if by_user.is_empty() {
self.0.swap_remove(annotation);
}
return Some(info);
if let Some(by_user) = self.0.get_mut(annotation)
&& let Some(info) = by_user.swap_remove(sender)
{
// If this was the last reaction, remove the annotation entry.
if by_user.is_empty() {
self.0.swap_remove(annotation);
}
return Some(info);
}
None
}

View File

@@ -614,8 +614,8 @@ impl Timeline {
/// This also unsets the unread marker of the room if necessary.
#[instrument(skip(self))]
pub async fn send_multiple_receipts(&self, mut receipts: Receipts) -> Result<()> {
if let Some(fully_read) = &receipts.fully_read {
if !self
if let Some(fully_read) = &receipts.fully_read
&& !self
.controller
.should_send_receipt(
&ReceiptType::FullyRead,
@@ -623,23 +623,21 @@ impl Timeline {
fully_read,
)
.await
{
receipts.fully_read = None;
}
{
receipts.fully_read = None;
}
if let Some(read_receipt) = &receipts.public_read_receipt {
if !self
if let Some(read_receipt) = &receipts.public_read_receipt
&& !self
.controller
.should_send_receipt(&ReceiptType::Read, &ReceiptThread::Unthreaded, read_receipt)
.await
{
receipts.public_read_receipt = None;
}
{
receipts.public_read_receipt = None;
}
if let Some(private_read_receipt) = &receipts.private_read_receipt {
if !self
if let Some(private_read_receipt) = &receipts.private_read_receipt
&& !self
.controller
.should_send_receipt(
&ReceiptType::ReadPrivate,
@@ -647,9 +645,8 @@ impl Timeline {
private_read_receipt,
)
.await
{
receipts.private_read_receipt = None;
}
{
receipts.private_read_receipt = None;
}
let room = self.room();

View File

@@ -171,13 +171,12 @@ impl PinnedEventsRoom for Room {
related_event_filters: Option<Vec<RelationType>>,
) -> BoxFuture<'a, Result<(TimelineEvent, Vec<TimelineEvent>), matrix_sdk::Error>> {
Box::pin(async move {
if let Ok((cache, _handles)) = self.event_cache().await {
if let Some(ret) =
if let Ok((cache, _handles)) = self.event_cache().await
&& let Some(ret) =
cache.find_event_with_relations(event_id, related_event_filters).await
{
debug!("Loaded pinned event {event_id} and related events from cache");
return Ok(ret);
}
{
debug!("Loaded pinned event {event_id} and related events from cache");
return Ok(ret);
}
debug!("Loading pinned event {event_id} from HS");

View File

@@ -110,22 +110,22 @@ async fn test_sync_service_state() -> anyhow::Result<()> {
let mut json_value = serde_json::from_slice::<serde_json::Value>(&request.body).unwrap();
if let Some(root) = json_value.as_object_mut() {
if let Some(conn_id) = root.get("conn_id").and_then(|obj| obj.as_str()) {
if conn_id == "encryption" {
num_encryption_sync_requests += 1;
} else if conn_id == "room-list" {
num_room_list_requests += 1;
if let Some(root) = json_value.as_object_mut()
&& let Some(conn_id) = root.get("conn_id").and_then(|obj| obj.as_str())
{
if conn_id == "encryption" {
num_encryption_sync_requests += 1;
} else if conn_id == "room-list" {
num_room_list_requests += 1;
// Retrieve the position used in the query.
for (key, val) in request.url.query_pairs() {
if key == "pos" {
latest_room_list_pos = Some(val.to_string());
}
// Retrieve the position used in the query.
for (key, val) in request.url.query_pairs() {
if key == "pos" {
latest_room_list_pos = Some(val.to_string());
}
} else {
panic!("unexpected conn id seen server side: {conn_id}");
}
} else {
panic!("unexpected conn id seen server side: {conn_id}");
}
}
}
@@ -167,29 +167,29 @@ async fn test_sync_service_state() -> anyhow::Result<()> {
let mut json_value = serde_json::from_slice::<serde_json::Value>(&request.body).unwrap();
if let Some(root) = json_value.as_object_mut() {
if let Some(conn_id) = root.get("conn_id").and_then(|obj| obj.as_str()) {
if conn_id == "encryption" {
num_encryption_sync_requests += 1;
} else if conn_id == "room-list" {
if num_room_list_requests == 0 {
// Either it's the same pos, or it's the next one if the request could be
// processed by the client.
let mut current_pos = None;
for (key, val) in request.url.query_pairs() {
if key == "pos" {
current_pos = Some(val);
}
if let Some(root) = json_value.as_object_mut()
&& let Some(conn_id) = root.get("conn_id").and_then(|obj| obj.as_str())
{
if conn_id == "encryption" {
num_encryption_sync_requests += 1;
} else if conn_id == "room-list" {
if num_room_list_requests == 0 {
// Either it's the same pos, or it's the next one if the request could be
// processed by the client.
let mut current_pos = None;
for (key, val) in request.url.query_pairs() {
if key == "pos" {
current_pos = Some(val);
}
let current_pos: i32 = current_pos.unwrap().parse()?;
let prev_pos: i32 = latest_room_list_pos.take().unwrap().parse()?;
assert!((current_pos - prev_pos).abs() <= 1);
}
num_room_list_requests += 1;
} else {
panic!("unexpected conn id seen server side: {conn_id}");
let current_pos: i32 = current_pos.unwrap().parse()?;
let prev_pos: i32 = latest_room_list_pos.take().unwrap().parse()?;
assert!((current_pos - prev_pos).abs() <= 1);
}
num_room_list_requests += 1;
} else {
panic!("unexpected conn id seen server side: {conn_id}");
}
}
}

View File

@@ -19,6 +19,11 @@ All notable changes to this project will be documented in this file.
- [**breaking**] `OAuth::login` now allows requesting additional scopes for the authorization code grant.
([#5395](https://github.com/matrix-org/matrix-rust-sdk/pull/5395))
### Refactor
- [**breaking**] The MSRV has been bumped to Rust 1.88.
([#5431](https://github.com/matrix-org/matrix-rust-sdk/pull/5431))
## [0.13.0] - 2025-07-10
### Security Fixes