Skip to content

Commit 5e13d3a

Browse files
committed
auto merge of #17378 : Gankro/rust/hashmap-entry, r=aturon
Deprecates the `find_or_*` family of "internal mutation" methods on `HashMap` in favour of the "external mutation" Entry API as part of RFC 60. Part of #17320, but this still needs to be done on the rest of the maps. However they don't have any internal mutation methods defined, so they can be done without deprecating or breaking anything. Work on `BTree` is part of the complete rewrite in #17334. The implemented API deviates from the API described in the RFC in two key places: * `VacantEntry.set` yields a mutable reference to the inserted element to avoid code duplication where complex logic needs to be done *regardless* of whether the entry was vacant or not. * `OccupiedEntry.into_mut` was added so that it is possible to return a reference into the map beyond the lifetime of the Entry itself, providing functional parity to `VacantEntry.set`. This allows the full find_or_insert functionality to be implemented using this API. A PR will be submitted to the RFC to amend this. [breaking-change]
2 parents 4d69696 + fe8a413 commit 5e13d3a

File tree

16 files changed

+386
-50
lines changed

16 files changed

+386
-50
lines changed

src/librustc/driver/config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use syntax::parse;
3131
use syntax::parse::token::InternedString;
3232

3333
use std::collections::HashMap;
34+
use std::collections::hashmap::{Occupied, Vacant};
3435
use getopts::{optopt, optmulti, optflag, optflagopt};
3536
use getopts;
3637
use std::cell::{RefCell};
@@ -804,8 +805,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
804805
Some(s) => s,
805806
None => early_error("--extern value must be of the format `foo=bar`"),
806807
};
807-
let locs = externs.find_or_insert(name.to_string(), Vec::new());
808-
locs.push(location.to_string());
808+
809+
match externs.entry(name.to_string()) {
810+
Vacant(entry) => { entry.set(vec![location.to_string()]); },
811+
Occupied(mut entry) => { entry.get_mut().push(location.to_string()); },
812+
}
809813
}
810814

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

src/librustc/lint/builtin.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use lint::{Context, LintPass, LintArray};
3636

