about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-08-15 13:41:54 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-08-29 14:34:43 +0300
commit9be155d88e44c1e4cdacfc640448fc9305151ab2 (patch)
tree3033245d1b0cc6a67dbaf17afb57986dad6be931 /src
parentfceab9fb348becb62f404d0d9381a49446beac7a (diff)
downloadrust-9be155d88e44c1e4cdacfc640448fc9305151ab2.tar.gz
rust-9be155d88e44c1e4cdacfc640448fc9305151ab2.zip
remove the hacky selection impl in `method::probe`
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/method/confirm.rs18
-rw-r--r--src/librustc_typeck/check/method/mod.rs5
-rw-r--r--src/librustc_typeck/check/method/probe.rs505
-rw-r--r--src/librustc_typeck/check/method/suggest.rs16
-rw-r--r--src/test/run-pass/unboxed-closures-infer-explicit-call-early.rs (renamed from src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs)8
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr4
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr2
7 files changed, 120 insertions, 438 deletions
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index db383b6305b..08ec3bf74a7 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -232,24 +232,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                 })
             }
 
-            probe::ExtensionImplPick(impl_def_id) => {
-                // The method being invoked is the method as defined on the trait,
-                // so return the substitutions from the trait. Consider:
-                //
-                //     impl<A,B,C> Trait<A,B> for Foo<C> { ... }
-                //
-                // If we instantiate A, B, and C with $A, $B, and $C
-                // respectively, then we want to return the type
-                // parameters from the trait ([$A,$B]), not those from
-                // the impl ([$A,$B,$C]) not the receiver type ([$C]).
-                let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
-                let impl_trait_ref =
-                    self.instantiate_type_scheme(self.span,
-                                                 impl_polytype.substs,
-                                                 &self.tcx.impl_trait_ref(impl_def_id).unwrap());
-                impl_trait_ref.substs
-            }
-
             probe::TraitPick => {
                 let trait_def_id = pick.item.container.id();
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 819f48a1b57..caf1ab7cf83 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -52,10 +52,6 @@ pub enum MethodError<'tcx> {
     // Multiple methods might apply.
     Ambiguity(Vec<CandidateSource>),
 
-    // Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind.
-    ClosureAmbiguity(// DefId of fn trait
-                     DefId),
-
     // Found an applicable method, but it is not visible. The second argument contains a list of
     // not-in-scope traits which may work.
     PrivateMatch(Def, Vec<DefId>),
@@ -113,7 +109,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Ok(..) => true,
             Err(NoMatch(..)) => false,
             Err(Ambiguity(..)) => true,
-            Err(ClosureAmbiguity(..)) => true,
             Err(PrivateMatch(..)) => allow_private,
             Err(IllegalSizedBound(..)) => true,
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 30683eeeba8..f63db891bfb 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -18,7 +18,7 @@ use hir::def_id::DefId;
 use hir::def::Def;
 use rustc::ty::subst::{Subst, Substs};
 use rustc::traits::{self, ObligationCause};
-use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable};
+use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::util::nodemap::FxHashSet;
 use rustc::infer::{self, InferOk};
@@ -51,7 +51,6 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     mode: Mode,
     looking_for: LookingFor<'tcx>,
     steps: Rc<Vec<CandidateStep<'tcx>>>,
