From d7cf1549e6e330cbc8cf16619d2a2dfd3bdb7455 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 3 Oct 2016 19:06:56 +0300 Subject: [PATCH 1/3] add a fastpath to match_impl for the non-HRTB case this leads to a 1.5% all-around typeck time improvement --- src/librustc/traits/select.rs | 52 ++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 666311110971d..41328ed30c3c2 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2668,6 +2668,49 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } + fn match_impl_fastpath(&mut self, + impl_def_id: DefId, + impl_trait_ref: ty::TraitRef<'tcx>, + obligation: &TraitObligation<'tcx>) + -> Option, ()>> + { + debug!("match_impl_fastpath({:?}={:?}, {:?}) entry", + impl_def_id, impl_trait_ref, obligation); + + if impl_trait_ref.has_projection_types() { + return None; + } + + let obligation_predicate = self.tcx().no_late_bound_regions(&obligation.predicate); + let obligation_trait_ref = match obligation_predicate { + Some(predicate) => predicate.trait_ref, + _ => return None + }; + + let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, + impl_def_id); + let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs); + + debug!("match_impl(impl_def_id={:?}, obligation={:?}, \ + impl_trait_ref={:?}, skol_obligation_trait_ref={:?}) fastpath", + impl_def_id, + obligation, + impl_trait_ref, + obligation_trait_ref); + + let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); + match self.infcx.eq_trait_refs(false, origin, impl_trait_ref, obligation_trait_ref) { + Ok(InferOk { obligations, .. }) => { + self.inferred_obligations.extend(obligations); + Some(Ok(impl_substs)) + } + Err(e) => { + debug!("match_impl_fastpath: failed eq_trait_refs due to `{}`", e); + Some(Err(())) + } + } + } + fn match_impl(&mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, @@ -2684,6 +2727,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } + if let Some(result) = self.match_impl_fastpath(impl_def_id, impl_trait_ref, obligation) { + return result.map(|substs| ( + Normalized { value: substs, obligations: vec![] }, + FnvHashMap() + )); + } + let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions( &obligation.predicate, snapshot); @@ -2702,7 +2752,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &impl_trait_ref); debug!("match_impl(impl_def_id={:?}, obligation={:?}, \ - impl_trait_ref={:?}, skol_obligation_trait_ref={:?})", + impl_trait_ref={:?}, skol_obligation_trait_ref={:?}) slowpath", impl_def_id, obligation, impl_trait_ref, From 50fb018f3f91d7995a966bf9930ace3c290f2a64 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 3 Oct 2016 20:25:46 +0300 Subject: [PATCH 2/3] split slices and arrays in fast_reject this does not have a measurable performance effect and mostly makes the logs clearer --- src/librustc/ty/fast_reject.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index befc9533c387b..4b007c69d3941 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use syntax::ast; @@ -24,8 +25,9 @@ pub enum SimplifiedType { FloatSimplifiedType(ast::FloatTy), AdtSimplifiedType(DefId), StrSimplifiedType, - ArraySimplifiedType, - PtrSimplifiedType, + ArraySimplifiedType(usize), + SliceSimplifiedType, + PtrSimplifiedType(hir::Mutability), NeverSimplifiedType, TupleSimplifiedType(usize), TraitSimplifiedType(DefId), @@ -57,8 +59,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)), ty::TyAdt(def, _) => Some(AdtSimplifiedType(def.did)), ty::TyStr => Some(StrSimplifiedType), - ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), - ty::TyRawPtr(_) => Some(PtrSimplifiedType), + ty::TyArray(_, n) => Some(ArraySimplifiedType(n)), + ty::TySlice(_) => Some(SliceSimplifiedType), + ty::TyRawPtr(mt) => Some(PtrSimplifiedType(mt.mutbl)), ty::TyTrait(ref trait_info) => { Some(TraitSimplifiedType(trait_info.principal.def_id())) } From 13ca54dd4a7f6e89a52f7189a95d0b55e2390692 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 14:45:43 +0300 Subject: [PATCH 3/3] add a fastpath to non-higher-ranked trait projection this improves typeck performance by another 1% --- src/librustc/traits/project.rs | 37 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index ddabc53a89a81..04c38696aa058 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -162,24 +162,29 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (skol_predicate, skol_map) = - infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); - - let skol_obligation = obligation.with(skol_predicate); - match project_and_unify_type(selcx, &skol_obligation) { - Ok(result) => { - let span = obligation.cause.span; - match infcx.leak_check(false, span, &skol_map, snapshot) { - Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)), - Err(e) => Err(MismatchedProjectionTypes { err: e }), + if let Some(skol_predicate) = infcx.tcx.no_late_bound_regions(&obligation.predicate) { + // Fastpath: no escaping regions. + project_and_unify_type(selcx, &obligation.with(skol_predicate)) + } else { + infcx.commit_if_ok(|snapshot| { + let (skol_predicate, skol_map) = + infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); + + let skol_obligation = obligation.with(skol_predicate); + match project_and_unify_type(selcx, &skol_obligation) { + Ok(result) => { + let span = obligation.cause.span; + match infcx.leak_check(false, span, &skol_map, snapshot) { + Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)), + Err(e) => Err(MismatchedProjectionTypes { err: e }), + } + } + Err(e) => { + Err(e) } } - Err(e) => { - Err(e) - } - } - }) + }) + } } /// Evaluates constraints of the form: