Skip to content

Commit 242ed0b

Browse files
committed
Auto merge of #22930 - Gankro:entry_3, r=aturon
RFC pending, but this is the patch that does it. Totally untested. Likely needs some removed imports. std::collections docs should also be updated to provide better examples. Closes #23508
2 parents 53a183f + 1b98f6d commit 242ed0b

File tree

16 files changed

+102
-93
lines changed

16 files changed

+102
-93
lines changed

src/libcollections/btree/map.rs

+27-12
Original file line numberDiff line numberDiff line change
@@ -1143,15 +1143,39 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
11431143
}
11441144

11451145
impl<'a, K: Ord, V> Entry<'a, K, V> {
1146-
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
11471146
#[unstable(feature = "std_misc",
11481147
reason = "will soon be replaced by or_insert")]
1148+
#[deprecated(since = "1.0",
1149+
reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
1150+
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
11491151
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
11501152
match self {
11511153
Occupied(entry) => Ok(entry.into_mut()),
11521154
Vacant(entry) => Err(entry),
11531155
}
11541156
}
1157+
1158+
#[unstable(feature = "collections",
1159+
reason = "matches entry v3 specification, waiting for dust to settle")]
1160+
/// Ensures a value is in the entry by inserting the default if empty, and returns
1161+
/// a mutable reference to the value in the entry.
1162+
pub fn or_insert(self, default: V) -> &'a mut V {
1163+
match self {
1164+
Occupied(entry) => entry.into_mut(),
1165+
Vacant(entry) => entry.insert(default),
1166+
}
1167+
}
1168+
1169+
#[unstable(feature = "collections",
1170+
reason = "matches entry v3 specification, waiting for dust to settle")]
1171+
/// Ensures a value is in the entry by inserting the result of the default function if empty,
1172+
/// and returns a mutable reference to the value in the entry.
1173+
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
1174+
match self {
1175+
Occupied(entry) => entry.into_mut(),
1176+
Vacant(entry) => entry.insert(default()),
1177+
}
1178+
}
11551179
}
11561180

11571181
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
@@ -1563,21 +1587,12 @@ impl<K: Ord, V> BTreeMap<K, V> {
15631587
/// ```
15641588
/// # #![feature(collections)]
15651589
/// use std::collections::BTreeMap;
1566-
/// use std::collections::btree_map::Entry;
15671590
///
15681591
/// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
15691592
///
15701593
/// // count the number of occurrences of letters in the vec
1571-
/// for x in vec!["a","b","a","c","a","b"].iter() {
1572-
/// match count.entry(*x) {
1573-
/// Entry::Vacant(view) => {
1574-
/// view.insert(1);
1575-
/// },
1576-
/// Entry::Occupied(mut view) => {
1577-
/// let v = view.get_mut();
1578-
/// *v += 1;
1579-
/// },
1580-
/// }
1594+
/// for x in vec!["a","b","a","c","a","b"] {
1595+
/// *count.entry(x).or_insert(0) += 1;
15811596
/// }
15821597
///
15831598
/// assert_eq!(count["a"], 3);

src/libcollections/vec_map.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -632,21 +632,12 @@ impl<V> VecMap<V> {
632632
/// ```
633633
/// # #![feature(collections)]
634634
/// use std::collections::VecMap;
635-
/// use std::collections::vec_map::Entry;
636635
///
637636
/// let mut count: VecMap<u32> = VecMap::new();
638637
///
639638
/// // count the number of occurrences of numbers in the vec
640-
/// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4].iter() {
641-
/// match count.entry(*x) {
642-
/// Entry::Vacant(view) => {
643-
/// view.insert(1);
644-
/// },
645-
/// Entry::Occupied(mut view) => {
646-
/// let v = view.get_mut();
647-
/// *v += 1;
648-
/// },
649-
/// }
639+
/// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4] {
640+
/// *count.entry(x).or_insert(0) += 1;
650641
/// }
651642
///
652643
/// assert_eq!(count[1], 3);
@@ -675,13 +666,37 @@ impl<V> VecMap<V> {
675666
impl<'a, V> Entry<'a, V> {
676667
#[unstable(feature = "collections",
677668
reason = "will soon be replaced by or_insert")]
669+
#[deprecated(since = "1.0",
670+
reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
678671
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
679672
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> {
680673
match self {
681674
Occupied(entry) => Ok(entry.into_mut()),
682675
Vacant(entry) => Err(entry),
683676
}
684677
}
678+
679+
#[unstable(feature = "collections",
680+
reason = "matches entry v3 specification, waiting for dust to settle")]
681+
/// Ensures a value is in the entry by inserting the default if empty, and returns
682+
/// a mutable reference to the value in the entry.
683+
pub fn or_insert(self, default: V) -> &'a mut V {
684+
match self {
685+
Occupied(entry) => entry.into_mut(),
686+
Vacant(entry) => entry.insert(default),
687+
}
688+
}
689+
690+
#[unstable(feature = "collections",
691+
reason = "matches entry v3 specification, waiting for dust to settle")]
692+
/// Ensures a value is in the entry by inserting the result of the default function if empty,
693+
/// and returns a mutable reference to the value in the entry.
694+
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
695+
match self {
696+
Occupied(entry) => entry.into_mut(),
697+
Vacant(entry) => entry.insert(default()),
698+
}
699+
}
685700
}
686701

687702
impl<'a, V> VacantEntry<'a, V> {

src/librustc/metadata/loader.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,8 @@ impl<'a> Context<'a> {
426426
info!("lib candidate: {}", path.display());
427427

428428
let hash_str = hash.to_string();
429-
let slot = candidates.entry(hash_str).get().unwrap_or_else(
430-
|vacant_entry| vacant_entry.insert((HashMap::new(), HashMap::new())));
429+
let slot = candidates.entry(hash_str)
430+
.or_insert_with(|| (HashMap::new(), HashMap::new()));
431431
let (ref mut rlibs, ref mut dylibs) = *slot;
432432
if rlib {
433433
rlibs.insert(fs::realpath(path).unwrap(), kind);

src/librustc/middle/dataflow.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
160160

161161
cfg.graph.each_node(|node_idx, node| {
162162
if let cfg::CFGNodeData::AST(id) = node.data {
163-
match index.entry(id).get() {
164-
Ok(v) => v.push(node_idx),
165-
Err(e) => {
166-
e.insert(vec![node_idx]);
167-
}
168-
}
163+
index.entry(id).or_insert(vec![]).push(node_idx);
169164
}
170165
true
171166
});
@@ -185,12 +180,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
185180
visit::walk_fn_decl(&mut formals, decl);
186181
impl<'a, 'v> visit::Visitor<'v> for Formals<'a> {
187182
fn visit_pat(&mut self, p: &ast::Pat) {
188-
match self.index.entry(p.id).get() {
189-
Ok(v) => v.push(self.entry),
190-
Err(e) => {
191-
e.insert(vec![self.entry]);
192-
}
193-
}
183+
self.index.entry(p.id).or_insert(vec![]).push(self.entry);
194184
visit::walk_pat(self, p)
195185
}
196186
}

src/librustc/middle/traits/fulfill.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use middle::infer::{InferCtxt};
1212
use middle::ty::{self, RegionEscape, Ty};
1313
use std::collections::HashSet;
14-
use std::collections::hash_map::Entry::{Occupied, Vacant};
1514
use std::default::Default;
1615
use syntax::ast;
1716
use util::common::ErrorReported;
@@ -437,9 +436,7 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
437436
debug!("register_region_obligation({})",
438437
region_obligation.repr(tcx));
439438

440-
match region_obligations.entry(region_obligation.cause.body_id) {
441-
Vacant(entry) => { entry.insert(vec![region_obligation]); },
442-
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
443-
}
439+
region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![])
440+
.push(region_obligation);
444441

445442
}

src/librustc/middle/ty.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -5669,9 +5669,7 @@ pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
56695669
node_id_to_type(tcx, id.node)
56705670
} else {
56715671
let mut tcache = tcx.tcache.borrow_mut();
5672-
let pty = tcache.entry(id).get().unwrap_or_else(
5673-
|vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id)));
5674-
pty.ty
5672+
tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty
56755673
};
56765674
ty.subst(tcx, substs)
56775675
}
@@ -6819,9 +6817,7 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
68196817
debug!("region={}", region.repr(tcx));
68206818
match region {
68216819
ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
6822-
let region =
6823-
* map.entry(br).get().unwrap_or_else(
6824-
|vacant_entry| vacant_entry.insert(mapf(br)));
6820+
let region = *map.entry(br).or_insert_with(|| mapf(br));
68256821

68266822
if let ty::ReLateBound(debruijn1, br) = region {
68276823
// If the callback returns a late-bound region,

src/librustc/session/config.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ use syntax::parse::token::InternedString;
3535

3636
use getopts;
3737
use std::collections::HashMap;
38-
use std::collections::hash_map::Entry::{Occupied, Vacant};
3938
use std::env;
4039
use std::fmt;
4140
use std::path::PathBuf;
@@ -1037,10 +1036,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10371036
None => early_error("--extern value must be of the format `foo=bar`"),
10381037
};
10391038

1040-
match externs.entry(name.to_string()) {
1041-
Vacant(entry) => { entry.insert(vec![location.to_string()]); },
1042-
Occupied(mut entry) => { entry.get_mut().push(location.to_string()); },
1043-
}
1039+
externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string());
10441040
}
10451041

