Call skolemize_late_bound_regions only after fast rejection
skolemize_late_bound_regions essentially copies the entire type (most of the times it shouldn't, but it does), and match_impl runs millions of times. Times compiling rustc, tested with $ make -j4 rustc-stage1 $ ( time RUSTFLAGS=-Z time-passes make -j4 rustc-stage2 ) # need LLVM time for calibration Before: real 21m44.960s user 29m38.812s sys 0m14.944s After: real 19m31.445s user 26m47.260s sys 0m14.952s Making this is a 10% performance improvement. LLVM passes took 867 seconds before, 862 seconds after.
This commit is contained in:
parent
be41e98067
commit
94a1b266f9
1 changed files with 20 additions and 27 deletions
|
@ -532,11 +532,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
obligation.repr(self.tcx()));
|
obligation.repr(self.tcx()));
|
||||||
|
|
||||||
self.infcx.probe(|snapshot| {
|
self.infcx.probe(|snapshot| {
|
||||||
let (skol_obligation_trait_ref, skol_map) =
|
match self.match_impl(impl_def_id, obligation, snapshot) {
|
||||||
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
|
Ok((substs, skol_map)) => {
|
||||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
|
||||||
&skol_map, skol_obligation_trait_ref.trait_ref.clone()) {
|
|
||||||
Ok(substs) => {
|
|
||||||
let vtable_impl = self.vtable_impl(impl_def_id,
|
let vtable_impl = self.vtable_impl(impl_def_id,
|
||||||
substs,
|
substs,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
|
@ -1160,10 +1157,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let all_impls = self.all_impls(def_id);
|
let all_impls = self.all_impls(def_id);
|
||||||
for &impl_def_id in &all_impls {
|
for &impl_def_id in &all_impls {
|
||||||
self.infcx.probe(|snapshot| {
|
self.infcx.probe(|snapshot| {
|
||||||
let (skol_obligation_trait_pred, skol_map) =
|
match self.match_impl(impl_def_id, obligation, snapshot) {
|
||||||
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
|
|
||||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
|
||||||
&skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||||
}
|
}
|
||||||
|
@ -2115,11 +2109,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// First, create the substitutions by matching the impl again,
|
// First, create the substitutions by matching the impl again,
|
||||||
// this time not in a probe.
|
// this time not in a probe.
|
||||||
self.infcx.commit_if_ok(|snapshot| {
|
self.infcx.commit_if_ok(|snapshot| {
|
||||||
let (skol_obligation_trait_ref, skol_map) =
|
let (substs, skol_map) =
|
||||||
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
|
|
||||||
let substs =
|
|
||||||
self.rematch_impl(impl_def_id, obligation,
|
self.rematch_impl(impl_def_id, obligation,
|
||||||
snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
|
snapshot);
|
||||||
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
|
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
|
||||||
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
|
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
|
||||||
obligation.recursion_depth + 1, skol_map, snapshot))
|
obligation.recursion_depth + 1, skol_map, snapshot))
|
||||||
|
@ -2306,14 +2298,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
fn rematch_impl(&mut self,
|
fn rematch_impl(&mut self,
|
||||||
impl_def_id: ast::DefId,
|
impl_def_id: ast::DefId,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
snapshot: &infer::CombinedSnapshot,
|
snapshot: &infer::CombinedSnapshot)
|
||||||
skol_map: &infer::SkolemizationMap,
|
-> (Normalized<'tcx, Substs<'tcx>>, infer::SkolemizationMap)
|
||||||
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
|
|
||||||
-> Normalized<'tcx, Substs<'tcx>>
|
|
||||||
{
|
{
|
||||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
match self.match_impl(impl_def_id, obligation, snapshot) {
|
||||||
skol_map, skol_obligation_trait_ref) {
|
Ok((substs, skol_map)) => (substs, skol_map),
|
||||||
Ok(substs) => substs,
|
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
self.tcx().sess.bug(
|
self.tcx().sess.bug(
|
||||||
&format!("Impl {} was matchable against {} but now is not",
|
&format!("Impl {} was matchable against {} but now is not",
|
||||||
|
@ -2326,10 +2315,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
fn match_impl(&mut self,
|
fn match_impl(&mut self,
|
||||||
impl_def_id: ast::DefId,
|
impl_def_id: ast::DefId,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
snapshot: &infer::CombinedSnapshot,
|
snapshot: &infer::CombinedSnapshot)
|
||||||
skol_map: &infer::SkolemizationMap,
|
-> Result<(Normalized<'tcx, Substs<'tcx>>,
|
||||||
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
|
infer::SkolemizationMap), ()>
|
||||||
-> Result<Normalized<'tcx, Substs<'tcx>>, ()>
|
|
||||||
{
|
{
|
||||||
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
|
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
|
||||||
|
|
||||||
|
@ -2340,6 +2328,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
|
||||||
|
&obligation.predicate,
|
||||||
|
snapshot);
|
||||||
|
let skol_obligation_trait_ref = skol_obligation.trait_ref;
|
||||||
|
|
||||||
let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
|
let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
impl_def_id);
|
impl_def_id);
|
||||||
|
@ -2370,17 +2363,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
|
if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
|
||||||
debug!("match_impl: failed leak check due to `{}`",
|
debug!("match_impl: failed leak check due to `{}`",
|
||||||
ty::type_err_to_str(self.tcx(), &e));
|
ty::type_err_to_str(self.tcx(), &e));
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
|
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
|
||||||
Ok(Normalized {
|
Ok((Normalized {
|
||||||
value: impl_substs,
|
value: impl_substs,
|
||||||
obligations: impl_trait_ref.obligations
|
obligations: impl_trait_ref.obligations
|
||||||
})
|
}, skol_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fast_reject_trait_refs(&mut self,
|
fn fast_reject_trait_refs(&mut self,
|
||||||
|
|
Loading…
Reference in a new issue