1
Fork 0

make trait matching smarter with projections

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
This commit is contained in:
Ariel Ben-Yehuda 2015-08-17 20:26:22 +03:00
parent a49d9bab1e
commit 9b75a2bcd1
3 changed files with 30 additions and 8 deletions

View file

@ -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

View file

@ -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)

View file

@ -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>,
@ -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);