-    opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>,
     inherent_candidates: Vec<Candidate<'tcx>>,
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: FxHashSet<DefId>,
@@ -95,13 +94,8 @@ enum CandidateKind<'tcx> {
     InherentImplCandidate(&'tcx Substs<'tcx>,
                           // Normalize obligations
                           Vec<traits::PredicateObligation<'tcx>>),
-    ExtensionImplCandidate(// Impl
-                           DefId,
-                           &'tcx Substs<'tcx>,
-                           // Normalize obligations
-                           Vec<traits::PredicateObligation<'tcx>>),
     ObjectCandidate,
-    TraitCandidate,
+    TraitCandidate(ty::TraitRef<'tcx>),
     WhereClauseCandidate(// Trait
                          ty::PolyTraitRef<'tcx>),
 }
@@ -133,8 +127,6 @@ pub struct Pick<'tcx> {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum PickKind<'tcx> {
     InherentImplPick,
-    ExtensionImplPick(// Impl
-                      DefId),
     ObjectPick,
     TraitPick,
     WhereClausePick(// Trait
@@ -259,24 +251,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                  }]
         };
 
-        // Create a list of simplified self types, if we can.
-        let mut simplified_steps = Vec::new();
-        for step in &steps {
-            match ty::fast_reject::simplify_type(self.tcx, step.self_ty, true) {
-                None => {
-                    break;
-                }
-                Some(simplified_type) => {
-                    simplified_steps.push(simplified_type);
-                }
-            }
-        }
-        let opt_simplified_steps = if simplified_steps.len() < steps.len() {
-            None // failed to convert at least one of the steps
-        } else {
-            Some(simplified_steps)
-        };
-
         debug!("ProbeContext: steps for self_ty={:?} are {:?}",
                self_ty,
                steps);
@@ -285,8 +259,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // that we create during the probe process are removed later
         self.probe(|_| {
             let mut probe_cx =
-                ProbeContext::new(self, span, mode, looking_for,
-                                  steps, opt_simplified_steps);
+                ProbeContext::new(self, span, mode, looking_for, steps);
 
             probe_cx.assemble_inherent_candidates();
             match scope {
@@ -357,8 +330,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
            span: Span,
            mode: Mode,
            looking_for: LookingFor<'tcx>,
-           steps: Vec<CandidateStep<'tcx>>,
-           opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
+           steps: Vec<CandidateStep<'tcx>>)
            -> ProbeContext<'a, 'gcx, 'tcx> {
         ProbeContext {
             fcx,
@@ -369,7 +341,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             extension_candidates: Vec::new(),
             impl_dups: FxHashSet(),
             steps: Rc::new(steps),
-            opt_simplified_steps,
             static_candidates: Vec::new(),
             private_candidate: None,
             unsatisfied_predicates: Vec::new(),
@@ -710,6 +681,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                                                -> Result<(), MethodError<'tcx>> {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
                trait_def_id);
+        let trait_substs = self.fresh_item_substs(trait_def_id);
+        let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
 
         for item in self.impl_or_trait_item(trait_def_id) {
             // Check whether `trait_def_id` defines a method with suitable name:
@@ -719,317 +692,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 continue;
             }
 
-            self.assemble_builtin_candidates(import_id, trait_def_id, item.clone());
-
-            self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id,
-                                                               item.clone());
-
-            self.assemble_closure_candidates(import_id, trait_def_id, item.clone())?;
-
-            self.assemble_generator_candidates(import_id, trait_def_id, item.clone())?;
-
-            self.assemble_projection_candidates(import_id, trait_def_id, item.clone());
-
-            self.assemble_where_clause_candidates(import_id, trait_def_id, item.clone());
-        }
-
-        Ok(())
-    }
-
-    fn assemble_builtin_candidates(&mut self,
-                                   import_id: Option<ast::NodeId>,
-                                   trait_def_id: DefId,
-                                   item: ty::AssociatedItem) {
-        if Some(trait_def_id) == self.tcx.lang_items.clone_trait() {
-            self.assemble_builtin_clone_candidates(import_id, trait_def_id, item);
-        }
-    }
-
-    fn assemble_builtin_clone_candidates(&mut self,
-                                         import_id: Option<ast::NodeId>,
-                                         trait_def_id: DefId,
-                                         item: ty::AssociatedItem) {
-        for step in Rc::clone(&self.steps).iter() {
-            match step.self_ty.sty {
-                ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
-                ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
-                ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
-                ty::TyRawPtr(..) | ty::TyError | ty::TyNever |
-                ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) |
-                ty::TyArray(..) | ty::TyTuple(..) => {
-                    ()
-                }
-
-                _ => continue,
-            };
-
-            let substs = Substs::for_item(self.tcx,
-                                          trait_def_id,
-                                          |def, _| self.region_var_for_def(self.span, def),
-                                          |def, substs| {
-                if def.index == 0 {
-                    step.self_ty
-                } else {
-                    self.type_var_for_def(self.span, def, substs)
-                }
-            });
-
-            let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
-            self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id);
-        }
-    }
-
-    fn assemble_extension_candidates_for_trait_impls(&mut self,
-                                                     import_id: Option<ast::NodeId>,
-                                                     trait_def_id: DefId,
-                                                     item: ty::AssociatedItem) {
-        // FIXME(arielb1): can we use for_each_relevant_impl here?
-        self.tcx.for_each_impl(trait_def_id, |impl_def_id| {
-            debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \
-                                                                  impl_def_id={:?}",
-                   trait_def_id,
-                   impl_def_id);
-
-            if !self.impl_can_possibly_match(impl_def_id) {
-                return;
-            }
-
-            let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
-
-            debug!("impl_substs={:?}", impl_substs);
-
-            let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id)
-                .unwrap() // we know this is a trait impl
-                .subst(self.tcx, impl_substs);
-
-            debug!("impl_trait_ref={:?}", impl_trait_ref);
-
-            // Determine the receiver type that the method itself expects.
-            let xform_self_ty =
-                self.xform_self_ty(&item, impl_trait_ref.self_ty(), impl_trait_ref.substs);
-
-            // Normalize the receiver. We can't use normalize_associated_types_in
-            // as it will pollute the fcx's fulfillment context after this probe
-            // is over.
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
-            let selcx = &mut traits::SelectionContext::new(self.fcx);
-            let traits::Normalized { value: xform_self_ty, obligations } =
-                traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
-
-            debug!("xform_self_ty={:?}", xform_self_ty);
-
+            let xform_self_ty = self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
             self.push_extension_candidate(xform_self_ty, item,
-                        ExtensionImplCandidate(impl_def_id, impl_substs, obligations), import_id);
-        });
-    }
-
-    fn impl_can_possibly_match(&self, impl_def_id: DefId) -> bool {
-        let simplified_steps = match self.opt_simplified_steps {
-            Some(ref simplified_steps) => simplified_steps,
-            None => {
-                return true;
-            }
-        };
-
-        let impl_type = self.tcx.type_of(impl_def_id);
-        let impl_simplified_type =
-            match ty::fast_reject::simplify_type(self.tcx, impl_type, false) {
-                Some(simplified_type) => simplified_type,
-                None => {
-                    return true;
-                }
-            };
-
-        simplified_steps.contains(&impl_simplified_type)
-    }
-
-    fn assemble_closure_candidates(&mut self,
-                                   import_id: Option<ast::NodeId>,
-                                   trait_def_id: DefId,
-                                   item: ty::AssociatedItem)
-                                   -> Result<(), MethodError<'tcx>> {
-        // Check if this is one of the Fn,FnMut,FnOnce traits.
-        let tcx = self.tcx;
-        let kind = if Some(trait_def_id) == tcx.lang_items.fn_trait() {
-            ty::ClosureKind::Fn
-        } else if Some(trait_def_id) == tcx.lang_items.fn_mut_trait() {
-            ty::ClosureKind::FnMut
-        } else if Some(trait_def_id) == tcx.lang_items.fn_once_trait() {
-            ty::ClosureKind::FnOnce
-        } else {
-            return Ok(());
-        };
-
-        // Check if there is an unboxed-closure self-type in the list of receivers.
-        // If so, add "synthetic impls".
-        let steps = self.steps.clone();
-        for step in steps.iter() {
-            let closure_id = match step.self_ty.sty {
-                ty::TyClosure(def_id, _) => {
-                    if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                        self.tcx.hir.node_to_hir_id(id)
-                    } else {
-                        continue;
-                    }
-                }
-                _ => continue,
-            };
-
-            let closure_kind = {
-                match self.tables.borrow().closure_kinds().get(closure_id) {
-                    Some(&(k, _)) => k,
-                    None => {
-                        return Err(MethodError::ClosureAmbiguity(trait_def_id));
-                    }
-                }
-            };
-
-            // this closure doesn't implement the right kind of `Fn` trait
-            if !closure_kind.extends(kind) {
-                continue;
-            }
-
-            // create some substitutions for the argument/return type;
-            // for the purposes of our method lookup, we only take
-            // receiver type into account, so we can just substitute
-            // fresh types here to use during substitution and subtyping.
-            let substs = Substs::for_item(self.tcx,
-                                          trait_def_id,
-                                          |def, _| self.region_var_for_def(self.span, def),
-                                          |def, substs| {
-                if def.index == 0 {
-                    step.self_ty
-                } else {
-                    self.type_var_for_def(self.span, def, substs)
-                }
-            });
-
-            let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
-            self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id);
+                                          TraitCandidate(trait_ref),
+                                          import_id);
         }
