Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
52 changes: 51 additions & 1 deletion src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2668,6 +2668,49 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
}

fn match_impl_fastpath(&mut self,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I'm not thrilled about the duplication, though the perf win is nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's about the smallest amount of code you can duplicate ;-).

impl_def_id: DefId,
impl_trait_ref: ty::TraitRef<'tcx>,
obligation: &TraitObligation<'tcx>)
-> Option<Result<&'tcx Substs<'tcx>, ()>>
{
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>,
Expand All @@ -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);
Expand All @@ -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,
Expand Down
11 changes: 7 additions & 4 deletions src/librustc/ty/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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),
Expand Down Expand Up @@ -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()))
}
Expand Down