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:
parent
a49d9bab1e
commit
9b75a2bcd1
3 changed files with 30 additions and 8 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue