diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 8ff81635416a4..11d9512034440 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -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 diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 578b39af88cb4..1b47ce75bc50d 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -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) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 967eb3ff74f49..9f5b24c6b765b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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(&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 Copy for Option`, we replace the type variable + // in `Option` 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);