@@ -400,39 +400,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
400
400
}
401
401
}
402
402
ty:: CoroutineClosure ( def_id, args) => {
403
+ let args = args. as_coroutine_closure ( ) ;
403
404
let is_const = self . tcx ( ) . is_const_fn_raw ( def_id) ;
404
- match self . infcx . closure_kind ( self_ty) {
405
- Some ( closure_kind) => {
406
- let no_borrows = match self
407
- . infcx
408
- . shallow_resolve ( args. as_coroutine_closure ( ) . tupled_upvars_ty ( ) )
409
- . kind ( )
410
- {
411
- ty:: Tuple ( tys) => tys. is_empty ( ) ,
412
- ty:: Error ( _) => false ,
413
- _ => bug ! ( "tuple_fields called on non-tuple" ) ,
414
- } ;
415
- // A coroutine-closure implements `FnOnce` *always*, since it may
416
- // always be called once. It additionally implements `Fn`/`FnMut`
417
- // only if it has no upvars (therefore no borrows from the closure
418
- // that would need to be represented with a lifetime) and if the
419
- // closure kind permits it.
420
- // FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
421
- // if it takes all of its upvars by copy, and none by ref. This would
422
- // require us to record a bit more information during upvar analysis.
423
- if no_borrows && closure_kind. extends ( kind) {
424
- candidates. vec . push ( ClosureCandidate { is_const } ) ;
425
- } else if kind == ty:: ClosureKind :: FnOnce {
426
- candidates. vec . push ( ClosureCandidate { is_const } ) ;
427
- }
405
+ if let Some ( closure_kind) = self . infcx . closure_kind ( self_ty)
406
+ // Ambiguity if upvars haven't been constrained yet
407
+ && !args. tupled_upvars_ty ( ) . is_ty_var ( )
408
+ {
409
+ let no_borrows = match args. tupled_upvars_ty ( ) . kind ( ) {
410
+ ty:: Tuple ( tys) => tys. is_empty ( ) ,
411
+ ty:: Error ( _) => false ,
412
+ _ => bug ! ( "tuple_fields called on non-tuple" ) ,
413
+ } ;
414
+ // A coroutine-closure implements `FnOnce` *always*, since it may
415
+ // always be called once. It additionally implements `Fn`/`FnMut`
416
+ // only if it has no upvars (therefore no borrows from the closure
417
+ // that would need to be represented with a lifetime) and if the
418
+ // closure kind permits it.
419
+ // FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
420
+ // if it takes all of its upvars by copy, and none by ref. This would
421
+ // require us to record a bit more information during upvar analysis.
422
+ if no_borrows && closure_kind. extends ( kind) {
423
+ candidates. vec . push ( ClosureCandidate { is_const } ) ;
424
+ } else if kind == ty:: ClosureKind :: FnOnce {
425
+ candidates. vec . push ( ClosureCandidate { is_const } ) ;
428
426
}
429
- None => {
430
- if kind == ty:: ClosureKind :: FnOnce {
431
- candidates. vec . push ( ClosureCandidate { is_const } ) ;
432
- } else {
433
- // This stays ambiguous until kind+upvars are determined.
434
- candidates. ambiguous = true ;
435
- }
427
+ } else {
428
+ if kind == ty:: ClosureKind :: FnOnce {
429
+ candidates. vec . push ( ClosureCandidate { is_const } ) ;
430
+ } else {
431
+ // This stays ambiguous until kind+upvars are determined.
432
+ candidates. ambiguous = true ;
436
433
}
437
434
}
438
435
}
0 commit comments