Skip to content

Commit 9b75a2b

Browse files
author
Ariel Ben-Yehuda
committed
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
1 parent a49d9ba commit 9b75a2b

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

src/librustc/middle/fast_reject.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ pub fn simplify_type(tcx: &ty::ctxt,
8585
ty::TyBareFn(_, ref f) => {
8686
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
8787
}
88-
ty::TyProjection(_) => {
89-
None
90-
}
91-
ty::TyParam(_) => {
88+
ty::TyProjection(_) | ty::TyParam(_) => {
9289
if can_simplify_params {
90+
// In normalized types, projections don't unify with
91+
// anything. when lazy normalization happens, this
92+
// will change. It would still be nice to have a way
93+
// to deal with known-not-to-unify-with-anything
94+
// projections (e.g. the likes of <__S as Encoder>::Error).
9395
Some(ParameterSimplifiedType)
9496
} else {
9597
None

src/librustc/middle/infer/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1456,9 +1456,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14561456

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

14641470
pub fn node_method_ty(&self, method_call: ty::MethodCall)

src/librustc/middle/ty.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -3192,6 +3192,8 @@ impl<'tcx> TraitDef<'tcx> {
31923192
}
31933193
}
31943194

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

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

0 commit comments

Comments
 (0)