@@ -233,21 +233,78 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
233
233
// is `Vec<Foo>:Iterable<Bar>`, but the impl specifies
234
234
// `impl<T> Iterable<T> for Vec<T>`, than an error would result.
235
235
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.
239
238
pub fn select ( & mut self , obligation : & TraitObligation < ' tcx > )
240
239
-> SelectionResult < ' tcx , Selection < ' tcx > > {
241
240
debug ! ( "select({})" , obligation. repr( self . tcx( ) ) ) ;
242
241
assert ! ( !obligation. predicate. has_escaping_regions( ) ) ;
243
242
244
243
let stack = self . push_stack ( None , obligation) ;
245
244
match try!( self . candidate_from_obligation ( & stack) ) {
246
- None => Ok ( None ) ,
245
+ None => {
246
+ self . consider_unification_despite_ambiguity ( obligation) ;
247
+ Ok ( None )
248
+ }
247
249
Some ( candidate) => Ok ( Some ( try!( self . confirm_candidate ( obligation, candidate) ) ) ) ,
248
250
}
249
251
}
250
252
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
+
251
308
///////////////////////////////////////////////////////////////////////////
252
309
// EVALUATION
253
310
//
@@ -1003,7 +1060,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1003
1060
candidates : & mut SelectionCandidateSet < ' tcx > )
1004
1061
-> Result < ( ) , SelectionError < ' tcx > >
1005
1062
{
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 ( ) ) {
1007
1064
Some ( k) => k,
1008
1065
None => { return Ok ( ( ) ) ; }
1009
1066
} ;
@@ -2303,22 +2360,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2303
2360
impl_obligations
2304
2361
}
2305
2362
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
-
2322
2363
#[ allow( unused_comparisons) ]
2323
2364
fn derived_cause ( & self ,
2324
2365
obligation : & TraitObligation < ' tcx > ,
0 commit comments