You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/10/02 09:08:12 UTC

(datafusion) 01/01: chore: Upgrade to Rust 1.99, MSRV to 1.95 (#25935)

This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-25935-4d167a167228a424ef8cc29fd6bea5f17fc23c2a
in repository https://gitbox.apache.org/repos/asf/datafusion.git

commit c297f83cb107b9546b23aba154be67ef88662b72
Author: Neil Conway <ne...@gmail.com>
AuthorDate: Fri Oct 2 09:07:44 2026 +0000

    chore: Upgrade to Rust 1.99, MSRV to 1.95 (#25935)
    
    ## Which issue does this PR close?
    
    - N/A
    
    ## Rationale for this change
    
    Update the Rust toolchain version to 1.99, and the MSRV to Rust 1.95.
    
    The MSRV bump is because 1.99 deprecates `AtomicUsize::fetch_update` in
    favour of `AtomicUsize::try_update`, but the latter was only stabilized
    in Rust 1.95.
    
    Rust 1.99 moves from LLVM 22.1.8 to LLVM 23.1.1. I haven't attempted to
    validate how that impacts codegen.
    
    ## What changes are included in this PR?
    
    * Fix various new clippy warnings
    * Add migration guide note for MSRV bump
    
    ## What is the testing strategy for this PR?
    
    Existing tests pass.
    
    ## Are there any user-facing changes?
    
    Yes, MSRV bump.
---
 Cargo.toml                                                |  3 ++-
 datafusion/common/src/param_value.rs                      |  3 +--
 datafusion/core/benches/data_utils/mod.rs                 |  2 +-
 datafusion/core/tests/datasource/object_store_access.rs   |  6 +-----
 .../tests/memory_limit/memory_limit_validation/utils.rs   | 10 +---------
 datafusion/datasource-parquet/src/source.rs               |  3 +--
 datafusion/datasource/src/mod.rs                          |  2 +-
 datafusion/execution/src/memory_pool/mod.rs               |  6 +++---
 datafusion/execution/src/memory_pool/pool.rs              |  2 +-
 datafusion/expr/src/lib.rs                                |  2 +-
 datafusion/expr/src/proto.rs                              |  3 +--
 datafusion/functions-aggregate/src/first_last.rs          | 15 +++++----------
 datafusion/functions/src/core/getfield.rs                 | 13 ++++---------
 datafusion/physical-plan/src/coalesce_batches.rs          |  4 +---
 datafusion/physical-plan/src/repartition/mod.rs           |  3 +--
 .../physical-plan/src/sorts/sort_preserving_merge.rs      |  5 +----
 datafusion/physical-plan/src/streaming.rs                 |  5 +----
 datafusion/physical-plan/src/topk/mod.rs                  |  2 +-
 .../substrait/src/logical_plan/consumer/rel/fetch_rel.rs  |  4 ++++
 .../substrait/src/logical_plan/consumer/rel/filter_rel.rs |  4 ++++
 datafusion/substrait/src/logical_plan/consumer/rel/mod.rs |  4 ++++
 .../src/logical_plan/consumer/rel/project_rel.rs          |  4 ++++
 datafusion/substrait/src/physical_plan/consumer.rs        |  4 ++++
 dev/depcheck/rust-toolchain.toml                          |  2 +-
 docs/source/contributor-guide/development_environment.md  |  2 +-
 docs/source/library-user-guide/upgrading/56.0.0.md        |  6 ++++++
 rust-toolchain.toml                                       |  2 +-
 27 files changed, 57 insertions(+), 64 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 8da1274aa9..7bbfe851fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -79,7 +79,7 @@ license = "Apache-2.0"
 readme = "README.md"
 repository = "https://github.com/apache/datafusion"
 # Define Minimum Supported Rust Version (MSRV)
-rust-version = "1.94.0"
+rust-version = "1.95.0"
 # Define DataFusion version
 version = "55.1.0"
 
@@ -273,6 +273,7 @@ wildcard_dependencies = "warn"
 
 # Pedantic lints we opt out of, with the number of hits at the time we enabled `pedantic`.
 # Some of these we should consider enabling.
+assert_is_empty = "allow"                    # 105 hits
 cast_lossless = "allow"                      # 361 hits
 cast_possible_truncation = "allow"           # 911 hits
 cast_possible_wrap = "allow"                 # 493 hits
diff --git a/datafusion/common/src/param_value.rs b/datafusion/common/src/param_value.rs
index 1979daa7e3..c228dd451a 100644
--- a/datafusion/common/src/param_value.rs
+++ b/datafusion/common/src/param_value.rs
@@ -71,14 +71,13 @@ impl ParamValues {
                         &format!(" at index {i}"),
                     )?;
                 }
-                Ok(())
             }
             ParamValues::Map(_) => {
                 // If it is a named query, variables can be reused,
                 // but the lengths are not necessarily equal
-                Ok(())
             }
         }
