@@ -39,6 +39,7 @@ use crate::astconv::AstConv;
39
39
use crate :: check:: FnCtxt ;
40
40
use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
41
41
use rustc_hir as hir;
42
+ use rustc_hir:: def_id:: DefId ;
42
43
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
43
44
use rustc_infer:: infer:: { Coercion , InferOk , InferResult } ;
44
45
use rustc_middle:: ty:: adjustment:: {
@@ -221,11 +222,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
221
222
// unsafe qualifier.
222
223
self . coerce_from_fn_pointer ( a, a_f, b)
223
224
}
224
- ty:: Closure ( _ , substs_a) => {
225
+ ty:: Closure ( closure_def_id_a , substs_a) => {
225
226
// Non-capturing closures are coercible to
226
227
// function pointers or unsafe function pointers.
227
228
// It cannot convert closures that require unsafe.
228
- self . coerce_closure_to_fn ( a, substs_a, b)
229
+ self . coerce_closure_to_fn ( a, closure_def_id_a , substs_a, b)
229
230
}
230
231
_ => {
231
232
// Otherwise, just use unification rules.
@@ -762,6 +763,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
762
763
fn coerce_closure_to_fn (
763
764
& self ,
764
765
a : Ty < ' tcx > ,
766
+ closure_def_id_a : DefId ,
765
767
substs_a : SubstsRef < ' tcx > ,
766
768
b : Ty < ' tcx > ,
767
769
) -> CoerceResult < ' tcx > {
@@ -772,7 +774,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
772
774
let b = self . shallow_resolve ( b) ;
773
775
774
776
match b. kind ( ) {
775
- ty:: FnPtr ( fn_ty) if substs_a. as_closure ( ) . upvar_tys ( ) . next ( ) . is_none ( ) => {
777
+ // At this point we haven't done capture analysis, which means
778
+ // that the ClosureSubsts just contains an inference variable instead
779
+ // of tuple of captured types.
780
+ //
781
+ // All we care here is if any variable is being captured and not the exact paths,
782
+ // so we check `upvars_mentioned` for root variables being captured.
783
+ ty:: FnPtr ( fn_ty)
784
+ if self
785
+ . tcx
786
+ . upvars_mentioned ( closure_def_id_a. expect_local ( ) )
787
+ . map_or ( true , |u| u. is_empty ( ) ) =>
788
+ {
776
789
// We coerce the closure, which has fn type
777
790
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
778
791
// to
@@ -906,8 +919,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
906
919
// Function items or non-capturing closures of differing IDs or InternalSubsts.
907
920
let ( a_sig, b_sig) = {
908
921
let is_capturing_closure = |ty| {
909
- if let & ty:: Closure ( _ , substs ) = ty {
910
- substs . as_closure ( ) . upvar_tys ( ) . next ( ) . is_some ( )
922
+ if let & ty:: Closure ( closure_def_id , _substs ) = ty {
923
+ self . tcx . upvars_mentioned ( closure_def_id . expect_local ( ) ) . is_some ( )
911
924
} else {
912
925
false
913
926
}
0 commit comments