diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 68f2313843c31..56c53fca62cb1 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1400,6 +1400,7 @@ impl [T] { let sz_usize = mem::size_of::<(K, usize)>(); let len = self.len(); + if len < 2 { return } if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7da664e6d0255..0b4c3be8b7814 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -61,6 +61,7 @@ #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] +#![feature(slice_sort_by_cached_key)] #![feature(specialization)] #![feature(unboxed_closures)] #![feature(trace_macros)] diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index add9b621596b6..41334a37dbef6 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -401,7 +401,7 @@ pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference) .collect::>(); let mut ordering = tcx.postorder_cnums(LOCAL_CRATE); Lrc::make_mut(&mut ordering).reverse(); - libs.sort_by_key(|&(a, _)| { + libs.sort_by_cached_key(|&(a, _)| { ordering.iter().position(|x| *x == a) }); libs diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6f88b0aecb6b6..ab710f2e9004d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -23,6 +23,7 @@ #![cfg_attr(unix, feature(libc))] #![feature(quote)] #![feature(rustc_diagnostic_macros)] +#![feature(slice_sort_by_cached_key)] #![feature(set_stdio)] #![feature(rustc_stack_internals)] @@ -83,7 +84,6 @@ use rustc_trans_utils::trans_crate::TransCrate; use serialize::json::ToJson; use std::any::Any; -use std::cmp::Ordering::Equal; use std::cmp::max; use std::default::Default; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; @@ -1177,13 +1177,8 @@ Available lint options: fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> { let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect(); - lints.sort_by(|x: &&Lint, y: &&Lint| { - match x.default_level(sess).cmp(&y.default_level(sess)) { - // The sort doesn't case-fold but it's doubtful we care. - Equal => x.name.cmp(y.name), - r => r, - } - }); + // The sort doesn't case-fold but it's doubtful we care. + lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name)); lints } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1b208a512e2a4..e40a3057a95cf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1414,7 +1414,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); // Bring everything into deterministic order for hashing - all_impls.sort_unstable_by_key(|&(trait_def_id, _)| { + all_impls.sort_by_cached_key(|&(trait_def_id, _)| { tcx.def_path_hash(trait_def_id) }); @@ -1422,7 +1422,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { .into_iter() .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing - impls.sort_unstable_by_key(|&def_index| { + impls.sort_by_cached_key(|&def_index| { tcx.hir.definitions().def_path_hash(def_index) }); diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index e89b5a7fc1b4e..76a14cf44f2c2 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -21,6 +21,7 @@ #![feature(macro_lifetime_matcher)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] +#![feature(slice_sort_by_cached_key)] #![feature(specialization)] #![feature(rustc_private)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 8762e7550cded..2fe64f492dd8c 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -17,6 +17,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![deny(warnings)] #![feature(slice_patterns)] +#![feature(slice_sort_by_cached_key)] #![feature(from_ref)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index da4cb4ec78904..f29f86af4aba7 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -112,11 +112,11 @@ use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; +use std::cmp; use syntax::ast::NodeId; use syntax::symbol::{Symbol, InternedString}; use rustc::mir::mono::MonoItem; use monomorphize::item::{MonoItemExt, InstantiationMode}; -use core::usize; pub use rustc::mir::mono::CodegenUnit; @@ -189,11 +189,9 @@ pub trait CodegenUnitExt<'tcx> { }, item.symbol_name(tcx)) } - let items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect(); - let mut items : Vec<_> = items.iter() - .map(|il| (il, item_sort_key(tcx, il.0))).collect(); - items.sort_by(|&(_, ref key1), &(_, ref key2)| key1.cmp(key2)); - items.into_iter().map(|(&item_linkage, _)| item_linkage).collect() + let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect(); + items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i)); + items } } @@ -509,7 +507,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning< // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > target_cgu_count { // Sort small cgus to the back - codegen_units.sort_by_key(|cgu| usize::MAX - cgu.size_estimate()); + codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate())); let mut smallest = codegen_units.pop().unwrap(); let second_smallest = codegen_units.last_mut().unwrap(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2bf17cd1317d4..9ca7d1a372b11 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -14,6 +14,7 @@ #![deny(warnings)] #![feature(rustc_diagnostic_macros)] +#![feature(slice_sort_by_cached_key)] #[macro_use] extern crate log; @@ -1150,13 +1151,9 @@ impl<'a> ModuleData<'a> { fn for_each_child_stable)>(&self, mut f: F) { let resolutions = self.resolutions.borrow(); - let mut resolutions = resolutions.iter().map(|(&(ident, ns), &resolution)| { - // Pre-compute keys for sorting - (ident.name.as_str(), ns, ident, resolution) - }) - .collect::>(); - resolutions.sort_unstable_by_key(|&(str, ns, ..)| (str, ns)); - for &(_, ns, ident, resolution) in resolutions.iter() { + let mut resolutions = resolutions.iter().collect::>(); + resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.name.as_str(), ns)); + for &(&(ident, ns), &resolution) in resolutions.iter() { resolution.borrow().binding.map(|binding| f(ident, ns, binding)); } } @@ -3341,7 +3338,9 @@ impl<'a> Resolver<'a> { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = self.lookup_import_candidates(name, TypeNS, is_mod); - candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string())); + candidates.sort_by_cached_key(|c| { + (c.path.segments.len(), c.path.to_string()) + }); if let Some(candidate) = candidates.get(0) { format!("Did you mean `{}`?", candidate.path) } else { @@ -3579,7 +3578,7 @@ impl<'a> Resolver<'a> { let name = path[path.len() - 1].name; // Make sure error reporting is deterministic. - names.sort_by_key(|name| name.as_str()); + names.sort_by_cached_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { Some(found) if found != name => Some(found), _ => None, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0329264a3125f..09aba830d050d 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -82,7 +82,8 @@ use std::ffi::CString; use std::str; use std::sync::Arc; use std::time::{Instant, Duration}; -use std::{i32, usize}; +use std::i32; +use std::cmp; use std::sync::mpsc; use syntax_pos::Span; use syntax_pos::symbol::InternedString; @@ -830,7 +831,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // a bit more efficiently. let codegen_units = { let mut codegen_units = codegen_units; - codegen_units.sort_by_key(|cgu| usize::MAX - cgu.size_estimate()); + codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate())); codegen_units }; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 344f959c1414c..73c676021ec36 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -27,6 +27,7 @@ #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] +#![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] #![feature(inclusive_range_fields)] #![feature(underscore_lifetimes)] diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index fa2022e8cc994..de5709566225c 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -799,7 +799,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { .collect(); // sort them by the name so we have a stable result - names.sort_by_key(|n| n.as_str()); + names.sort_by_cached_key(|n| n.as_str()); names } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 6f71db998bd41..2ead5e9d91306 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -82,6 +82,7 @@ This API is completely unstable and subject to change. #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] +#![feature(slice_sort_by_cached_key)] #![feature(dyn_trait)] #[macro_use] extern crate log; diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a87e1df5efc2c..322527839e02e 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1435,9 +1435,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // involved (impls rarely have more than a few bounds) means that it // shouldn't matter in practice. fn unstable_debug_sort(&self, vec: &mut Vec) { - vec.sort_unstable_by(|first, second| { - format!("{:?}", first).cmp(&format!("{:?}", second)) - }); + vec.sort_by_cached_key(|x| format!("{:?}", x)) } fn is_fn_ty(&self, tcx: &TyCtxt, ty: &Type) -> bool { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 42e87f88fd40d..e34cf6222cf83 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -20,6 +20,7 @@ #![feature(box_syntax)] #![feature(fs_read_write)] #![feature(set_stdio)] +#![feature(slice_sort_by_cached_key)] #![feature(test)] #![feature(unicode)] #![feature(vec_remove_item)] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c456dc45d2182..7774095e20421 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -22,6 +22,7 @@ #![feature(unicode)] #![feature(rustc_diagnostic_macros)] +#![feature(slice_sort_by_cached_key)] #![feature(non_exhaustive)] #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e6da5bcaa3ae6..6ed7088d0521d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -689,7 +689,7 @@ impl<'a> Parser<'a> { .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) .chain(self.expected_tokens.iter().cloned()) .collect::>(); - expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); + expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); let expect = tokens_to_string(&expected[..]); let actual = self.this_token_to_string();