+        Ok(())
     }
 
     pub fn get_placeholders_with_values(&self, id: &str) -> Result<ScalarAndMetadata> {
diff --git a/datafusion/core/benches/data_utils/mod.rs b/datafusion/core/benches/data_utils/mod.rs
index 728c6490c7..992ef0b47a 100644
--- a/datafusion/core/benches/data_utils/mod.rs
+++ b/datafusion/core/benches/data_utils/mod.rs
@@ -233,7 +233,7 @@ pub(crate) fn make_data(
                 })
         };
         let gen_sample_cnt =
-            |mut rng: &mut rand::rngs::SmallRng| pareto.sample(&mut rng).ceil() as u32;
+            |rng: &mut rand::rngs::SmallRng| pareto.sample(rng).ceil() as u32;
         let mut group_ids = (0..simultaneous_group_cnt)
             .map(|_| gen_id(&mut rng))
             .collect::<Vec<_>>();
diff --git a/datafusion/core/tests/datasource/object_store_access.rs b/datafusion/core/tests/datasource/object_store_access.rs
index c494f0ee8e..215725cf04 100644
--- a/datafusion/core/tests/datasource/object_store_access.rs
+++ b/datafusion/core/tests/datasource/object_store_access.rs
@@ -1395,7 +1395,6 @@ impl Display for RequestDetails {
                 if get_options.head {
                     write!(f, " head=true")?;
                 }
-                Ok(())
             }
             RequestDetails::GetRanges { path, ranges } => {
                 write!(f, "GET  (ranges) path={path}")?;
@@ -1408,30 +1407,27 @@ impl Display for RequestDetails {
                         write!(f, "{}", display_range(range))?;
                     }
                 }
-                Ok(())
             }
             RequestDetails::List { prefix } => {
                 write!(f, "LIST")?;
                 if let Some(prefix) = prefix {
                     write!(f, " prefix={prefix}")?;
                 }
-                Ok(())
             }
             RequestDetails::ListWithDelimiter { prefix } => {
                 write!(f, "LIST (with delimiter)")?;
                 if let Some(prefix) = prefix {
                     write!(f, " prefix={prefix}")?;
                 }
-                Ok(())
             }
             RequestDetails::ListWithOffset { prefix, offset } => {
                 write!(f, "LIST (with offset) offset={offset}")?;
                 if let Some(prefix) = prefix {
                     write!(f, " prefix={prefix}")?;
                 }
-                Ok(())
             }
         }
+        Ok(())
     }
 }
 
