@@ -56,7 +56,7 @@ use tracing::{debug, instrument};
5656use crate :: {
5757 Adjust , Adjustment , AutoBorrow , ParamEnvAndCrate , PointerCast , TargetFeatures ,
5858 autoderef:: Autoderef ,
59- db:: { HirDatabase , InternedClosureId } ,
59+ db:: { HirDatabase , InternedClosure , InternedClosureId } ,
6060 infer:: {
6161 AllowTwoPhase , AutoBorrowMutability , InferenceContext , TypeMismatch , expr:: ExprIsRead ,
6262 } ,
@@ -74,6 +74,7 @@ use crate::{
7474 } ,
7575 obligation_ctxt:: ObligationCtxt ,
7676 } ,
77+ upvars:: upvars_mentioned,
7778 utils:: TargetFeatureIsSafeInTarget ,
7879} ;
7980
@@ -896,27 +897,15 @@ where
896897 fn coerce_closure_to_fn (
897898 & mut self ,
898899 a : Ty < ' db > ,
899- _closure_def_id_a : InternedClosureId ,
900+ closure_def_id_a : InternedClosureId ,
900901 args_a : GenericArgs < ' db > ,
901902 b : Ty < ' db > ,
902903 ) -> CoerceResult < ' db > {
903904 debug_assert ! ( self . infcx( ) . shallow_resolve( a) == a) ;
904905 debug_assert ! ( self . infcx( ) . shallow_resolve( b) == b) ;
905906
906907 match b. kind ( ) {
907- // FIXME: We need to have an `upvars_mentioned()` query:
908- // At this point we haven't done capture analysis, which means
909- // that the ClosureArgs just contains an inference variable instead
910- // of tuple of captured types.
911- //
912- // All we care here is if any variable is being captured and not the exact paths,
913- // so we check `upvars_mentioned` for root variables being captured.
914- TyKind :: FnPtr ( _, hdr) =>
915- // if self
916- // .db
917- // .upvars_mentioned(closure_def_id_a.expect_local())
918- // .is_none_or(|u| u.is_empty()) =>
919- {
908+ TyKind :: FnPtr ( _, hdr) if !is_capturing_closure ( self . db ( ) , closure_def_id_a) => {
920909 // We coerce the closure, which has fn type
921910 // `extern "rust-call" fn((arg0,arg1,...)) -> _`
922911 // to
@@ -1089,14 +1078,12 @@ impl<'db> InferenceContext<'_, 'db> {
10891078 // Special-case that coercion alone cannot handle:
10901079 // Function items or non-capturing closures of differing IDs or GenericArgs.
10911080 let ( a_sig, b_sig) = {
1092- let is_capturing_closure = |_ty : Ty < ' db > | {
1093- // FIXME:
1094- // if let TyKind::Closure(closure_def_id, _args) = ty.kind() {
1095- // self.db.upvars_mentioned(closure_def_id.expect_local()).is_some()
1096- // } else {
1097- // false
1098- // }
1099- false
1081+ let is_capturing_closure = |ty : Ty < ' db > | {
1082+ if let TyKind :: Closure ( closure_def_id, _args) = ty. kind ( ) {
1083+ is_capturing_closure ( self . db , closure_def_id. 0 )
1084+ } else {
1085+ false
1086+ }
11001087 } ;
11011088 if is_capturing_closure ( prev_ty) || is_capturing_closure ( new_ty) {
11021089 ( None , None )
@@ -1728,3 +1715,9 @@ fn coerce<'db>(
17281715 . collect ( ) ;
17291716 Ok ( ( adjustments, ty) )
17301717}
1718+
1719+ fn is_capturing_closure ( db : & dyn HirDatabase , closure : InternedClosureId ) -> bool {
1720+ let InternedClosure ( owner, expr) = closure. loc ( db) ;
1721+ upvars_mentioned ( db, owner)
1722+ . is_some_and ( |upvars| upvars. get ( & expr) . is_some_and ( |upvars| !upvars. is_empty ( ) ) )
1723+ }
0 commit comments