-
         Ok(())
     }
 
-    fn assemble_generator_candidates(&mut self,
-                                   import_id: Option<ast::NodeId>,
-                                   trait_def_id: DefId,
-                                   item: ty::AssociatedItem)
-                                   -> Result<(), MethodError<'tcx>> {
-        // Check if this is the Generator trait.
-        let tcx = self.tcx;
-        if Some(trait_def_id) != tcx.lang_items.gen_trait() {
-            return Ok(());
-        }
-
-        // Check if there is an generator self-type in the list of receivers.
-        // If so, add "synthetic impls".
-        let steps = self.steps.clone();
-        for step in steps.iter() {
-            match step.self_ty.sty {
-                ty::TyGenerator(..) => (),
-                _ => continue,
-            };
-
-            // create some substitutions for the argument/return type;
-            // for the purposes of our method lookup, we only take
-            // receiver type into account, so we can just substitute
-            // fresh types here to use during substitution and subtyping.
-            let substs = Substs::for_item(self.tcx,
-                                          trait_def_id,
-                                          |def, _| self.region_var_for_def(self.span, def),
-                                          |def, substs| {
-                if def.index == 0 {
-                    step.self_ty
-                } else {
-                    self.type_var_for_def(self.span, def, substs)
-                }
-            });
-
-            let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
-            self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id);
-        }
-
-        Ok(())
-    }
-
-    fn assemble_projection_candidates(&mut self,
-                                      import_id: Option<ast::NodeId>,
-                                      trait_def_id: DefId,
-                                      item: ty::AssociatedItem) {
-        debug!("assemble_projection_candidates(\
-               trait_def_id={:?}, \
-               item={:?})",
-               trait_def_id,
-               item);
-
-        for step in Rc::clone(&self.steps).iter() {
-            debug!("assemble_projection_candidates: step={:?}", step);
-
-            let (def_id, substs) = match step.self_ty.sty {
-                ty::TyProjection(ref data) => {
-                    let trait_ref = data.trait_ref(self.tcx);
-                    (trait_ref.def_id, trait_ref.substs)
-                },
-                ty::TyAnon(def_id, substs) => (def_id, substs),
-                _ => continue,
-            };
-
-            debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
-                   def_id,
-                   substs);
-
-            let trait_predicates = self.tcx.predicates_of(def_id);
-            let bounds = trait_predicates.instantiate(self.tcx, substs);
-            let predicates = bounds.predicates;
-            debug!("assemble_projection_candidates: predicates={:?}",
-                   predicates);
-            for poly_bound in traits::elaborate_predicates(self.tcx, predicates)
-                .filter_map(|p| p.to_opt_poly_trait_ref())
-                .filter(|b| b.def_id() == trait_def_id) {
-                let bound = self.erase_late_bound_regions(&poly_bound);
-
-                debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
-                       def_id,
-                       substs,
-                       bound);
-
-                if self.can_eq(self.param_env, step.self_ty, bound.self_ty()).is_ok() {
-                    let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
-
-                    debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
-                           bound,
-                           xform_self_ty);
-
-                    self.push_extension_candidate(xform_self_ty, item, TraitCandidate, import_id);
-                }
-            }
-        }
-    }
-
-    fn assemble_where_clause_candidates(&mut self,
-                                        import_id: Option<ast::NodeId>,
-                                        trait_def_id: DefId,
-                                        item: ty::AssociatedItem) {
-        debug!("assemble_where_clause_candidates(trait_def_id={:?})",
-               trait_def_id);
-
-        let caller_predicates = self.param_env.caller_bounds.to_vec();
-        for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
-            .filter_map(|p| p.to_opt_poly_trait_ref())
-            .filter(|b| b.def_id() == trait_def_id) {
-            let bound = self.erase_late_bound_regions(&poly_bound);
-            let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
-
-            debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}",
-                   bound,
-                   xform_self_ty);
-
-            self.push_extension_candidate(xform_self_ty, item,
-                                          WhereClauseCandidate(poly_bound), import_id);
-        }
-    }
-
     fn candidate_method_names(&self) -> Vec<ast::Name> {
         let mut set = FxHashSet();
         let mut names: Vec<_> =
@@ -1095,10 +765,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 assert!(others.is_empty());
                 vec![]
             }