diff --git a/datafusion/core/tests/memory_limit/memory_limit_validation/utils.rs b/datafusion/core/tests/memory_limit/memory_limit_validation/utils.rs
index 788b8f4942..aae30418b2 100644
--- a/datafusion/core/tests/memory_limit/memory_limit_validation/utils.rs
+++ b/datafusion/core/tests/memory_limit/memory_limit_validation/utils.rs
@@ -70,15 +70,7 @@ where
             );
             if let Some(process) = sys.process(pid) {
                 let rss_bytes = process.memory();
-                max_rss_clone
-                    .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
-                        if rss_bytes as usize > current {
-                            Some(rss_bytes as usize)
-                        } else {
-                            None
-                        }
-                    })
-                    .ok();
+                max_rss_clone.fetch_max(rss_bytes as usize, Ordering::Relaxed);
             } else {
                 // Process no longer exists
                 break;
diff --git a/datafusion/datasource-parquet/src/source.rs b/datafusion/datasource-parquet/src/source.rs
index a5c165abb1..4959a56ce6 100644
--- a/datafusion/datasource-parquet/src/source.rs
+++ b/datafusion/datasource-parquet/src/source.rs
@@ -844,15 +844,14 @@ impl FileSource for ParquetSource {
                         )?;
                     }
                 }
-                Ok(())
             }
             DisplayFormatType::TreeRender => {
                 if let Some(predicate) = self.filter() {
                     writeln!(f, "predicate={}", fmt_sql(predicate.as_ref()))?;
                 }
-                Ok(())
             }
         }
