Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a fastpath to match_impl for the non-HRTB case #36931

Closed
wants to merge 3 commits into from
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