-            Some(Err(MethodError::ClosureAmbiguity(..))) => {
-                // this error only occurs when assembling candidates
-                span_bug!(span, "encountered ClosureAmbiguity from pick_core");
-            }
             _ => vec![],
         };
 
@@ -1226,13 +892,49 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         }
 
         if applicable_candidates.len() > 1 {
-            let sources = probes.iter().map(|p| p.to_source()).collect();
+            let sources = probes.iter()
+                .map(|p| self.candidate_source(p, self_ty))
+                .collect();
             return Some(Err(MethodError::Ambiguity(sources)));
         }
 
         applicable_candidates.pop().map(|probe| Ok(probe.to_unadjusted_pick()))
     }
 
+    fn select_trait_candidate(&self, trait_ref: ty::TraitRef<'tcx>)
+                              -> traits::SelectionResult<'tcx, traits::Selection<'tcx>>
+    {
+        let cause = traits::ObligationCause::misc(self.span, self.body_id);
+        let predicate =
+            trait_ref.to_poly_trait_ref().to_poly_trait_predicate();
+        let obligation = traits::Obligation::new(cause, self.param_env, predicate);
+        traits::SelectionContext::new(self).select(&obligation)
+    }
+
+    fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>)
+                        -> CandidateSource
+    {
+        match candidate.kind {
+            InherentImplCandidate(..) => ImplSource(candidate.item.container.id()),
+            ObjectCandidate |
+            WhereClauseCandidate(_) => TraitSource(candidate.item.container.id()),
+            TraitCandidate(trait_ref) => self.probe(|_| {
+                let _ = self.at(&ObligationCause::dummy(), self.param_env)
+                    .sup(candidate.xform_self_ty, self_ty);
+                match self.select_trait_candidate(trait_ref) {
+                    Ok(Some(traits::Vtable::VtableImpl(ref impl_data))) => {
+                        // If only a single impl matches, make the error message point
+                        // to that impl.
+                        ImplSource(impl_data.impl_def_id)
+                    }
+                    _ => {
+                        TraitSource(candidate.item.container.id())
+                    }
+                }
+            })
+        }
+    }
+
     fn consider_probe(&self,
                       self_ty: Ty<'tcx>,
                       probe: &Candidate<'tcx>,
@@ -1251,56 +953,80 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 }
             };
 