10461042
let crate_name = matches.opt_str("crate-name");

src/librustc_resolve/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#![feature(rustc_diagnostic_macros)]
2727
#![feature(rustc_private)]
2828
#![feature(staged_api)]
29-
#![feature(std_misc)]
3029

3130
#[macro_use] extern crate log;
3231
#[macro_use] extern crate syntax;

src/librustc_resolve/resolve_imports.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -836,11 +836,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
836836
let is_public = import_directive.is_public;
837837

838838
let mut import_resolutions = module_.import_resolutions.borrow_mut();
839-
let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else(
840-
|vacant_entry| {
841-
// Create a new import resolution from this child.
842-
vacant_entry.insert(ImportResolution::new(id, is_public))
843-
});
839+
let dest_import_resolution = import_resolutions.entry(name)
840+
.or_insert_with(|| ImportResolution::new(id, is_public));
844841

845842
debug!("(resolving glob import) writing resolution `{}` in `{}` \
846843
to `{}`",

src/librustc_typeck/check/mod.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
112112
use util::lev_distance::lev_distance;
113113

114114
use std::cell::{Cell, Ref, RefCell};
115-
use std::collections::hash_map::Entry::{Occupied, Vacant};
116115
use std::mem::replace;
117116
use std::rc::Rc;
118117
use std::iter::repeat;
@@ -1362,11 +1361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13621361
closure_def_id: ast::DefId,
13631362
r: DeferredCallResolutionHandler<'tcx>) {
13641363
let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1365-
let mut vec = match deferred_call_resolutions.entry(closure_def_id) {
1366-
Occupied(entry) => entry.into_mut(),
1367-
Vacant(entry) => entry.insert(Vec::new()),
1368-
};
1369-
vec.push(r);
1364+
deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
13701365
}
13711366