+        Ok(())
     }
 
     fn try_pushdown_filters(
diff --git a/datafusion/datasource/src/mod.rs b/datafusion/datasource/src/mod.rs
index 6135835616..86549a96b3 100644
--- a/datafusion/datasource/src/mod.rs
+++ b/datafusion/datasource/src/mod.rs
@@ -42,7 +42,7 @@ pub mod memory;
 pub mod morsel;
 pub mod projection;
 /// Protobuf conversions for [`FileRange`], [`PartitionedFile`] and
-/// [`FileGroup`](crate::file_groups::FileGroup), gated on the `proto` feature.
+/// [`FileGroup`], gated on the `proto` feature.
 #[cfg(feature = "proto")]
 mod proto;
 pub mod schema_adapter;
diff --git a/datafusion/execution/src/memory_pool/mod.rs b/datafusion/execution/src/memory_pool/mod.rs
index 09cef6ddd4..2686f7ef38 100644
--- a/datafusion/execution/src/memory_pool/mod.rs
+++ b/datafusion/execution/src/memory_pool/mod.rs
@@ -412,7 +412,7 @@ impl MemoryReservation {
     /// Panics if `capacity` exceeds [`Self::size`]
     pub fn shrink(&self, capacity: usize) {
         self.size
-            .fetch_update(
+            .try_update(
                 atomic::Ordering::Relaxed,
                 atomic::Ordering::Relaxed,
                 |prev| prev.checked_sub(capacity),
@@ -430,7 +430,7 @@ impl MemoryReservation {
     pub fn try_shrink(&self, capacity: usize) -> Result<usize> {
         let prev = self
             .size
-            .fetch_update(
+            .try_update(
                 atomic::Ordering::Relaxed,
                 atomic::Ordering::Relaxed,
                 |prev| prev.checked_sub(capacity),
@@ -495,7 +495,7 @@ impl MemoryReservation {
     /// Panics if `capacity` exceeds [`Self::size`]
     pub fn split(&self, capacity: usize) -> MemoryReservation {
         self.size
-            .fetch_update(
+            .try_update(
                 atomic::Ordering::Relaxed,
                 atomic::Ordering::Relaxed,
                 |prev| prev.checked_sub(capacity),
diff --git a/datafusion/execution/src/memory_pool/pool.rs b/datafusion/execution/src/memory_pool/pool.rs
index f291d7052a..0d05efb8be 100644
--- a/datafusion/execution/src/memory_pool/pool.rs
+++ b/datafusion/execution/src/memory_pool/pool.rs
@@ -105,7 +105,7 @@ impl MemoryPool for GreedyMemoryPool {
 
     fn try_grow(&self, reservation: &MemoryReservation, additional: usize) -> Result<()> {
         self.used
-            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |used| {
+            .try_update(Ordering::Relaxed, Ordering::Relaxed, |used| {
                 let new_used = used + additional;
                 (new_used <= self.pool_size).then_some(new_used)
             })
diff --git a/datafusion/expr/src/lib.rs b/datafusion/expr/src/lib.rs
index 48ed38e8f4..8a21dc6693 100644
--- a/datafusion/expr/src/lib.rs
+++ b/datafusion/expr/src/lib.rs
@@ -70,7 +70,7 @@ pub mod dml {
 }
 pub mod planner;
 /// Protobuf conversions for [`WindowFrame`], [`WindowFrameBound`],
-/// [`WindowFrameUnits`], [`MergeIntoClauseKind`](dml::MergeIntoClauseKind) and
+/// [`WindowFrameUnits`], [`MergeIntoClauseKind`] and
 /// [`NullTreatment`](expr::NullTreatment), gated on the `proto` feature.
 #[cfg(feature = "proto")]
 mod proto;
diff --git a/datafusion/expr/src/proto.rs b/datafusion/expr/src/proto.rs
index 00b3402108..8bced7106f 100644
--- a/datafusion/expr/src/proto.rs
+++ b/datafusion/expr/src/proto.rs
@@ -17,8 +17,7 @@
 
 //! Protobuf conversions for the expression types owned by this crate:
 //! [`WindowFrame`], [`WindowFrameBound`], [`WindowFrameUnits`],
-//! [`MergeIntoClauseKind`](crate::dml::MergeIntoClauseKind) and
-//! [`NullTreatment`](crate::expr::NullTreatment).
+//! [`MergeIntoClauseKind`] and [`NullTreatment`](crate::expr::NullTreatment).
 //!
 //! These are plain [`From`] / [`TryFrom`] impls rather than something taking a
 //! codec: every field is either an enum tag or a [`ScalarValue`], so the
diff --git a/datafusion/functions-aggregate/src/first_last.rs b/datafusion/functions-aggregate/src/first_last.rs
index d9254c0d2a..17be6359cf 100644
--- a/datafusion/functions-aggregate/src/first_last.rs
+++ b/datafusion/functions-aggregate/src/first_last.rs
@@ -900,17 +900,12 @@ impl<S: ValueState + 'static> GroupsAccumulator for FirstLastGroupsAccumulator<S
         values: &[ArrayRef],
         opt_filter: Option<&BooleanArray>,
     ) -> Result<Vec<ArrayRef>> {
+        let filter = opt_filter
+            .cloned()
+            .unwrap_or_else(|| BooleanArray::from(vec![true; values[0].len()]));
         let mut result = values.to_vec();
-        match opt_filter {
-            Some(f) => {
-                result.push(Arc::new(f.clone()));
-                Ok(result)
-            }
-            None => {
-                result.push(Arc::new(BooleanArray::from(vec![true; values[0].len()])));
-                Ok(result)
-            }
-        }
+        result.push(Arc::new(filter));
+        Ok(result)
     }
 }
 
diff --git a/datafusion/functions/src/core/getfield.rs b/datafusion/functions/src/core/getfield.rs
index 2b75623daa..07ae4b1f2e 100644
--- a/datafusion/functions/src/core/getfield.rs
+++ b/datafusion/functions/src/core/getfield.rs
@@ -327,15 +327,13 @@ impl ScalarUDFImpl for GetFieldFunc {
             match current_field.data_type() {
                 DataType::Map(map_field, _) => {
                     match map_field.data_type() {
-                        DataType::Struct(fields) if fields.len() == 2 => {
+                        DataType::Struct(fields)
+                            if let [_, value_field] = &fields[..] =>
+                        {
                             // Arrow's MapArray is essentially a ListArray of structs with two columns. They are
                             // often named "key", and "value", but we don't require any specific naming here;
                             // instead, we assume that the second column is the "value" column both here and in
                             // execution.
-                            let value_field = fields
-                                .get(1)
-                                .expect("fields should have exactly two members");
-
                             current_field = Arc::new(
                                 value_field.as_ref().clone().with_nullable(true),
                             );
@@ -351,11 +349,8 @@ impl ScalarUDFImpl for GetFieldFunc {
                 // the underlying struct, then wrap the result back in the
                 // same Dictionary type so the promised type matches execution.
                 DataType::Dictionary(key_type, value_type)
-                    if matches!(value_type.as_ref(), DataType::Struct(_)) =>
+                    if let DataType::Struct(fields) = value_type.as_ref() =>
                 {
-                    let DataType::Struct(fields) = value_type.as_ref() else {
-                        unreachable!()
-                    };
                     let field_name = sv
                         .as_ref()
                         .and_then(|sv| {
diff --git a/datafusion/physical-plan/src/coalesce_batches.rs b/datafusion/physical-plan/src/coalesce_batches.rs
index 9da7df822f..7068dc28b2 100644
--- a/datafusion/physical-plan/src/coalesce_batches.rs
+++ b/datafusion/physical-plan/src/coalesce_batches.rs
@@ -137,17 +137,15 @@ impl DisplayAs for CoalesceBatchesExec {
                 if let Some(fetch) = self.fetch {
                     write!(f, ", fetch={fetch}")?;
                 }
-
-                Ok(())
             }
             DisplayFormatType::TreeRender => {
                 writeln!(f, "target_batch_size={}", self.target_batch_size)?;
                 if let Some(fetch) = self.fetch {
                     write!(f, "limit={fetch}")?;
                 }
-                Ok(())
             }
         }
+        Ok(())
     }
 }
 
diff --git a/datafusion/physical-plan/src/repartition/mod.rs b/datafusion/physical-plan/src/repartition/mod.rs
index d2d8ec38da..3df29b577c 100644
--- a/datafusion/physical-plan/src/repartition/mod.rs
+++ b/datafusion/physical-plan/src/repartition/mod.rs
@@ -1628,7 +1628,6 @@ impl DisplayAs for RepartitionExec {
                 if let Some(sort_exprs) = self.sort_exprs() {
                     write!(f, ", sort_exprs={}", sort_exprs.clone())?;
                 }
-                Ok(())
             }
             DisplayFormatType::TreeRender => {
                 writeln!(f, "partitioning_scheme={}", self.partitioning())?;
@@ -1643,9 +1642,9 @@ impl DisplayAs for RepartitionExec {
                 if self.preserve_order {
                     writeln!(f, "preserve_order={}", self.preserve_order)?;
                 }
-                Ok(())
             }
         }
+        Ok(())
     }
 }
 
diff --git a/datafusion/physical-plan/src/sorts/sort_preserving_merge.rs b/datafusion/physical-plan/src/sorts/sort_preserving_merge.rs
index 3551631b41..7c924ff32b 100644
--- a/datafusion/physical-plan/src/sorts/sort_preserving_merge.rs
+++ b/datafusion/physical-plan/src/sorts/sort_preserving_merge.rs
@@ -199,8 +199,6 @@ impl DisplayAs for SortPreservingMergeExec {
                 if let Some(fetch) = self.fetch {
                     write!(f, ", fetch={fetch}")?;
                 }
-
-                Ok(())
             }
             DisplayFormatType::TreeRender => {
                 if let Some(fetch) = self.fetch {
@@ -213,10 +211,9 @@ impl DisplayAs for SortPreservingMergeExec {
                         write!(f, ", ")?;
                     }
                 }
-
-                Ok(())
             }
         }
+        Ok(())
     }
 }
 
diff --git a/datafusion/physical-plan/src/streaming.rs b/datafusion/physical-plan/src/streaming.rs
index dd57f958e8..e58de52ae9 100644
--- a/datafusion/physical-plan/src/streaming.rs
+++ b/datafusion/physical-plan/src/streaming.rs
@@ -239,8 +239,6 @@ impl DisplayAs for StreamingTableExec {
                 }
 
                 display_orderings(f, &self.projected_output_ordering)?;
-
-                Ok(())
             }
             DisplayFormatType::TreeRender => {
                 if self.infinite {
@@ -251,10 +249,9 @@ impl DisplayAs for StreamingTableExec {
                 } else {
                     write!(f, "limit=None")?;
                 }
-
-                Ok(())
             }
         }
+        Ok(())
     }
 }
 
diff --git a/datafusion/physical-plan/src/topk/mod.rs b/datafusion/physical-plan/src/topk/mod.rs
index d4405c1f12..05743472f9 100644
--- a/datafusion/physical-plan/src/topk/mod.rs
+++ b/datafusion/physical-plan/src/topk/mod.rs
@@ -287,7 +287,7 @@ impl TopKDynamicFilters {
     fn mark_topk_emitted(&self) {
         let previous = self
             .remaining_topk_emitters
-            .fetch_update(
+            .try_update(
                 AtomicOrdering::AcqRel,
                 AtomicOrdering::Acquire,
                 |remaining| remaining.checked_sub(1),
diff --git a/datafusion/substrait/src/logical_plan/consumer/rel/fetch_rel.rs b/datafusion/substrait/src/logical_plan/consumer/rel/fetch_rel.rs
index 12a8a77199..ebc73a3ee3 100644
--- a/datafusion/substrait/src/logical_plan/consumer/rel/fetch_rel.rs
+++ b/datafusion/substrait/src/logical_plan/consumer/rel/fetch_rel.rs
@@ -22,6 +22,10 @@ use datafusion::logical_expr::{LogicalPlan, LogicalPlanBuilder, lit};
 use substrait::proto::{FetchRel, fetch_rel};
 
 #[async_recursion]
+#[expect(
+    clippy::double_must_use,
+    reason = "`async_recursion` adds `#[must_use]` to the boxed future it returns"
+)]
 pub async fn from_fetch_rel(
     consumer: &impl SubstraitConsumer,
     fetch: &FetchRel,
diff --git a/datafusion/substrait/src/logical_plan/consumer/rel/filter_rel.rs b/datafusion/substrait/src/logical_plan/consumer/rel/filter_rel.rs
index 645b982782..ac527d95c9 100644
--- a/datafusion/substrait/src/logical_plan/consumer/rel/filter_rel.rs
+++ b/datafusion/substrait/src/logical_plan/consumer/rel/filter_rel.rs
@@ -22,6 +22,10 @@ use datafusion::logical_expr::{LogicalPlan, LogicalPlanBuilder};
 use substrait::proto::FilterRel;
 
 #[async_recursion]
+#[expect(
+    clippy::double_must_use,
+    reason = "`async_recursion` adds `#[must_use]` to the boxed future it returns"
+)]
 pub async fn from_filter_rel(
     consumer: &impl SubstraitConsumer,
     filter: &FilterRel,
diff --git a/datafusion/substrait/src/logical_plan/consumer/rel/mod.rs b/datafusion/substrait/src/logical_plan/consumer/rel/mod.rs
index 038ada115b..f95c2e7dd2 100644
--- a/datafusion/substrait/src/logical_plan/consumer/rel/mod.rs
+++ b/datafusion/substrait/src/logical_plan/consumer/rel/mod.rs
@@ -50,6 +50,10 @@ use substrait::proto::{Rel, RelCommon, rel_common};
 
 /// Convert Substrait Rel to DataFusion DataFrame
 #[async_recursion]
+#[expect(
+    clippy::double_must_use,
+    reason = "`async_recursion` adds `#[must_use]` to the boxed future it returns"
+)]
 pub async fn from_substrait_rel(
     consumer: &impl SubstraitConsumer,
     relation: &Rel,
diff --git a/datafusion/substrait/src/logical_plan/consumer/rel/project_rel.rs b/datafusion/substrait/src/logical_plan/consumer/rel/project_rel.rs
index fa93add0ff..211ccdd848 100644
--- a/datafusion/substrait/src/logical_plan/consumer/rel/project_rel.rs
+++ b/datafusion/substrait/src/logical_plan/consumer/rel/project_rel.rs
@@ -29,6 +29,10 @@ use std::sync::Arc;
 use substrait::proto::ProjectRel;
 
 #[async_recursion]
+#[expect(
+    clippy::double_must_use,
+    reason = "`async_recursion` adds `#[must_use]` to the boxed future it returns"
+)]
 pub async fn from_project_rel(
     consumer: &impl SubstraitConsumer,
     p: &ProjectRel,
diff --git a/datafusion/substrait/src/physical_plan/consumer.rs b/datafusion/substrait/src/physical_plan/consumer.rs
index 3c0df01b4a..eb971e0a3c 100644
--- a/datafusion/substrait/src/physical_plan/consumer.rs
+++ b/datafusion/substrait/src/physical_plan/consumer.rs
@@ -46,6 +46,10 @@ use substrait::proto::{
 
 /// Convert Substrait Rel to DataFusion ExecutionPlan
 #[async_recursion]
+#[expect(
+    clippy::double_must_use,
+    reason = "`async_recursion` adds `#[must_use]` to the boxed future it returns"
+)]
 pub async fn from_substrait_rel(
     _ctx: &SessionContext,
     rel: &Rel,
diff --git a/dev/depcheck/rust-toolchain.toml b/dev/depcheck/rust-toolchain.toml
index 8a06035a6a..d3483e9f75 100644
--- a/dev/depcheck/rust-toolchain.toml
+++ b/dev/depcheck/rust-toolchain.toml
@@ -19,5 +19,5 @@
 # to compile this workspace and run CI jobs.
 
 [toolchain]
-channel = "1.98.1"
+channel = "1.99.0"
 components = ["rustfmt", "clippy"]
diff --git a/docs/source/contributor-guide/development_environment.md b/docs/source/contributor-guide/development_environment.md
index 20cfd6edd0..f54ac75d89 100644
--- a/docs/source/contributor-guide/development_environment.md
+++ b/docs/source/contributor-guide/development_environment.md
@@ -108,7 +108,7 @@ DataFusion is written in Rust and it uses a standard rust toolkit:
 
 - `rustup update stable` DataFusion generally uses the latest stable release of Rust, though it may lag when new Rust toolchains release
   - See which toolchain is currently pinned in the [`rust-toolchain.toml`](https://github.com/apache/datafusion/blob/main/rust-toolchain.toml) file
-  - This can cause issues such as not having the rust-analyzer component installed for the specified toolchain, in which case just install it manually, e.g. `rustup component add --toolchain 1.98.1 rust-analyzer`
+  - This can cause issues such as not having the rust-analyzer component installed for the specified toolchain, in which case just install it manually, e.g. `rustup component add --toolchain 1.99.0 rust-analyzer`
 - `cargo build`
 - `cargo fmt` to format the code
 - etc.
diff --git a/docs/source/library-user-guide/upgrading/56.0.0.md b/docs/source/library-user-guide/upgrading/56.0.0.md
index 1f1855f76f..6c251c5cfb 100644
--- a/docs/source/library-user-guide/upgrading/56.0.0.md
+++ b/docs/source/library-user-guide/upgrading/56.0.0.md
@@ -25,6 +25,12 @@
 in this section pertains to features and changes that have already been merged
 to the main branch and are awaiting release in this version.
 
+### `MSRV` updated to 1.95.0
+
+The Minimum Supported Rust Version (MSRV) has been updated to [`1.95.0`].
+
+[`1.95.0`]: https://releases.rs/docs/1.95.0/
+
 ### Upgrade arrow/parquet to 60.0.0 and object_store to 0.14.2
 
 DataFusion 56.0.0 uses `arrow` and `parquet` 60.0.0, and `object_store` 0.14.2.
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 8a06035a6a..d3483e9f75 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -19,5 +19,5 @@
 # to compile this workspace and run CI jobs.
 
 [toolchain]
-channel = "1.98.1"
+channel = "1.99.0"
 components = ["rustfmt", "clippy"]


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org