+            let mut successful = true;
+            let selcx = &mut traits::SelectionContext::new(self);
+            let cause = traits::ObligationCause::misc(self.span, self.body_id);
+
             // If so, impls may carry other conditions (e.g., where
             // clauses) that must be considered. Make sure that those
             // match as well (or at least may match, sometimes we
             // don't have enough information to fully evaluate).
-            let (impl_def_id, substs, ref_obligations) = match probe.kind {
+            let candidate_obligations : Vec<_> = match probe.kind {
                 InherentImplCandidate(ref substs, ref ref_obligations) => {
-                    (probe.item.container.id(), substs, ref_obligations)
-                }
-
-                ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => {
-                    (impl_def_id, substs, ref_obligations)
+                    // Check whether the impl imposes obligations we have to worry about.
+                    let impl_def_id = probe.item.container.id();
+                    let impl_bounds = self.tcx.predicates_of(impl_def_id);
+                    let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
+                    let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
+                        traits::normalize(selcx, self.param_env, cause.clone(), &impl_bounds);
+
+                    // Convert the bounds into obligations.
+                    let impl_obligations = traits::predicates_for_generics(
+                        cause.clone(), self.param_env, &impl_bounds);
+
+                    debug!("impl_obligations={:?}", impl_obligations);
+                    impl_obligations.into_iter()
+                        .chain(norm_obligations.into_iter())
+                        .chain(ref_obligations.iter().cloned())
+                        .collect()
                 }
 
                 ObjectCandidate |
-                TraitCandidate |
                 WhereClauseCandidate(..) => {
                     // These have no additional conditions to check.
-                    return true;
+                    vec![]
                 }
-            };
 
-            let selcx = &mut traits::SelectionContext::new(self);
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
-
-            // Check whether the impl imposes obligations we have to worry about.
-            let impl_bounds = self.tcx.predicates_of(impl_def_id);
-            let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
-            let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
-                traits::normalize(selcx, self.param_env, cause.clone(), &impl_bounds);
+                TraitCandidate(trait_ref) => {
+                    let predicate = trait_ref.to_predicate();
+                    let obligation =
+                        traits::Obligation::new(cause.clone(), self.param_env, predicate);
+                    if !selcx.evaluate_obligation(&obligation) {
+                        if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
+                            // This candidate's primary obligation doesn't even
+                            // select - don't bother registering anything in
+                            // `potentially_unsatisfied_predicates`.
+                            return false
+                        } else {
+                            // Some nested subobligation of this predicate
+                            // failed.
+                            //
+                            // FIXME: try to find the exact nested subobligation
+                            // and point at it rather than reporting the entire
+                            // trait-ref?
+                            successful = false;
+                            let trait_ref = self.resolve_type_vars_if_possible(&trait_ref);
+                            possibly_unsatisfied_predicates.push(trait_ref);
+                        }
+                    }
+                    vec![]
+                }
+            };
 
