Skip to content

Commit 3d46d09

Browse files
author
Ariel Ben-Yehuda
committed
use stalled_on in all obligation types
this improves typeck performance by 5% (LLVM times are still huge). Basically fixes #25916 (still O(n^2), but the example takes <1s to compile).
1 parent 3a254fe commit 3d46d09

File tree

3 files changed

+68
-14
lines changed

3 files changed

+68
-14
lines changed

src/librustc/middle/traits/fulfill.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use dep_graph::DepGraph;
1212
use middle::infer::InferCtxt;
13-
use middle::ty::{self, Ty, TypeFoldable};
13+
use middle::ty::{self, Ty, TypeFoldable, ToPolyTraitRef};
1414
use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error};
1515
use std::iter;
1616
use syntax::ast;
@@ -417,6 +417,21 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
417417
}
418418
}
419419

420+
421+
/// Return the set of type variables contained in a trait ref
422+
fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>,
423+
t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>>
424+
{
425+
t.skip_binder() // ok b/c this check doesn't care about regions
426+
.input_types()
427+
.iter()
428+
.map(|t| selcx.infcx().resolve_type_vars_if_possible(t))
429+
.filter(|t| t.has_infer_types())
430+
.flat_map(|t| t.walk())
431+
.filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
432+
.collect()
433+
}
434+
420435
/// Processes a predicate obligation and returns either:
421436
/// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true
422437
/// - `Ok(None)` if we don't have enough info to be sure
@@ -433,7 +448,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
433448
// doing more work yet
434449
if !pending_obligation.stalled_on.is_empty() {
435450
if pending_obligation.stalled_on.iter().all(|&ty| {
436-
let resolved_ty = selcx.infcx().resolve_type_vars_if_possible(&ty);
451+
let resolved_ty = selcx.infcx().shallow_resolve(&ty);
437452
resolved_ty == ty // nothing changed here
438453
}) {
439454
debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
@@ -493,14 +508,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
493508
// of its type, and those types are resolved at
494509
// the same time.
495510
pending_obligation.stalled_on =
496-
data.skip_binder() // ok b/c this check doesn't care about regions
497-
.input_types()
498-
.iter()
499-
.map(|t| selcx.infcx().resolve_type_vars_if_possible(t))
500-
.filter(|t| t.has_infer_types())
501-
.flat_map(|t| t.walk())
502-
.filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
503-
.collect();
511+
trait_ref_type_vars(selcx, data.to_poly_trait_ref());
504512

505513
debug!("process_predicate: pending obligation {:?} now stalled on {:?}",
506514
selcx.infcx().resolve_type_vars_if_possible(obligation),
@@ -568,6 +576,11 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
568576
ty::Predicate::Projection(ref data) => {
569577
let project_obligation = obligation.with(data.clone());
570578
match project::poly_project_and_unify_type(selcx, &project_obligation) {
579+
Ok(None) => {
580+
pending_obligation.stalled_on =
581+
trait_ref_type_vars(selcx, data.to_poly_trait_ref());
582+
Ok(None)
583+
}
571584
Ok(v) => Ok(v),
572585
Err(e) => Err(CodeProjectionError(e))
573586
}
@@ -582,8 +595,14 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
582595
}
583596

584597
ty::Predicate::WellFormed(ty) => {
585-
Ok(ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
586-
ty, obligation.cause.span))
598+
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
599+
ty, obligation.cause.span) {
600+
None => {
601+
pending_obligation.stalled_on = vec![ty];
602+
Ok(None)
603+
}
604+
s => Ok(s)
605+
}
587606
}
588607
}
589608
}

src/librustc/middle/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> {
917917

918918
impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
919919
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
920-
self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone())
920+
self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
921921
}
922922
}
923923

@@ -928,7 +928,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> {
928928
// This is because here `self` has a `Binder` and so does our
929929
// return value, so we are preserving the number of binding
930930
// levels.
931-
ty::Binder(self.0.projection_ty.trait_ref.clone())
931+
ty::Binder(self.0.projection_ty.trait_ref)
932932
}
933933
}
934934

src/test/run-pass/issue-25916.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
macro_rules! f {
13+
() => { 0 + 0 }
14+
}
15+
// 16 per line
16+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
17+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
18+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
19+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
20+
21+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
22+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
23+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
24+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
25+
26+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
27+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
28+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
29+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
30+
31+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
32+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
33+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
34+
f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
35+
}

0 commit comments

Comments
 (0)