13721367
fn remove_deferred_call_resolutions(&self,

src/librustdoc/html/render.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -876,9 +876,7 @@ impl DocFolder for Cache {
876876
if let clean::ImplItem(ref i) = item.inner {
877877
match i.trait_ {
878878
Some(clean::ResolvedPath{ did, .. }) => {
879-
let v = self.implementors.entry(did).get().unwrap_or_else(
880-
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
881-
v.push(Implementor {
879+
self.implementors.entry(did).or_insert(vec![]).push(Implementor {
882880
def_id: item.def_id,
883881
generics: i.generics.clone(),
884882
trait_: i.trait_.as_ref().unwrap().clone(),
@@ -1080,9 +1078,7 @@ impl DocFolder for Cache {
10801078
};
10811079

10821080
if let Some(did) = did {
1083-
let v = self.impls.entry(did).get().unwrap_or_else(
1084-
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
1085-
v.push(Impl {
1081+
self.impls.entry(did).or_insert(vec![]).push(Impl {
10861082
impl_: i,
10871083
dox: dox,
10881084
stability: item.stability.clone(),
@@ -1334,9 +1330,8 @@ impl Context {
13341330
Some(ref s) => s.to_string(),
13351331
};
13361332
let short = short.to_string();
1337-
let v = map.entry(short).get().unwrap_or_else(
1338-
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
1339-
v.push((myname, Some(plain_summary_line(item.doc_value()))));
1333+
map.entry(short).or_insert(vec![])
1334+
.push((myname, Some(plain_summary_line(item.doc_value()))));
13401335
}
13411336

13421337
for (_, items) in &mut map {

src/librustdoc/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
352352
}
353353
};
354354
let name = name.to_string();
355-
let locs = externs.entry(name).get().unwrap_or_else(
356-
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
357-
locs.push(location.to_string());
355+
externs.entry(name).or_insert(vec![]).push(location.to_string());
358356
}
359357
Ok(externs)
360358
}

src/libstd/collections/hash/map.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use hash::{Hash, SipHasher};
2323
use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
2424
use marker::Sized;
2525
use mem::{self, replace};
26-
use ops::{Deref, FnMut, Index};
26+
use ops::{Deref, FnMut, FnOnce, Index};
2727
use option::Option::{self, Some, None};
2828
use rand::{self, Rng};
2929
use result::Result::{self, Ok, Err};
@@ -1488,12 +1488,37 @@ impl<'a, K, V> Entry<'a, K, V> {
14881488
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant.
14891489
#[unstable(feature = "std_misc",
14901490
reason = "will soon be replaced by or_insert")]
1491+
#[deprecated(since = "1.0",
1492+
reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
1493+
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
14911494
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
14921495
match self {
14931496
Occupied(entry) => Ok(entry.into_mut()),
14941497
Vacant(entry) => Err(entry),
14951498
}
14961499
}
1500+
1501+
#[unstable(feature = "collections",
1502+
reason = "matches entry v3 specification, waiting for dust to settle")]
1503+
/// Ensures a value is in the entry by inserting the default if empty, and returns
1504+
/// a mutable reference to the value in the entry.
1505+
pub fn or_insert(self, default: V) -> &'a mut V {
1506+
match self {
1507+
Occupied(entry) => entry.into_mut(),
1508+
Vacant(entry) => entry.insert(default),
1509+
}
1510+
}
1511+
1512+
#[unstable(feature = "collections",
1513+
reason = "matches entry v3 specification, waiting for dust to settle")]
1514+
/// Ensures a value is in the entry by inserting the result of the default function if empty,
1515+
/// and returns a mutable reference to the value in the entry.
1516+
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
1517+
match self {
1518+
Occupied(entry) => entry.into_mut(),
1519+
Vacant(entry) => entry.insert(default()),
1520+
}
1521+
}
14971522
}
14981523

14991524
impl<'a, K, V> OccupiedEntry<'a, K, V> {

src/libstd/collections/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,7 @@
307307
//! let message = "she sells sea shells by the sea shore";
308308
//!
309309
//! for c in message.chars() {
310-
//! match count.entry(c) {
311-
//! Entry::Vacant(entry) => { entry.insert(1); },
312-
//! Entry::Occupied(mut entry) => *entry.get_mut() += 1,
313-
//! }
310+
//! *count.entry(c).or_insert(0) += 1;
314311
//! }
315312
//!
316313
//! assert_eq!(count.get(&'s'), Some(&8));
@@ -343,10 +340,7 @@
343340
//! for id in orders.into_iter() {
344341
//! // If this is the first time we've seen this customer, initialize them
345342
//! // with no blood alcohol. Otherwise, just retrieve them.
346-
//! let person = match blood_alcohol.entry(id) {
347-
//! Entry::Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}),
348-
//! Entry::Occupied(entry) => entry.into_mut(),
349-
//! };
343+
//! let person = blood_alcohol.entry(id).or_insert(Person{id: id, blood_alcohol: 0.0});
350344
//!
351345
//! // Reduce their blood alcohol level. It takes time to order and drink a beer!
352346
//! person.blood_alcohol *= 0.9;

0 commit comments

Comments
 (0)