-            // Convert the bounds into obligations.
-            let obligations = traits::predicates_for_generics(cause.clone(),
-                                                              self.param_env,
-                                                              &impl_bounds);
-            debug!("impl_obligations={:?}", obligations);
+            debug!("consider_probe - candidate_obligations={:?} sub_obligations={:?}",
+                   candidate_obligations, sub_obligations);
 
             // Evaluate those obligations to see if they might possibly hold.
-            let mut all_true = true;
-            for o in obligations.iter()
-                .chain(sub_obligations.iter())
-                .chain(norm_obligations.iter())
-                .chain(ref_obligations.iter()) {
-                if !selcx.evaluate_obligation(o) {
-                    all_true = false;
+            for o in candidate_obligations.into_iter().chain(sub_obligations) {
+                let o = self.resolve_type_vars_if_possible(&o);
+                if !selcx.evaluate_obligation(&o) {
+                    successful = false;
                     if let &ty::Predicate::Trait(ref pred) = &o.predicate {
                         possibly_unsatisfied_predicates.push(pred.0.trait_ref);
                     }
                 }
             }
-            all_true
+            successful
         })
     }
 
@@ -1434,16 +1160,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
 
     /// Get the type of an impl and generate substitutions with placeholders.
     fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) {
-        let impl_ty = self.tcx.type_of(impl_def_id);
-
-        let substs = Substs::for_item(self.tcx,
-                                      impl_def_id,
-                                      |_, _| self.tcx.types.re_erased,
-                                      |_, _| self.next_ty_var(
-                                        TypeVariableOrigin::SubstitutionPlaceholder(
-                                            self.tcx.def_span(impl_def_id))));
+        (self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
+    }
 
-        (impl_ty, substs)
+    fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
+        Substs::for_item(self.tcx,
+                         def_id,
+                         |_, _| self.tcx.types.re_erased,
+                         |_, _| self.next_ty_var(
+                             TypeVariableOrigin::SubstitutionPlaceholder(
+                                 self.tcx.def_span(def_id))))
     }
 
     /// Replace late-bound-regions bound by `value` with `'static` using
