@@ -233,21 +233,78 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
233233 // is `Vec<Foo>:Iterable<Bar>`, but the impl specifies
234234 // `impl<T> Iterable<T> for Vec<T>`, than an error would result.
235235
236- /// Evaluates whether the obligation can be satisfied. Returns an indication of whether the
237- /// obligation can be satisfied and, if so, by what means. Never affects surrounding typing
238- /// environment.
236+ /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
237+ /// type environment by performing unification.
239238 pub fn select ( & mut self , obligation : & TraitObligation < ' tcx > )
240239 -> SelectionResult < ' tcx , Selection < ' tcx > > {
241240 debug ! ( "select({})" , obligation. repr( self . tcx( ) ) ) ;
242241 assert ! ( !obligation. predicate. has_escaping_regions( ) ) ;
243242
244243 let stack = self . push_stack ( None , obligation) ;
245244 match try!( self . candidate_from_obligation ( & stack) ) {
246- None => Ok ( None ) ,
245+ None => {
246+ self . consider_unification_despite_ambiguity ( obligation) ;
247+ Ok ( None )
248+ }
247249 Some ( candidate) => Ok ( Some ( try!( self . confirm_candidate ( obligation, candidate) ) ) ) ,
248250 }
249251 }
250252
253+ /// In the particular case of unboxed closure obligations, we can
254+ /// sometimes do some amount of unification for the
255+ /// argument/return types even though we can't yet fully match obligation.
256+ /// The particular case we are interesting in is an obligation of the form:
257+ ///
258+ /// C : FnFoo<A>
259+ ///
260+ /// where `C` is an unboxed closure type and `FnFoo` is one of the
261+ /// `Fn` traits. Because we know that users cannot write impls for closure types
262+ /// themselves, the only way that `C : FnFoo` can fail to match is under two
263+ /// conditions:
264+ ///
265+ /// 1. The closure kind for `C` is not yet known, because inference isn't complete.
266+ /// 2. The closure kind for `C` *is* known, but doesn't match what is needed.
267+ /// For example, `C` may be a `FnOnce` closure, but a `Fn` closure is needed.
268+ ///
269+ /// In either case, we always know what argument types are
270+ /// expected by `C`, no matter what kind of `Fn` trait it
271+ /// eventually matches. So we can go ahead and unify the argument
272+ /// types, even though the end result is ambiguous.
273+ ///
274+ /// Note that this is safe *even if* the trait would never be
275+ /// matched (case 2 above). After all, in that case, an error will
276+ /// result, so it kind of doesn't matter what we do --- unifying
277+ /// the argument types can only be helpful to the user, because
278+ /// once they patch up the kind of closure that is expected, the
279+ /// argment types won't really change.
280+ fn consider_unification_despite_ambiguity ( & mut self , obligation : & TraitObligation < ' tcx > )
281+ {
282+ // Is this a `C : FnFoo(...)` trait reference for some trait binding `FnFoo`?
283+ match self . tcx ( ) . lang_items . fn_trait_kind ( obligation. predicate . 0 . def_id ( ) ) {
284+ Some ( _) => { }
285+ None => { return ; }
286+ }
287+
288+ // Is the self-type a closure type? We ignore bindings here
289+ // because if it is a closure type, it must be a closure type from
290+ // within this current fn, and hence none of the higher-ranked
291+ // lifetimes can appear inside the self-type.
292+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
293+ let ( closure_def_id, substs) = match self_ty. sty {
294+ ty:: ty_closure( id, _, ref substs) => ( id, substs. clone ( ) ) ,
295+ _ => { return ; }
296+ } ;
297+ assert ! ( !substs. has_escaping_regions( ) ) ;
298+
299+ let closure_trait_ref = self . closure_trait_ref ( obligation, closure_def_id, substs) ;
300+ match self . confirm_poly_trait_refs ( obligation. cause . clone ( ) ,
301+ obligation. predicate . to_poly_trait_ref ( ) ,
302+ closure_trait_ref) {
303+ Ok ( ( ) ) => { }
304+ Err ( _) => { /* Silently ignore errors. */ }
305+ }
306+ }
307+
251308 ///////////////////////////////////////////////////////////////////////////
252309 // EVALUATION
253310 //
@@ -1003,7 +1060,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10031060 candidates : & mut SelectionCandidateSet < ' tcx > )
10041061 -> Result < ( ) , SelectionError < ' tcx > >
10051062 {
1006- let kind = match self . fn_family_trait_kind ( obligation. predicate . 0 . def_id ( ) ) {
1063+ let kind = match self . tcx ( ) . lang_items . fn_trait_kind ( obligation. predicate . 0 . def_id ( ) ) {
10071064 Some ( k) => k,
10081065 None => { return Ok ( ( ) ) ; }
10091066 } ;
@@ -2303,22 +2360,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
23032360 impl_obligations
23042361 }
23052362
2306- fn fn_family_trait_kind ( & self ,
2307- trait_def_id : ast:: DefId )
2308- -> Option < ty:: ClosureKind >
2309- {
2310- let tcx = self . tcx ( ) ;
2311- if Some ( trait_def_id) == tcx. lang_items . fn_trait ( ) {
2312- Some ( ty:: FnClosureKind )
2313- } else if Some ( trait_def_id) == tcx. lang_items . fn_mut_trait ( ) {
2314- Some ( ty:: FnMutClosureKind )
2315- } else if Some ( trait_def_id) == tcx. lang_items . fn_once_trait ( ) {
2316- Some ( ty:: FnOnceClosureKind )
2317- } else {
2318- None
2319- }
2320- }
2321-
23222363 #[ allow( unused_comparisons) ]
23232364 fn derived_cause ( & self ,
23242365 obligation : & TraitObligation < ' tcx > ,
0 commit comments