Skip to content

Commit

Permalink
make trait matching smarter with projections
Browse files Browse the repository at this point in the history
also, use the right caching logic for type_moves_by_default (this was
broken by @jroesch).

before:
593.10user 5.21system 7:51.41elapsed 126%CPU (0avgtext+0avgdata 1150016maxresident)k
llvm: 427.045

after:
577.76user 4.27system 7:36.13elapsed 127%CPU (0avgtext+0avgdata 1141608maxresident)k
llvm: 431.001
  • Loading branch information
Ariel Ben-Yehuda committed Aug 17, 2015
1 parent a49d9ba commit 9b75a2b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 8 deletions.
10 changes: 6 additions & 4 deletions src/librustc/middle/fast_reject.rs
Expand Up @@ -85,11 +85,13 @@ pub fn simplify_type(tcx: &ty::ctxt,
ty::TyBareFn(_, ref f) => {
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
}
ty::TyProjection(_) => {
None
}
ty::TyParam(_) => {
ty::TyProjection(_) | ty::TyParam(_) => {
if can_simplify_params {
// In normalized types, projections don't unify with
// anything. when lazy normalization happens, this
// will change. It would still be nice to have a way
// to deal with known-not-to-unify-with-anything
// projections (e.g. the likes of <__S as Encoder>::Error).
Some(ParameterSimplifiedType)
} else {
None
Expand Down
12 changes: 9 additions & 3 deletions src/librustc/middle/infer/mod.rs
Expand Up @@ -1456,9 +1456,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
let ty = self.resolve_type_vars_if_possible(&ty);
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
// FIXME(@jroesch): should be able to use:
// ty.moves_by_default(&self.parameter_environment, span)
if ty.needs_infer() {
// this can get called from typeck (by euv), and moves_by_default
// rightly refuses to work with inference variables, but
// moves_by_default has a cache, which we want to use in other
// cases.
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
} else {
ty.moves_by_default(&self.parameter_environment, span)
}
}

pub fn node_method_ty(&self, method_call: ty::MethodCall)
Expand Down
16 changes: 15 additions & 1 deletion src/librustc/middle/ty.rs
Expand Up @@ -3192,6 +3192,8 @@ impl<'tcx> TraitDef<'tcx> {
}
}

/// Iterate over every impl that could possibly match the
/// self-type `self_ty`.
pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
tcx: &ctxt<'tcx>,
self_ty: Ty<'tcx>,
Expand All @@ -3203,7 +3205,19 @@ impl<'tcx> TraitDef<'tcx> {
f(impl_def_id);
}

if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, false) {
// simplify_type(.., false) basically replaces type parameters and
// projections with infer-variables. This is, of course, done on
// the impl trait-ref when it is instantiated, but not on the
// predicate trait-ref which is passed here.
//
// for example, if we match `S: Copy` against an impl like
// `impl<T:Copy> Copy for Option<T>`, we replace the type variable
// in `Option<T>` with an infer variable, to `Option<_>` (this
// doesn't actually change fast_reject output), but we don't
// replace `S` with anything - this impl of course can't be
// selected, and as there are hundreds of similar impls,
// considering them would significantly harm performance.
if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, true) {
if let Some(impls) = self.nonblanket_impls.borrow().get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
Expand Down

0 comments on commit 9b75a2b

Please sign in to comment.