@@ -1493,9 +1219,8 @@ impl<'tcx> Candidate<'tcx> {
             item: self.item.clone(),
             kind: match self.kind {
                 InherentImplCandidate(..) => InherentImplPick,
-                ExtensionImplCandidate(def_id, ..) => ExtensionImplPick(def_id),
                 ObjectCandidate => ObjectPick,
-                TraitCandidate => TraitPick,
+                TraitCandidate(_) => TraitPick,
                 WhereClauseCandidate(ref trait_ref) => {
                     // Only trait derived from where-clauses should
                     // appear here, so they should not contain any
@@ -1513,14 +1238,4 @@ impl<'tcx> Candidate<'tcx> {
             unsize: None,
         }
     }
-
-    fn to_source(&self) -> CandidateSource {
-        match self.kind {
-            InherentImplCandidate(..) => ImplSource(self.item.container.id()),
-            ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
-            ObjectCandidate |
-            TraitCandidate |
-            WhereClauseCandidate(_) => TraitSource(self.item.container.id()),
-        }
-    }
 }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index c8b828f3a43..9079ba4a893 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -296,22 +296,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 err.emit();
             }
 
-            MethodError::ClosureAmbiguity(trait_def_id) => {
-                let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
-                                   invoked on this closure as we have not yet inferred what \
-                                   kind of closure it is",
-                                  item_name,
-                                  self.tcx.item_path_str(trait_def_id));
-                let msg = if let Some(callee) = rcvr_expr {
-                    format!("{}; use overloaded call notation instead (e.g., `{}()`)",
-                            msg,
-                            self.tcx.hir.node_to_pretty_string(callee.id))
-                } else {
-                    msg
-                };
-                self.sess().span_err(span, &msg);
-            }
-
             MethodError::PrivateMatch(def, out_of_scope_traits) => {
                 let mut err = struct_span_err!(self.tcx.sess, span, E0624,
                                                "{} `{}` is private", def.kind_name(), item_name);
diff --git a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs b/src/test/run-pass/unboxed-closures-infer-explicit-call-early.rs
index 62f6ee56ca5..028f2e9375b 100644
--- a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
+++ b/src/test/run-pass/unboxed-closures-infer-explicit-call-early.rs
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(fn_traits)]
+
 fn main() {
-    let mut zero = || {};
-    let () = zero.call_mut(());
-    //~^ ERROR we have not yet inferred what kind of closure it is
+    let mut zero = || 0;
+    let x = zero.call_mut(());
+    assert_eq!(x, 0);
 }
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index fc441f94842..23f115858cd 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -8,6 +8,8 @@ error[E0599]: no method named `method` found for type `u32` in the current scope
    = note: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
            candidate #1: `use foo::Bar;`
            candidate #2: `use no_method_suggested_traits::foo::PubPub;`
+           candidate #3: `use no_method_suggested_traits::qux::PrivPub;`
+           candidate #4: `use no_method_suggested_traits::Reexported;`
 
 error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:38:44
@@ -19,6 +21,8 @@ error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::box
    = note: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
            candidate #1: `use foo::Bar;`
            candidate #2: `use no_method_suggested_traits::foo::PubPub;`
+           candidate #3: `use no_method_suggested_traits::qux::PrivPub;`
+           candidate #4: `use no_method_suggested_traits::Reexported;`
 
 error[E0599]: no method named `method` found for type `char` in the current scope
   --> $DIR/no-method-suggested-traits.rs:44:9
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 174f7dfa0d0..e2e2019307f 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -5,8 +5,8 @@ error[E0599]: no method named `count` found for type `std::iter::Filter<std::ite
    |                                                       ^^^^^
    |
    = note: the method `count` exists but the following trait bounds were not satisfied:
-           `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`
            `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
+           `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
 
 error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
   --> $DIR/issue-36053-2.rs:17:32