about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-03-10 08:01:32 +0900
committerGitHub <noreply@github.com>2021-03-10 08:01:32 +0900
commit1c3fea2f8c167451f3f23b9a48463bd1fed836ae (patch)
tree200249d518c76d6a72b3eb344606ba7643b90320
parent48a393e10bb17a5f123d24bfddc9fbb034f0cc10 (diff)
parent1cc8c4de6aa0549a3d7d1da23ba48d34d0efd7bf (diff)
downloadrust-1c3fea2f8c167451f3f23b9a48463bd1fed836ae.tar.gz
rust-1c3fea2f8c167451f3f23b9a48463bd1fed836ae.zip
Rollup merge of #82849 - camsteffen:option-get-or-default, r=joshtriplett
Add Option::get_or_default

Tracking issue: #82901

The original issue is #55042, which was closed, but for an invalid reason (see discussion there). Opening this to reconsider (I hope that's okay). It seems like the only gap for `Option` being "entry-like".

I ran into a need for this method where I had a `Vec<Option<MyData>>` and wanted to do `vec[n].get_or_default().my_data_method()`. Using an `Option` as an inner component of a data structure is probably where the need for this will normally arise.
-rw-r--r--compiler/rustc_mir/src/lib.rs1
-rw-r--r--compiler/rustc_mir/src/transform/coverage/graph.rs5
-rw-r--r--library/core/src/option.rs28
3 files changed, 30 insertions, 4 deletions
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 508510a81e1..bbfcec5a76a 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -25,6 +25,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
 #![feature(option_expect_none)]
+#![feature(option_get_or_default)]
 #![feature(or_patterns)]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs
index e58b915f126..8ad0d133b17 100644
--- a/compiler/rustc_mir/src/transform/coverage/graph.rs
+++ b/compiler/rustc_mir/src/transform/coverage/graph.rs
@@ -392,10 +392,7 @@ impl BasicCoverageBlockData {
             }
         }
         let operand = counter_kind.as_operand_id();
-        if let Some(replaced) = self
-            .edge_from_bcbs
-            .get_or_insert_with(FxHashMap::default)
-            .insert(from_bcb, counter_kind)
+        if let Some(replaced) = self.edge_from_bcbs.get_or_default().insert(from_bcb, counter_kind)
         {
             Error::from_string(format!(
                 "attempt to set an edge counter more than once; from_bcb: \
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index e3c812a047c..9478e7f06bd 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -854,6 +854,34 @@ impl<T> Option<T> {
     // Entry-like operations to insert if None and return a reference
     /////////////////////////////////////////////////////////////////////////
 
+    /// Inserts the default value into the option if it is [`None`], then
+    /// returns a mutable reference to the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_get_or_default)]
+    ///
+    /// let mut x = None;
+    ///
+    /// {
+    ///     let y: &mut u32 = x.get_or_default();
+    ///     assert_eq!(y, &0);
+    ///
+    ///     *y = 7;
+    /// }
+    ///
+    /// assert_eq!(x, Some(7));
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_get_or_default", issue = "82901")]
+    pub fn get_or_default(&mut self) -> &mut T
+    where
+        T: Default,
+    {
+        self.get_or_insert_with(Default::default)
+    }
+
     /// Inserts `value` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///