diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index d34649782ba6a..ae539f07336d5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -101,7 +101,7 @@ pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx> } -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] enum ProjectionTyCandidate<'tcx> { // from a where-clause in the env or object type ParamEnv(ty::PolyProjectionPredicate<'tcx>), @@ -838,21 +838,12 @@ fn project_type<'cx, 'gcx, 'tcx>( // Drop duplicates. // // Note: `candidates.vec` seems to be on the critical path of the - // compiler. Replacing it with an hash set was also tried, which would - // render the following dedup unnecessary. It led to cleaner code but - // prolonged compiling time of `librustc` from 5m30s to 6m in one test, or - // ~9% performance lost. - if candidates.vec.len() > 1 { - let mut i = 0; - while i < candidates.vec.len() { - let has_dup = (0..i).any(|j| candidates.vec[i] == candidates.vec[j]); - if has_dup { - candidates.vec.swap_remove(i); - } else { - i += 1; - } - } - } + // compiler. Replacing it with an HashSet was also tried, which would + // render the following dedup unnecessary. The original comment indicated + // that it was 9% slower, but that data is now obsolete and a new + // benchmark should be performed. + candidates.vec.sort_unstable(); + candidates.vec.dedup(); // Prefer where-clauses. As in select, if there are multiple // candidates, we prefer where-clause candidates over impls. This diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b8c11e381b8f6..e0fb8c0c0a50d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -41,6 +41,7 @@ use serialize::{self, Encodable, Encoder}; use std::cell::RefCell; use std::collections::BTreeMap; use std::cmp; +use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; @@ -499,6 +500,20 @@ impl<'tcx> Hash for TyS<'tcx> { } } +impl<'tcx> Ord for TyS<'tcx> { + #[inline] + fn cmp(&self, other: &TyS<'tcx>) -> Ordering { + // (self as *const _).cmp(other as *const _) + (self as *const TyS<'tcx>).cmp(&(other as *const TyS<'tcx>)) + } +} +impl<'tcx> PartialOrd for TyS<'tcx> { + #[inline] + fn partial_cmp(&self, other: &TyS<'tcx>) -> Option { + Some(self.cmp(other)) + } +} + impl<'tcx> TyS<'tcx> { pub fn is_primitive_ty(&self) -> bool { match self.sty { @@ -568,6 +583,19 @@ impl PartialEq for Slice { } impl Eq for Slice {} +impl Ord for Slice { + #[inline] + fn cmp(&self, other: &Slice) -> Ordering { + (&self.0 as *const [T]).cmp(&(&other.0 as *const [T])) + } +} +impl PartialOrd for Slice { + #[inline] + fn partial_cmp(&self, other: &Slice) -> Option { + Some(self.cmp(other)) + } +} + impl Hash for Slice { fn hash(&self, s: &mut H) { (self.as_ptr(), self.len()).hash(s) @@ -1103,7 +1131,7 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder>; /// equality between arbitrary types. Processing an instance of /// Form #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, pub ty: Ty<'tcx>, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index b6ba7896497b4..db7e4fe45ef76 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -638,7 +638,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// erase, or otherwise "discharge" these bound regions, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Binder(pub T); impl Binder { @@ -738,7 +738,7 @@ impl Binder { /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `>::N`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ProjectionTy<'tcx> { /// The parameters of the associated item. pub substs: &'tcx Substs<'tcx>, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 80b113dfdf5a5..7c167f69ebd8c 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -29,7 +29,7 @@ use std::mem; /// To reduce memory usage, a `Kind` is a interned pointer, /// with the lowest 2 bits being reserved for a tag to /// indicate the type (`Ty` or `Region`) it points to. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Kind<'tcx> { ptr: NonZero, marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)>