3737
use std::cmp;
3838
use std::collections::HashMap;
39+
use std::collections::hashmap::{Occupied, Vacant};
3940
use std::slice;
4041
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
4142
use syntax::abi;
@@ -1203,15 +1204,18 @@ impl UnusedMut {
12031204
fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
12041205
// collect all mutable pattern and group their NodeIDs by their Identifier to
12051206
// avoid false warnings in match arms with multiple patterns
1207+
12061208
let mut mutables = HashMap::new();
12071209
for p in pats.iter() {
12081210
pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| {
12091211
let ident = path1.node;
12101212
match mode {
12111213
ast::BindByValue(ast::MutMutable) => {
12121214
if !token::get_ident(ident).get().starts_with("_") {
1213-
mutables.insert_or_update_with(ident.name.uint(),
1214-
vec!(id), |_, old| { old.push(id); });
1215+
match mutables.entry(ident.name.uint()) {
1216+
Vacant(entry) => { entry.set(vec![id]); },
1217+
Occupied(mut entry) => { entry.get_mut().push(id); },
1218+
}
12151219
}
12161220
}
12171221
_ => {

src/librustc/metadata/creader.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use plugin::load::PluginMetadata;
2424

2525
use std::rc::Rc;
2626
use std::collections::HashMap;
27+
use std::collections::hashmap::{Occupied, Vacant};
2728
use syntax::ast;
2829
use syntax::abi;
2930
use syntax::attr;
@@ -82,7 +83,10 @@ fn dump_crates(cstore: &CStore) {
8283
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
8384
let mut map = HashMap::new();
8485
cstore.iter_crate_data(|cnum, data| {
85-
map.find_or_insert_with(data.name(), |_| Vec::new()).push(cnum);
86+
match map.entry(data.name()) {
87+
Vacant(entry) => { entry.set(vec![cnum]); },
88+
Occupied(mut entry) => { entry.get_mut().push(cnum); },
89+
}
8690
});
8791

8892
for (name, dupes) in map.into_iter() {

src/librustc/metadata/loader.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ use std::slice;
237237
use std::string;
238238

239239
use std::collections::{HashMap, HashSet};
240+
use std::collections::hashmap::{Occupied, Vacant};
240241
use flate;
241242
use time;
242243

@@ -428,15 +429,18 @@ impl<'a> Context<'a> {
428429
return FileDoesntMatch
429430
};
430431
info!("lib candidate: {}", path.display());
431-
let slot = candidates.find_or_insert_with(hash.to_string(), |_| {
432-
(HashSet::new(), HashSet::new())
433-
});
432+
433+
let slot = match candidates.entry(hash.to_string()) {
434+
Occupied(entry) => entry.into_mut(),
435+
Vacant(entry) => entry.set((HashSet::new(), HashSet::new())),
436+
};
434437
let (ref mut rlibs, ref mut dylibs) = *slot;
435438
if rlib {
436439
rlibs.insert(fs::realpath(path).unwrap());
437440
} else {
438441
dylibs.insert(fs::realpath(path).unwrap());
439442
}
443+
440444
FileMatches
441445
});
442446

src/librustc/middle/const_eval.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use syntax::visit;
2828
use syntax::{ast, ast_map, ast_util};
2929

3030
use std::rc::Rc;
31+
use std::collections::hashmap::Vacant;
3132

3233
//
3334
// This pass classifies expressions by their constant-ness.
@@ -321,7 +322,10 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<Pat> {
321322

322323
ExprCall(ref callee, ref args) => {
323324
let def = tcx.def_map.borrow().get_copy(&callee.id);
324-
tcx.def_map.borrow_mut().find_or_insert(expr.id, def);
325+
match tcx.def_map.borrow_mut().entry(expr.id) {
326+
Vacant(entry) => { entry.set(def); }
327+
_ => {}
328+
};
325329
let path = match def {
326330
def::DefStruct(def_id) => def_to_path(tcx, def_id),
327331
def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),

src/librustc/middle/resolve.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use syntax::visit;
5959
use syntax::visit::Visitor;
6060

6161
use std::collections::{HashMap, HashSet};
62+
use std::collections::hashmap::{Occupied, Vacant};
6263
use std::cell::{Cell, RefCell};
6364
use std::mem::replace;
6465
use std::rc::{Rc, Weak};
@@ -2815,10 +2816,13 @@ impl<'a> Resolver<'a> {
28152816
let is_public = import_directive.is_public;
28162817

28172818
let mut import_resolutions = module_.import_resolutions.borrow_mut();
2818-
let dest_import_resolution = import_resolutions.find_or_insert_with(name, |_| {
2819-
// Create a new import resolution from this child.
2820-
ImportResolution::new(id, is_public)
2821-
});
2819+
let dest_import_resolution = match import_resolutions.entry(name) {
2820+
Occupied(entry) => entry.into_mut(),
2821+
Vacant(entry) => {
2822+
// Create a new import resolution from this child.
2823+
entry.set(ImportResolution::new(id, is_public))
2824+
}
2825+
};
28222826

28232827
debug!("(resolving glob import) writing resolution `{}` in `{}` \
28242828
to `{}`",
@@ -6026,19 +6030,21 @@ impl<'a> Resolver<'a> {
60266030
assert!(match lp {LastImport{..} => false, _ => true},
60276031
"Import should only be used for `use` directives");
60286032
self.last_private.insert(node_id, lp);
6029-
self.def_map.borrow_mut().insert_or_update_with(node_id, def, |_, old_value| {
6033+
6034+
match self.def_map.borrow_mut().entry(node_id) {
60306035
// Resolve appears to "resolve" the same ID multiple
60316036
// times, so here is a sanity check it at least comes to
60326037
// the same conclusion! - nmatsakis
6033-
if def != *old_value {
6038+
Occupied(entry) => if def != *entry.get() {
60346039
self.session
60356040
.bug(format!("node_id {:?} resolved first to {:?} and \
60366041
then {:?}",
60376042
node_id,
6038-
*old_value,
6043+
*entry.get(),
60396044
def).as_slice());
6040-
}
6041-
});
6045+
},
6046+
Vacant(entry) => { entry.set(def); },
6047+
}
60426048
}
60436049

60446050
fn enforce_default_binding_mode(&mut self,

src/librustc/middle/ty.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use std::mem;
4848
use std::ops;
4949
use std::rc::Rc;
5050
use std::collections::{HashMap, HashSet};
51+
use std::collections::hashmap::{Occupied, Vacant};
5152
use arena::TypedArena;
5253
use syntax::abi;
5354
use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
@@ -4566,9 +4567,10 @@ pub fn lookup_field_type(tcx: &ctxt,
45664567
node_id_to_type(tcx, id.node)
45674568
} else {
45684569
let mut tcache = tcx.tcache.borrow_mut();
4569-
let pty = tcache.find_or_insert_with(id, |_| {
4570-
csearch::get_field_type(tcx, struct_id, id)
4571-
});
4570+
let pty = match tcache.entry(id) {
4571+
Occupied(entry) => entry.into_mut(),
4572+
Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
4573+
};
45724574
pty.ty
45734575
};
45744576
t.subst(tcx, substs)

src/librustc/middle/typeck/check/mod.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
121121

122122
use std::cell::{Cell, RefCell};
123123
use std::collections::HashMap;
124+
use std::collections::hashmap::{Occupied, Vacant};
124125
use std::mem::replace;
125126
use std::rc::Rc;
126127
use syntax::abi;
@@ -1991,11 +1992,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19911992
*/
19921993

19931994
let mut region_obligations = self.inh.region_obligations.borrow_mut();
1994-
let v = region_obligations.find_or_insert_with(self.body_id,
1995-
|_| Vec::new());
1996-
v.push(RegionObligation { sub_region: r,
1995+
let region_obligation = RegionObligation { sub_region: r,
19971996
sup_type: ty,
1998-
origin: origin });
1997+
origin: origin };
1998+
1999+
match region_obligations.entry(self.body_id) {
2000+
Vacant(entry) => { entry.set(vec![region_obligation]); },
2001+
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
2002+
}
19992003
}
20002004

20012005
pub fn add_obligations_for_parameters(&self,

src/librustc/middle/typeck/check/regionmanip.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use middle::ty_fold::TypeFolder;
1818
use syntax::ast;
1919

2020
use std::collections::HashMap;
21+
use std::collections::hashmap::{Occupied, Vacant};
2122
use util::ppaux::Repr;
2223

2324
// Helper functions related to manipulating region types.
@@ -35,7 +36,10 @@ pub fn replace_late_bound_regions_in_fn_sig(
3536
debug!("region r={}", r.to_string());
3637
match r {
3738
ty::ReLateBound(s, br) if s == fn_sig.binder_id => {
38-
*map.find_or_insert_with(br, |_| mapf(br))
39+
* match map.entry(br) {
40+
Vacant(entry) => entry.set(mapf(br)),
41+
Occupied(entry) => entry.into_mut(),
42+
}
3943
}
4044
_ => r
4145
}

src/librustdoc/html/render.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
//! both occur before the crate is rendered.
3535
3636
use std::collections::{HashMap, HashSet};
37+
use std::collections::hashmap::{Occupied, Vacant};
3738
use std::fmt;
3839
use std::io::fs::PathExtensions;
3940
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
@@ -802,9 +803,10 @@ impl DocFolder for Cache {
802803
clean::ImplItem(ref i) => {
803804
match i.trait_ {
804805
Some(clean::ResolvedPath{ did, .. }) => {
805-
let v = self.implementors.find_or_insert_with(did, |_| {
806-
Vec::new()
807-
});
806+
let v = match self.implementors.entry(did) {
807+
Vacant(entry) => entry.set(Vec::with_capacity(1)),
808+
Occupied(entry) => entry.into_mut(),
809+
};
808810
v.push(Implementor {
809811
def_id: item.def_id,
810812
generics: i.generics.clone(),
@@ -999,9 +1001,10 @@ impl DocFolder for Cache {
9991001

10001002
match did {
10011003
Some(did) => {
1002-
let v = self.impls.find_or_insert_with(did, |_| {
1003-
Vec::new()
1004-
});
1004+
let v = match self.impls.entry(did) {
1005+
Vacant(entry) => entry.set(Vec::with_capacity(1)),
1006+
Occupied(entry) => entry.into_mut(),
1007+
};
10051008
v.push(Impl {
10061009
impl_: i,
10071010
dox: dox,
@@ -2143,7 +2146,10 @@ fn build_sidebar(m: &clean::Module) -> HashMap<String, Vec<String>> {
21432146
None => continue,
21442147
Some(ref s) => s.to_string(),
21452148
};
2146-
let v = map.find_or_insert_with(short.to_string(), |_| Vec::new());
2149+
let v = match map.entry(short.to_string()) {
2150+
Vacant(entry) => entry.set(Vec::with_capacity(1)),
2151+
Occupied(entry) => entry.into_mut(),
2152+
};
21472153
v.push(myname);
21482154
}
21492155

src/librustdoc/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern crate time;
3131
use std::io;
3232
use std::io::{File, MemWriter};
3333
use std::collections::HashMap;
34+
use std::collections::hashmap::{Occupied, Vacant};
3435
use serialize::{json, Decodable, Encodable};
3536
use externalfiles::ExternalHtml;
3637

@@ -340,7 +341,10 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
340341
return Err("--extern value must be of the format `foo=bar`".to_string());
341342
}
342343
};
343-
let locs = externs.find_or_insert(name.to_string(), Vec::new());
344+
let locs = match externs.entry(name.to_string()) {
345+
Vacant(entry) => entry.set(Vec::with_capacity(1)),
346+
Occupied(entry) => entry.into_mut(),
347+
};
344348
locs.push(location.to_string());
345349
}
346350
Ok(externs)

0 commit comments

Comments
 (0)